Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

ASoC: cs42xx8: Add codec driver support for CS42448/CS42888

This patch adds support for the Cirrus Logic CS42448/CS42888 Audio CODEC that
has six/four 24-bit AD and eight 24-bit DA converters.

[ CS42448/CS42888 supports both I2C and SPI control ports. As initial patch,
this patch only adds the support for I2C. ]

Signed-off-by: Nicolin Chen <Guangyu.Chen@freescale.com>
Acked-by: Brian Austin <brian.austin@cirrus.com>
Acked-by: Paul Handrigan <Paul.Handrigan@cirrus.com>
Signed-off-by: Mark Brown <broonie@linaro.org>

authored by

Nicolin Chen and committed by
Mark Brown
0c516b4f 38dbfb59

+946
+28
Documentation/devicetree/bindings/sound/cs42xx8.txt
··· 1 + CS42448/CS42888 audio CODEC 2 + 3 + Required properties: 4 + 5 + - compatible : must contain one of "cirrus,cs42448" and "cirrus,cs42888" 6 + 7 + - reg : the I2C address of the device for I2C 8 + 9 + - clocks : a list of phandles + clock-specifiers, one for each entry in 10 + clock-names 11 + 12 + - clock-names : must contain "mclk" 13 + 14 + - VA-supply, VD-supply, VLS-supply, VLC-supply: power supplies for the device, 15 + as covered in Documentation/devicetree/bindings/regulator/regulator.txt 16 + 17 + Example: 18 + 19 + codec: cs42888@48 { 20 + compatible = "cirrus,cs42888"; 21 + reg = <0x48>; 22 + clocks = <&codec_mclk 0>; 23 + clock-names = "mclk"; 24 + VA-supply = <&reg_audio>; 25 + VD-supply = <&reg_audio>; 26 + VLS-supply = <&reg_audio>; 27 + VLC-supply = <&reg_audio>; 28 + };
+10
sound/soc/codecs/Kconfig
··· 37 37 select SND_SOC_CS42L73 if I2C 38 38 select SND_SOC_CS4270 if I2C 39 39 select SND_SOC_CS4271 if SND_SOC_I2C_AND_SPI 40 + select SND_SOC_CS42XX8_I2C if I2C 40 41 select SND_SOC_CX20442 if TTY 41 42 select SND_SOC_DA7210 if I2C 42 43 select SND_SOC_DA7213 if I2C ··· 254 253 255 254 config SND_SOC_CS4271 256 255 tristate 256 + 257 + config SND_SOC_CS42XX8 258 + tristate 259 + 260 + config SND_SOC_CS42XX8_I2C 261 + tristate "Cirrus Logic CS42448/CS42888 CODEC (I2C)" 262 + depends on I2C 263 + select SND_SOC_CS42XX8 264 + select REGMAP_I2C 257 265 258 266 config SND_SOC_CX20442 259 267 tristate
+4
sound/soc/codecs/Makefile
··· 23 23 snd-soc-cs42l73-objs := cs42l73.o 24 24 snd-soc-cs4270-objs := cs4270.o 25 25 snd-soc-cs4271-objs := cs4271.o 26 + snd-soc-cs42xx8-objs := cs42xx8.o 27 + snd-soc-cs42xx8-i2c-objs := cs42xx8-i2c.o 26 28 snd-soc-cx20442-objs := cx20442.o 27 29 snd-soc-da7210-objs := da7210.o 28 30 snd-soc-da7213-objs := da7213.o ··· 158 156 obj-$(CONFIG_SND_SOC_CS42L73) += snd-soc-cs42l73.o 159 157 obj-$(CONFIG_SND_SOC_CS4270) += snd-soc-cs4270.o 160 158 obj-$(CONFIG_SND_SOC_CS4271) += snd-soc-cs4271.o 159 + obj-$(CONFIG_SND_SOC_CS42XX8) += snd-soc-cs42xx8.o 160 + obj-$(CONFIG_SND_SOC_CS42XX8_I2C) += snd-soc-cs42xx8-i2c.o 161 161 obj-$(CONFIG_SND_SOC_CX20442) += snd-soc-cx20442.o 162 162 obj-$(CONFIG_SND_SOC_DA7210) += snd-soc-da7210.o 163 163 obj-$(CONFIG_SND_SOC_DA7213) += snd-soc-da7213.o
+64
sound/soc/codecs/cs42xx8-i2c.c
··· 1 + /* 2 + * Cirrus Logic CS42448/CS42888 Audio CODEC DAI I2C driver 3 + * 4 + * Copyright (C) 2014 Freescale Semiconductor, Inc. 5 + * 6 + * Author: Nicolin Chen <Guangyu.Chen@freescale.com> 7 + * 8 + * This file is licensed under the terms of the GNU General Public License 9 + * version 2. This program is licensed "as is" without any warranty of any 10 + * kind, whether express or implied. 11 + */ 12 + 13 + #include <linux/i2c.h> 14 + #include <linux/module.h> 15 + #include <linux/pm_runtime.h> 16 + #include <sound/soc.h> 17 + 18 + #include "cs42xx8.h" 19 + 20 + static int cs42xx8_i2c_probe(struct i2c_client *i2c, 21 + const struct i2c_device_id *id) 22 + { 23 + u32 ret = cs42xx8_probe(&i2c->dev, 24 + devm_regmap_init_i2c(i2c, &cs42xx8_regmap_config)); 25 + if (ret) 26 + return ret; 27 + 28 + pm_runtime_enable(&i2c->dev); 29 + pm_request_idle(&i2c->dev); 30 + 31 + return 0; 32 + } 33 + 34 + static int cs42xx8_i2c_remove(struct i2c_client *i2c) 35 + { 36 + snd_soc_unregister_codec(&i2c->dev); 37 + pm_runtime_disable(&i2c->dev); 38 + 39 + return 0; 40 + } 41 + 42 + static struct i2c_device_id cs42xx8_i2c_id[] = { 43 + {"cs42448", (kernel_ulong_t)&cs42448_data}, 44 + {"cs42888", (kernel_ulong_t)&cs42888_data}, 45 + {} 46 + }; 47 + MODULE_DEVICE_TABLE(i2c, cs42xx8_i2c_id); 48 + 49 + static struct i2c_driver cs42xx8_i2c_driver = { 50 + .driver = { 51 + .name = "cs42xx8", 52 + .owner = THIS_MODULE, 53 + .pm = &cs42xx8_pm, 54 + }, 55 + .probe = cs42xx8_i2c_probe, 56 + .remove = cs42xx8_i2c_remove, 57 + .id_table = cs42xx8_i2c_id, 58 + }; 59 + 60 + module_i2c_driver(cs42xx8_i2c_driver); 61 + 62 + MODULE_DESCRIPTION("Cirrus Logic CS42448/CS42888 ALSA SoC Codec I2C Driver"); 63 + MODULE_AUTHOR("Freescale Semiconductor, Inc."); 64 + MODULE_LICENSE("GPL");
+602
sound/soc/codecs/cs42xx8.c
··· 1 + /* 2 + * Cirrus Logic CS42448/CS42888 Audio CODEC Digital Audio Interface (DAI) driver 3 + * 4 + * Copyright (C) 2014 Freescale Semiconductor, Inc. 5 + * 6 + * Author: Nicolin Chen <Guangyu.Chen@freescale.com> 7 + * 8 + * This file is licensed under the terms of the GNU General Public License 9 + * version 2. This program is licensed "as is" without any warranty of any 10 + * kind, whether express or implied. 11 + */ 12 + 13 + #include <linux/clk.h> 14 + #include <linux/delay.h> 15 + #include <linux/module.h> 16 + #include <linux/of_device.h> 17 + #include <linux/pm_runtime.h> 18 + #include <linux/regulator/consumer.h> 19 + #include <sound/pcm_params.h> 20 + #include <sound/soc.h> 21 + #include <sound/tlv.h> 22 + 23 + #include "cs42xx8.h" 24 + 25 + #define CS42XX8_NUM_SUPPLIES 4 26 + static const char *const cs42xx8_supply_names[CS42XX8_NUM_SUPPLIES] = { 27 + "VA", 28 + "VD", 29 + "VLS", 30 + "VLC", 31 + }; 32 + 33 + #define CS42XX8_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | \ 34 + SNDRV_PCM_FMTBIT_S20_3LE | \ 35 + SNDRV_PCM_FMTBIT_S24_LE | \ 36 + SNDRV_PCM_FMTBIT_S32_LE) 37 + 38 + /* codec private data */ 39 + struct cs42xx8_priv { 40 + struct regulator_bulk_data supplies[CS42XX8_NUM_SUPPLIES]; 41 + const struct cs42xx8_driver_data *drvdata; 42 + struct regmap *regmap; 43 + struct clk *clk; 44 + 45 + bool slave_mode; 46 + unsigned long sysclk; 47 + }; 48 + 49 + /* -127.5dB to 0dB with step of 0.5dB */ 50 + static const DECLARE_TLV_DB_SCALE(dac_tlv, -12750, 50, 1); 51 + /* -64dB to 24dB with step of 0.5dB */ 52 + static const DECLARE_TLV_DB_SCALE(adc_tlv, -6400, 50, 0); 53 + 54 + static const char *const cs42xx8_adc_single[] = { "Differential", "Single-Ended" }; 55 + static const char *const cs42xx8_szc[] = { "Immediate Change", "Zero Cross", 56 + "Soft Ramp", "Soft Ramp on Zero Cross" }; 57 + 58 + static const struct soc_enum adc1_single_enum = 59 + SOC_ENUM_SINGLE(CS42XX8_ADCCTL, 4, 2, cs42xx8_adc_single); 60 + static const struct soc_enum adc2_single_enum = 61 + SOC_ENUM_SINGLE(CS42XX8_ADCCTL, 3, 2, cs42xx8_adc_single); 62 + static const struct soc_enum adc3_single_enum = 63 + SOC_ENUM_SINGLE(CS42XX8_ADCCTL, 2, 2, cs42xx8_adc_single); 64 + static const struct soc_enum dac_szc_enum = 65 + SOC_ENUM_SINGLE(CS42XX8_TXCTL, 5, 4, cs42xx8_szc); 66 + static const struct soc_enum adc_szc_enum = 67 + SOC_ENUM_SINGLE(CS42XX8_TXCTL, 0, 4, cs42xx8_szc); 68 + 69 + static const struct snd_kcontrol_new cs42xx8_snd_controls[] = { 70 + SOC_DOUBLE_R_TLV("DAC1 Playback Volume", CS42XX8_VOLAOUT1, 71 + CS42XX8_VOLAOUT2, 0, 0xff, 1, dac_tlv), 72 + SOC_DOUBLE_R_TLV("DAC2 Playback Volume", CS42XX8_VOLAOUT3, 73 + CS42XX8_VOLAOUT4, 0, 0xff, 1, dac_tlv), 74 + SOC_DOUBLE_R_TLV("DAC3 Playback Volume", CS42XX8_VOLAOUT5, 75 + CS42XX8_VOLAOUT6, 0, 0xff, 1, dac_tlv), 76 + SOC_DOUBLE_R_TLV("DAC4 Playback Volume", CS42XX8_VOLAOUT7, 77 + CS42XX8_VOLAOUT8, 0, 0xff, 1, dac_tlv), 78 + SOC_DOUBLE_R_S_TLV("ADC1 Capture Volume", CS42XX8_VOLAIN1, 79 + CS42XX8_VOLAIN2, 0, -0x80, 0x30, 7, 0, adc_tlv), 80 + SOC_DOUBLE_R_S_TLV("ADC2 Capture Volume", CS42XX8_VOLAIN3, 81 + CS42XX8_VOLAIN4, 0, -0x80, 0x30, 7, 0, adc_tlv), 82 + SOC_DOUBLE("DAC1 Invert Switch", CS42XX8_DACINV, 0, 1, 1, 0), 83 + SOC_DOUBLE("DAC2 Invert Switch", CS42XX8_DACINV, 2, 3, 1, 0), 84 + SOC_DOUBLE("DAC3 Invert Switch", CS42XX8_DACINV, 4, 5, 1, 0), 85 + SOC_DOUBLE("DAC4 Invert Switch", CS42XX8_DACINV, 6, 7, 1, 0), 86 + SOC_DOUBLE("ADC1 Invert Switch", CS42XX8_ADCINV, 0, 1, 1, 0), 87 + SOC_DOUBLE("ADC2 Invert Switch", CS42XX8_ADCINV, 2, 3, 1, 0), 88 + SOC_SINGLE("ADC High-Pass Filter Switch", CS42XX8_ADCCTL, 7, 1, 1), 89 + SOC_SINGLE("DAC De-emphasis Switch", CS42XX8_ADCCTL, 5, 1, 0), 90 + SOC_ENUM("ADC1 Single Ended Mode Switch", adc1_single_enum), 91 + SOC_ENUM("ADC2 Single Ended Mode Switch", adc2_single_enum), 92 + SOC_SINGLE("DAC Single Volume Control Switch", CS42XX8_TXCTL, 7, 1, 0), 93 + SOC_ENUM("DAC Soft Ramp & Zero Cross Control Switch", dac_szc_enum), 94 + SOC_SINGLE("DAC Auto Mute Switch", CS42XX8_TXCTL, 4, 1, 0), 95 + SOC_SINGLE("Mute ADC Serial Port Switch", CS42XX8_TXCTL, 3, 1, 0), 96 + SOC_SINGLE("ADC Single Volume Control Switch", CS42XX8_TXCTL, 2, 1, 0), 97 + SOC_ENUM("ADC Soft Ramp & Zero Cross Control Switch", adc_szc_enum), 98 + }; 99 + 100 + static const struct snd_kcontrol_new cs42xx8_adc3_snd_controls[] = { 101 + SOC_DOUBLE_R_S_TLV("ADC3 Capture Volume", CS42XX8_VOLAIN5, 102 + CS42XX8_VOLAIN6, 0, -0x80, 0x30, 7, 0, adc_tlv), 103 + SOC_DOUBLE("ADC3 Invert Switch", CS42XX8_ADCINV, 4, 5, 1, 0), 104 + SOC_ENUM("ADC3 Single Ended Mode Switch", adc3_single_enum), 105 + }; 106 + 107 + static const struct snd_soc_dapm_widget cs42xx8_dapm_widgets[] = { 108 + SND_SOC_DAPM_DAC("DAC1", "Playback", CS42XX8_PWRCTL, 1, 1), 109 + SND_SOC_DAPM_DAC("DAC2", "Playback", CS42XX8_PWRCTL, 2, 1), 110 + SND_SOC_DAPM_DAC("DAC3", "Playback", CS42XX8_PWRCTL, 3, 1), 111 + SND_SOC_DAPM_DAC("DAC4", "Playback", CS42XX8_PWRCTL, 4, 1), 112 + 113 + SND_SOC_DAPM_OUTPUT("AOUT1L"), 114 + SND_SOC_DAPM_OUTPUT("AOUT1R"), 115 + SND_SOC_DAPM_OUTPUT("AOUT2L"), 116 + SND_SOC_DAPM_OUTPUT("AOUT2R"), 117 + SND_SOC_DAPM_OUTPUT("AOUT3L"), 118 + SND_SOC_DAPM_OUTPUT("AOUT3R"), 119 + SND_SOC_DAPM_OUTPUT("AOUT4L"), 120 + SND_SOC_DAPM_OUTPUT("AOUT4R"), 121 + 122 + SND_SOC_DAPM_ADC("ADC1", "Capture", CS42XX8_PWRCTL, 5, 1), 123 + SND_SOC_DAPM_ADC("ADC2", "Capture", CS42XX8_PWRCTL, 6, 1), 124 + 125 + SND_SOC_DAPM_INPUT("AIN1L"), 126 + SND_SOC_DAPM_INPUT("AIN1R"), 127 + SND_SOC_DAPM_INPUT("AIN2L"), 128 + SND_SOC_DAPM_INPUT("AIN2R"), 129 + 130 + SND_SOC_DAPM_SUPPLY("PWR", CS42XX8_PWRCTL, 0, 1, NULL, 0), 131 + }; 132 + 133 + static const struct snd_soc_dapm_widget cs42xx8_adc3_dapm_widgets[] = { 134 + SND_SOC_DAPM_ADC("ADC3", "Capture", CS42XX8_PWRCTL, 7, 1), 135 + 136 + SND_SOC_DAPM_INPUT("AIN3L"), 137 + SND_SOC_DAPM_INPUT("AIN3R"), 138 + }; 139 + 140 + static const struct snd_soc_dapm_route cs42xx8_dapm_routes[] = { 141 + /* Playback */ 142 + { "AOUT1L", NULL, "DAC1" }, 143 + { "AOUT1R", NULL, "DAC1" }, 144 + { "DAC1", NULL, "PWR" }, 145 + 146 + { "AOUT2L", NULL, "DAC2" }, 147 + { "AOUT2R", NULL, "DAC2" }, 148 + { "DAC2", NULL, "PWR" }, 149 + 150 + { "AOUT3L", NULL, "DAC3" }, 151 + { "AOUT3R", NULL, "DAC3" }, 152 + { "DAC3", NULL, "PWR" }, 153 + 154 + { "AOUT4L", NULL, "DAC4" }, 155 + { "AOUT4R", NULL, "DAC4" }, 156 + { "DAC4", NULL, "PWR" }, 157 + 158 + /* Capture */ 159 + { "ADC1", NULL, "AIN1L" }, 160 + { "ADC1", NULL, "AIN1R" }, 161 + { "ADC1", NULL, "PWR" }, 162 + 163 + { "ADC2", NULL, "AIN2L" }, 164 + { "ADC2", NULL, "AIN2R" }, 165 + { "ADC2", NULL, "PWR" }, 166 + }; 167 + 168 + static const struct snd_soc_dapm_route cs42xx8_adc3_dapm_routes[] = { 169 + /* Capture */ 170 + { "ADC3", NULL, "AIN3L" }, 171 + { "ADC3", NULL, "AIN3R" }, 172 + { "ADC3", NULL, "PWR" }, 173 + }; 174 + 175 + struct cs42xx8_ratios { 176 + unsigned int ratio; 177 + unsigned char speed; 178 + unsigned char mclk; 179 + }; 180 + 181 + static const struct cs42xx8_ratios cs42xx8_ratios[] = { 182 + { 64, CS42XX8_FM_QUAD, CS42XX8_FUNCMOD_MFREQ_256(4) }, 183 + { 96, CS42XX8_FM_QUAD, CS42XX8_FUNCMOD_MFREQ_384(4) }, 184 + { 128, CS42XX8_FM_QUAD, CS42XX8_FUNCMOD_MFREQ_512(4) }, 185 + { 192, CS42XX8_FM_QUAD, CS42XX8_FUNCMOD_MFREQ_768(4) }, 186 + { 256, CS42XX8_FM_SINGLE, CS42XX8_FUNCMOD_MFREQ_256(1) }, 187 + { 384, CS42XX8_FM_SINGLE, CS42XX8_FUNCMOD_MFREQ_384(1) }, 188 + { 512, CS42XX8_FM_SINGLE, CS42XX8_FUNCMOD_MFREQ_512(1) }, 189 + { 768, CS42XX8_FM_SINGLE, CS42XX8_FUNCMOD_MFREQ_768(1) }, 190 + { 1024, CS42XX8_FM_SINGLE, CS42XX8_FUNCMOD_MFREQ_1024(1) } 191 + }; 192 + 193 + static int cs42xx8_set_dai_sysclk(struct snd_soc_dai *codec_dai, 194 + int clk_id, unsigned int freq, int dir) 195 + { 196 + struct snd_soc_codec *codec = codec_dai->codec; 197 + struct cs42xx8_priv *cs42xx8 = snd_soc_codec_get_drvdata(codec); 198 + 199 + cs42xx8->sysclk = freq; 200 + 201 + return 0; 202 + } 203 + 204 + static int cs42xx8_set_dai_fmt(struct snd_soc_dai *codec_dai, 205 + unsigned int format) 206 + { 207 + struct snd_soc_codec *codec = codec_dai->codec; 208 + struct cs42xx8_priv *cs42xx8 = snd_soc_codec_get_drvdata(codec); 209 + u32 val; 210 + 211 + /* Set DAI format */ 212 + switch (format & SND_SOC_DAIFMT_FORMAT_MASK) { 213 + case SND_SOC_DAIFMT_LEFT_J: 214 + val = CS42XX8_INTF_DAC_DIF_LEFTJ | CS42XX8_INTF_ADC_DIF_LEFTJ; 215 + break; 216 + case SND_SOC_DAIFMT_I2S: 217 + val = CS42XX8_INTF_DAC_DIF_I2S | CS42XX8_INTF_ADC_DIF_I2S; 218 + break; 219 + case SND_SOC_DAIFMT_RIGHT_J: 220 + val = CS42XX8_INTF_DAC_DIF_RIGHTJ | CS42XX8_INTF_ADC_DIF_RIGHTJ; 221 + break; 222 + default: 223 + dev_err(codec->dev, "unsupported dai format\n"); 224 + return -EINVAL; 225 + } 226 + 227 + regmap_update_bits(cs42xx8->regmap, CS42XX8_INTF, 228 + CS42XX8_INTF_DAC_DIF_MASK | 229 + CS42XX8_INTF_ADC_DIF_MASK, val); 230 + 231 + /* Set master/slave audio interface */ 232 + switch (format & SND_SOC_DAIFMT_MASTER_MASK) { 233 + case SND_SOC_DAIFMT_CBS_CFS: 234 + cs42xx8->slave_mode = true; 235 + break; 236 + case SND_SOC_DAIFMT_CBM_CFM: 237 + cs42xx8->slave_mode = false; 238 + break; 239 + default: 240 + dev_err(codec->dev, "unsupported master/slave mode\n"); 241 + return -EINVAL; 242 + } 243 + 244 + return 0; 245 + } 246 + 247 + static int cs42xx8_hw_params(struct snd_pcm_substream *substream, 248 + struct snd_pcm_hw_params *params, 249 + struct snd_soc_dai *dai) 250 + { 251 + struct snd_soc_pcm_runtime *rtd = substream->private_data; 252 + struct snd_soc_codec *codec = rtd->codec; 253 + struct cs42xx8_priv *cs42xx8 = snd_soc_codec_get_drvdata(codec); 254 + bool tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK; 255 + u32 ratio = cs42xx8->sysclk / params_rate(params); 256 + u32 i, fm, val, mask; 257 + 258 + for (i = 0; i < ARRAY_SIZE(cs42xx8_ratios); i++) { 259 + if (cs42xx8_ratios[i].ratio == ratio) 260 + break; 261 + } 262 + 263 + if (i == ARRAY_SIZE(cs42xx8_ratios)) { 264 + dev_err(codec->dev, "unsupported sysclk ratio\n"); 265 + return -EINVAL; 266 + } 267 + 268 + mask = CS42XX8_FUNCMOD_MFREQ_MASK; 269 + val = cs42xx8_ratios[i].mclk; 270 + 271 + fm = cs42xx8->slave_mode ? CS42XX8_FM_AUTO : cs42xx8_ratios[i].speed; 272 + 273 + regmap_update_bits(cs42xx8->regmap, CS42XX8_FUNCMOD, 274 + CS42XX8_FUNCMOD_xC_FM_MASK(tx) | mask, 275 + CS42XX8_FUNCMOD_xC_FM(tx, fm) | val); 276 + 277 + return 0; 278 + } 279 + 280 + static int cs42xx8_digital_mute(struct snd_soc_dai *dai, int mute) 281 + { 282 + struct snd_soc_codec *codec = dai->codec; 283 + struct cs42xx8_priv *cs42xx8 = snd_soc_codec_get_drvdata(codec); 284 + 285 + regmap_update_bits(cs42xx8->regmap, CS42XX8_DACMUTE, 286 + CS42XX8_DACMUTE_ALL, mute ? CS42XX8_DACMUTE_ALL : 0); 287 + 288 + return 0; 289 + } 290 + 291 + static const struct snd_soc_dai_ops cs42xx8_dai_ops = { 292 + .set_fmt = cs42xx8_set_dai_fmt, 293 + .set_sysclk = cs42xx8_set_dai_sysclk, 294 + .hw_params = cs42xx8_hw_params, 295 + .digital_mute = cs42xx8_digital_mute, 296 + }; 297 + 298 + static struct snd_soc_dai_driver cs42xx8_dai = { 299 + .playback = { 300 + .stream_name = "Playback", 301 + .channels_min = 1, 302 + .channels_max = 8, 303 + .rates = SNDRV_PCM_RATE_8000_192000, 304 + .formats = CS42XX8_FORMATS, 305 + }, 306 + .capture = { 307 + .stream_name = "Capture", 308 + .channels_min = 1, 309 + .rates = SNDRV_PCM_RATE_8000_192000, 310 + .formats = CS42XX8_FORMATS, 311 + }, 312 + .ops = &cs42xx8_dai_ops, 313 + }; 314 + 315 + static const struct reg_default cs42xx8_reg[] = { 316 + { 0x01, 0x01 }, /* Chip I.D. and Revision Register */ 317 + { 0x02, 0x00 }, /* Power Control */ 318 + { 0x03, 0xF0 }, /* Functional Mode */ 319 + { 0x04, 0x46 }, /* Interface Formats */ 320 + { 0x05, 0x00 }, /* ADC Control & DAC De-Emphasis */ 321 + { 0x06, 0x10 }, /* Transition Control */ 322 + { 0x07, 0x00 }, /* DAC Channel Mute */ 323 + { 0x08, 0x00 }, /* Volume Control AOUT1 */ 324 + { 0x09, 0x00 }, /* Volume Control AOUT2 */ 325 + { 0x0a, 0x00 }, /* Volume Control AOUT3 */ 326 + { 0x0b, 0x00 }, /* Volume Control AOUT4 */ 327 + { 0x0c, 0x00 }, /* Volume Control AOUT5 */ 328 + { 0x0d, 0x00 }, /* Volume Control AOUT6 */ 329 + { 0x0e, 0x00 }, /* Volume Control AOUT7 */ 330 + { 0x0f, 0x00 }, /* Volume Control AOUT8 */ 331 + { 0x10, 0x00 }, /* DAC Channel Invert */ 332 + { 0x11, 0x00 }, /* Volume Control AIN1 */ 333 + { 0x12, 0x00 }, /* Volume Control AIN2 */ 334 + { 0x13, 0x00 }, /* Volume Control AIN3 */ 335 + { 0x14, 0x00 }, /* Volume Control AIN4 */ 336 + { 0x15, 0x00 }, /* Volume Control AIN5 */ 337 + { 0x16, 0x00 }, /* Volume Control AIN6 */ 338 + { 0x17, 0x00 }, /* ADC Channel Invert */ 339 + { 0x18, 0x00 }, /* Status Control */ 340 + { 0x1a, 0x00 }, /* Status Mask */ 341 + { 0x1b, 0x00 }, /* MUTEC Pin Control */ 342 + }; 343 + 344 + static bool cs42xx8_volatile_register(struct device *dev, unsigned int reg) 345 + { 346 + switch (reg) { 347 + case CS42XX8_STATUS: 348 + return true; 349 + default: 350 + return false; 351 + } 352 + } 353 + 354 + static bool cs42xx8_writeable_register(struct device *dev, unsigned int reg) 355 + { 356 + switch (reg) { 357 + case CS42XX8_CHIPID: 358 + case CS42XX8_STATUS: 359 + return false; 360 + default: 361 + return true; 362 + } 363 + } 364 + 365 + const struct regmap_config cs42xx8_regmap_config = { 366 + .reg_bits = 8, 367 + .val_bits = 8, 368 + 369 + .max_register = CS42XX8_LASTREG, 370 + .reg_defaults = cs42xx8_reg, 371 + .num_reg_defaults = ARRAY_SIZE(cs42xx8_reg), 372 + .volatile_reg = cs42xx8_volatile_register, 373 + .writeable_reg = cs42xx8_writeable_register, 374 + .cache_type = REGCACHE_RBTREE, 375 + }; 376 + EXPORT_SYMBOL_GPL(cs42xx8_regmap_config); 377 + 378 + static int cs42xx8_codec_probe(struct snd_soc_codec *codec) 379 + { 380 + struct cs42xx8_priv *cs42xx8 = snd_soc_codec_get_drvdata(codec); 381 + struct snd_soc_dapm_context *dapm = &codec->dapm; 382 + 383 + switch (cs42xx8->drvdata->num_adcs) { 384 + case 3: 385 + snd_soc_add_codec_controls(codec, cs42xx8_adc3_snd_controls, 386 + ARRAY_SIZE(cs42xx8_adc3_snd_controls)); 387 + snd_soc_dapm_new_controls(dapm, cs42xx8_adc3_dapm_widgets, 388 + ARRAY_SIZE(cs42xx8_adc3_dapm_widgets)); 389 + snd_soc_dapm_add_routes(dapm, cs42xx8_adc3_dapm_routes, 390 + ARRAY_SIZE(cs42xx8_adc3_dapm_routes)); 391 + break; 392 + default: 393 + break; 394 + } 395 + 396 + /* Mute all DAC channels */ 397 + regmap_write(cs42xx8->regmap, CS42XX8_DACMUTE, CS42XX8_DACMUTE_ALL); 398 + 399 + return 0; 400 + } 401 + 402 + static const struct snd_soc_codec_driver cs42xx8_driver = { 403 + .probe = cs42xx8_codec_probe, 404 + .idle_bias_off = true, 405 + 406 + .controls = cs42xx8_snd_controls, 407 + .num_controls = ARRAY_SIZE(cs42xx8_snd_controls), 408 + .dapm_widgets = cs42xx8_dapm_widgets, 409 + .num_dapm_widgets = ARRAY_SIZE(cs42xx8_dapm_widgets), 410 + .dapm_routes = cs42xx8_dapm_routes, 411 + .num_dapm_routes = ARRAY_SIZE(cs42xx8_dapm_routes), 412 + }; 413 + 414 + const struct cs42xx8_driver_data cs42448_data = { 415 + .name = "cs42448", 416 + .num_adcs = 3, 417 + }; 418 + EXPORT_SYMBOL_GPL(cs42448_data); 419 + 420 + const struct cs42xx8_driver_data cs42888_data = { 421 + .name = "cs42888", 422 + .num_adcs = 2, 423 + }; 424 + EXPORT_SYMBOL_GPL(cs42888_data); 425 + 426 + const struct of_device_id cs42xx8_of_match[] = { 427 + { .compatible = "cirrus,cs42448", .data = &cs42448_data, }, 428 + { .compatible = "cirrus,cs42888", .data = &cs42888_data, }, 429 + { /* sentinel */ } 430 + }; 431 + MODULE_DEVICE_TABLE(of, cs42xx8_of_match); 432 + EXPORT_SYMBOL_GPL(cs42xx8_of_match); 433 + 434 + int cs42xx8_probe(struct device *dev, struct regmap *regmap) 435 + { 436 + const struct of_device_id *of_id = of_match_device(cs42xx8_of_match, dev); 437 + struct cs42xx8_priv *cs42xx8; 438 + int ret, val, i; 439 + 440 + cs42xx8 = devm_kzalloc(dev, sizeof(*cs42xx8), GFP_KERNEL); 441 + if (cs42xx8 == NULL) 442 + return -ENOMEM; 443 + 444 + dev_set_drvdata(dev, cs42xx8); 445 + 446 + if (of_id) 447 + cs42xx8->drvdata = of_id->data; 448 + 449 + if (!cs42xx8->drvdata) { 450 + dev_err(dev, "failed to find driver data\n"); 451 + return -EINVAL; 452 + } 453 + 454 + cs42xx8->clk = devm_clk_get(dev, "mclk"); 455 + if (IS_ERR(cs42xx8->clk)) { 456 + dev_err(dev, "failed to get the clock: %ld\n", 457 + PTR_ERR(cs42xx8->clk)); 458 + return -EINVAL; 459 + } 460 + 461 + cs42xx8->sysclk = clk_get_rate(cs42xx8->clk); 462 + 463 + for (i = 0; i < ARRAY_SIZE(cs42xx8->supplies); i++) 464 + cs42xx8->supplies[i].supply = cs42xx8_supply_names[i]; 465 + 466 + ret = devm_regulator_bulk_get(dev, 467 + ARRAY_SIZE(cs42xx8->supplies), cs42xx8->supplies); 468 + if (ret) { 469 + dev_err(dev, "failed to request supplies: %d\n", ret); 470 + return ret; 471 + } 472 + 473 + ret = regulator_bulk_enable(ARRAY_SIZE(cs42xx8->supplies), 474 + cs42xx8->supplies); 475 + if (ret) { 476 + dev_err(dev, "failed to enable supplies: %d\n", ret); 477 + return ret; 478 + } 479 + 480 + /* Make sure hardware reset done */ 481 + msleep(5); 482 + 483 + cs42xx8->regmap = regmap; 484 + if (IS_ERR(cs42xx8->regmap)) { 485 + ret = PTR_ERR(cs42xx8->regmap); 486 + dev_err(dev, "failed to allocate regmap: %d\n", ret); 487 + goto err_enable; 488 + } 489 + 490 + /* 491 + * We haven't marked the chip revision as volatile due to 492 + * sharing a register with the right input volume; explicitly 493 + * bypass the cache to read it. 494 + */ 495 + regcache_cache_bypass(cs42xx8->regmap, true); 496 + 497 + /* Validate the chip ID */ 498 + regmap_read(cs42xx8->regmap, CS42XX8_CHIPID, &val); 499 + if (val < 0) { 500 + dev_err(dev, "failed to get device ID: %x", val); 501 + ret = -EINVAL; 502 + goto err_enable; 503 + } 504 + 505 + /* The top four bits of the chip ID should be 0000 */ 506 + if ((val & CS42XX8_CHIPID_CHIP_ID_MASK) != 0x00) { 507 + dev_err(dev, "unmatched chip ID: %d\n", 508 + val & CS42XX8_CHIPID_CHIP_ID_MASK); 509 + ret = -EINVAL; 510 + goto err_enable; 511 + } 512 + 513 + dev_info(dev, "found device, revision %X\n", 514 + val & CS42XX8_CHIPID_REV_ID_MASK); 515 + 516 + regcache_cache_bypass(cs42xx8->regmap, false); 517 + 518 + cs42xx8_dai.name = cs42xx8->drvdata->name; 519 + 520 + /* Each adc supports stereo input */ 521 + cs42xx8_dai.capture.channels_max = cs42xx8->drvdata->num_adcs * 2; 522 + 523 + ret = snd_soc_register_codec(dev, &cs42xx8_driver, &cs42xx8_dai, 1); 524 + if (ret) { 525 + dev_err(dev, "failed to register codec:%d\n", ret); 526 + goto err_enable; 527 + } 528 + 529 + regcache_cache_only(cs42xx8->regmap, true); 530 + 531 + err_enable: 532 + regulator_bulk_disable(ARRAY_SIZE(cs42xx8->supplies), 533 + cs42xx8->supplies); 534 + 535 + return ret; 536 + } 537 + EXPORT_SYMBOL_GPL(cs42xx8_probe); 538 + 539 + #ifdef CONFIG_PM_RUNTIME 540 + static int cs42xx8_runtime_resume(struct device *dev) 541 + { 542 + struct cs42xx8_priv *cs42xx8 = dev_get_drvdata(dev); 543 + int ret; 544 + 545 + ret = clk_prepare_enable(cs42xx8->clk); 546 + if (ret) { 547 + dev_err(dev, "failed to enable mclk: %d\n", ret); 548 + return ret; 549 + } 550 + 551 + ret = regulator_bulk_enable(ARRAY_SIZE(cs42xx8->supplies), 552 + cs42xx8->supplies); 553 + if (ret) { 554 + dev_err(dev, "failed to enable supplies: %d\n", ret); 555 + goto err_clk; 556 + } 557 + 558 + /* Make sure hardware reset done */ 559 + msleep(5); 560 + 561 + regcache_cache_only(cs42xx8->regmap, false); 562 + 563 + ret = regcache_sync(cs42xx8->regmap); 564 + if (ret) { 565 + dev_err(dev, "failed to sync regmap: %d\n", ret); 566 + goto err_bulk; 567 + } 568 + 569 + return 0; 570 + 571 + err_bulk: 572 + regulator_bulk_disable(ARRAY_SIZE(cs42xx8->supplies), 573 + cs42xx8->supplies); 574 + err_clk: 575 + clk_disable_unprepare(cs42xx8->clk); 576 + 577 + return ret; 578 + } 579 + 580 + static int cs42xx8_runtime_suspend(struct device *dev) 581 + { 582 + struct cs42xx8_priv *cs42xx8 = dev_get_drvdata(dev); 583 + 584 + regcache_cache_only(cs42xx8->regmap, true); 585 + 586 + regulator_bulk_disable(ARRAY_SIZE(cs42xx8->supplies), 587 + cs42xx8->supplies); 588 + 589 + clk_disable_unprepare(cs42xx8->clk); 590 + 591 + return 0; 592 + } 593 + #endif 594 + 595 + const struct dev_pm_ops cs42xx8_pm = { 596 + SET_RUNTIME_PM_OPS(cs42xx8_runtime_suspend, cs42xx8_runtime_resume, NULL) 597 + }; 598 + EXPORT_SYMBOL_GPL(cs42xx8_pm); 599 + 600 + MODULE_DESCRIPTION("Cirrus Logic CS42448/CS42888 ALSA SoC Codec Driver"); 601 + MODULE_AUTHOR("Freescale Semiconductor, Inc."); 602 + MODULE_LICENSE("GPL");
+238
sound/soc/codecs/cs42xx8.h
··· 1 + /* 2 + * cs42xx8.h - Cirrus Logic CS42448/CS42888 Audio CODEC driver header file 3 + * 4 + * Copyright (C) 2014 Freescale Semiconductor, Inc. 5 + * 6 + * Author: Nicolin Chen <Guangyu.Chen@freescale.com> 7 + * 8 + * This file is licensed under the terms of the GNU General Public License 9 + * version 2. This program is licensed "as is" without any warranty of any 10 + * kind, whether express or implied. 11 + */ 12 + 13 + #ifndef _CS42XX8_H 14 + #define _CS42XX8_H 15 + 16 + struct cs42xx8_driver_data { 17 + char name[32]; 18 + int num_adcs; 19 + }; 20 + 21 + extern const struct dev_pm_ops cs42xx8_pm; 22 + extern const struct cs42xx8_driver_data cs42448_data; 23 + extern const struct cs42xx8_driver_data cs42888_data; 24 + extern const struct regmap_config cs42xx8_regmap_config; 25 + int cs42xx8_probe(struct device *dev, struct regmap *regmap); 26 + 27 + /* CS42888 register map */ 28 + #define CS42XX8_CHIPID 0x01 /* Chip ID */ 29 + #define CS42XX8_PWRCTL 0x02 /* Power Control */ 30 + #define CS42XX8_FUNCMOD 0x03 /* Functional Mode */ 31 + #define CS42XX8_INTF 0x04 /* Interface Formats */ 32 + #define CS42XX8_ADCCTL 0x05 /* ADC Control */ 33 + #define CS42XX8_TXCTL 0x06 /* Transition Control */ 34 + #define CS42XX8_DACMUTE 0x07 /* DAC Mute Control */ 35 + #define CS42XX8_VOLAOUT1 0x08 /* Volume Control AOUT1 */ 36 + #define CS42XX8_VOLAOUT2 0x09 /* Volume Control AOUT2 */ 37 + #define CS42XX8_VOLAOUT3 0x0A /* Volume Control AOUT3 */ 38 + #define CS42XX8_VOLAOUT4 0x0B /* Volume Control AOUT4 */ 39 + #define CS42XX8_VOLAOUT5 0x0C /* Volume Control AOUT5 */ 40 + #define CS42XX8_VOLAOUT6 0x0D /* Volume Control AOUT6 */ 41 + #define CS42XX8_VOLAOUT7 0x0E /* Volume Control AOUT7 */ 42 + #define CS42XX8_VOLAOUT8 0x0F /* Volume Control AOUT8 */ 43 + #define CS42XX8_DACINV 0x10 /* DAC Channel Invert */ 44 + #define CS42XX8_VOLAIN1 0x11 /* Volume Control AIN1 */ 45 + #define CS42XX8_VOLAIN2 0x12 /* Volume Control AIN2 */ 46 + #define CS42XX8_VOLAIN3 0x13 /* Volume Control AIN3 */ 47 + #define CS42XX8_VOLAIN4 0x14 /* Volume Control AIN4 */ 48 + #define CS42XX8_VOLAIN5 0x15 /* Volume Control AIN5 */ 49 + #define CS42XX8_VOLAIN6 0x16 /* Volume Control AIN6 */ 50 + #define CS42XX8_ADCINV 0x17 /* ADC Channel Invert */ 51 + #define CS42XX8_STATUSCTL 0x18 /* Status Control */ 52 + #define CS42XX8_STATUS 0x19 /* Status */ 53 + #define CS42XX8_STATUSM 0x1A /* Status Mask */ 54 + #define CS42XX8_MUTEC 0x1B /* MUTEC Pin Control */ 55 + 56 + #define CS42XX8_FIRSTREG CS42XX8_CHIPID 57 + #define CS42XX8_LASTREG CS42XX8_MUTEC 58 + #define CS42XX8_NUMREGS (CS42XX8_LASTREG - CS42XX8_FIRSTREG + 1) 59 + #define CS42XX8_I2C_INCR 0x80 60 + 61 + /* Chip I.D. and Revision Register (Address 01h) */ 62 + #define CS42XX8_CHIPID_CHIP_ID_MASK 0xF0 63 + #define CS42XX8_CHIPID_REV_ID_MASK 0x0F 64 + 65 + /* Power Control (Address 02h) */ 66 + #define CS42XX8_PWRCTL_PDN_ADC3_SHIFT 7 67 + #define CS42XX8_PWRCTL_PDN_ADC3_MASK (1 << CS42XX8_PWRCTL_PDN_ADC3_SHIFT) 68 + #define CS42XX8_PWRCTL_PDN_ADC3 (1 << CS42XX8_PWRCTL_PDN_ADC3_SHIFT) 69 + #define CS42XX8_PWRCTL_PDN_ADC2_SHIFT 6 70 + #define CS42XX8_PWRCTL_PDN_ADC2_MASK (1 << CS42XX8_PWRCTL_PDN_ADC2_SHIFT) 71 + #define CS42XX8_PWRCTL_PDN_ADC2 (1 << CS42XX8_PWRCTL_PDN_ADC2_SHIFT) 72 + #define CS42XX8_PWRCTL_PDN_ADC1_SHIFT 5 73 + #define CS42XX8_PWRCTL_PDN_ADC1_MASK (1 << CS42XX8_PWRCTL_PDN_ADC1_SHIFT) 74 + #define CS42XX8_PWRCTL_PDN_ADC1 (1 << CS42XX8_PWRCTL_PDN_ADC1_SHIFT) 75 + #define CS42XX8_PWRCTL_PDN_DAC4_SHIFT 4 76 + #define CS42XX8_PWRCTL_PDN_DAC4_MASK (1 << CS42XX8_PWRCTL_PDN_DAC4_SHIFT) 77 + #define CS42XX8_PWRCTL_PDN_DAC4 (1 << CS42XX8_PWRCTL_PDN_DAC4_SHIFT) 78 + #define CS42XX8_PWRCTL_PDN_DAC3_SHIFT 3 79 + #define CS42XX8_PWRCTL_PDN_DAC3_MASK (1 << CS42XX8_PWRCTL_PDN_DAC3_SHIFT) 80 + #define CS42XX8_PWRCTL_PDN_DAC3 (1 << CS42XX8_PWRCTL_PDN_DAC3_SHIFT) 81 + #define CS42XX8_PWRCTL_PDN_DAC2_SHIFT 2 82 + #define CS42XX8_PWRCTL_PDN_DAC2_MASK (1 << CS42XX8_PWRCTL_PDN_DAC2_SHIFT) 83 + #define CS42XX8_PWRCTL_PDN_DAC2 (1 << CS42XX8_PWRCTL_PDN_DAC2_SHIFT) 84 + #define CS42XX8_PWRCTL_PDN_DAC1_SHIFT 1 85 + #define CS42XX8_PWRCTL_PDN_DAC1_MASK (1 << CS42XX8_PWRCTL_PDN_DAC1_SHIFT) 86 + #define CS42XX8_PWRCTL_PDN_DAC1 (1 << CS42XX8_PWRCTL_PDN_DAC1_SHIFT) 87 + #define CS42XX8_PWRCTL_PDN_SHIFT 0 88 + #define CS42XX8_PWRCTL_PDN_MASK (1 << CS42XX8_PWRCTL_PDN_SHIFT) 89 + #define CS42XX8_PWRCTL_PDN (1 << CS42XX8_PWRCTL_PDN_SHIFT) 90 + 91 + /* Functional Mode (Address 03h) */ 92 + #define CS42XX8_FUNCMOD_DAC_FM_SHIFT 6 93 + #define CS42XX8_FUNCMOD_DAC_FM_WIDTH 2 94 + #define CS42XX8_FUNCMOD_DAC_FM_MASK (((1 << CS42XX8_FUNCMOD_DAC_FM_WIDTH) - 1) << CS42XX8_FUNCMOD_DAC_FM_SHIFT) 95 + #define CS42XX8_FUNCMOD_DAC_FM(v) ((v) << CS42XX8_FUNCMOD_DAC_FM_SHIFT) 96 + #define CS42XX8_FUNCMOD_ADC_FM_SHIFT 4 97 + #define CS42XX8_FUNCMOD_ADC_FM_WIDTH 2 98 + #define CS42XX8_FUNCMOD_ADC_FM_MASK (((1 << CS42XX8_FUNCMOD_ADC_FM_WIDTH) - 1) << CS42XX8_FUNCMOD_ADC_FM_SHIFT) 99 + #define CS42XX8_FUNCMOD_ADC_FM(v) ((v) << CS42XX8_FUNCMOD_ADC_FM_SHIFT) 100 + #define CS42XX8_FUNCMOD_xC_FM_MASK(x) ((x) ? CS42XX8_FUNCMOD_DAC_FM_MASK : CS42XX8_FUNCMOD_ADC_FM_MASK) 101 + #define CS42XX8_FUNCMOD_xC_FM(x, v) ((x) ? CS42XX8_FUNCMOD_DAC_FM(v) : CS42XX8_FUNCMOD_ADC_FM(v)) 102 + #define CS42XX8_FUNCMOD_MFREQ_SHIFT 1 103 + #define CS42XX8_FUNCMOD_MFREQ_WIDTH 3 104 + #define CS42XX8_FUNCMOD_MFREQ_MASK (((1 << CS42XX8_FUNCMOD_MFREQ_WIDTH) - 1) << CS42XX8_FUNCMOD_MFREQ_SHIFT) 105 + #define CS42XX8_FUNCMOD_MFREQ_256(s) ((0 << CS42XX8_FUNCMOD_MFREQ_SHIFT) >> (s >> 1)) 106 + #define CS42XX8_FUNCMOD_MFREQ_384(s) ((1 << CS42XX8_FUNCMOD_MFREQ_SHIFT) >> (s >> 1)) 107 + #define CS42XX8_FUNCMOD_MFREQ_512(s) ((2 << CS42XX8_FUNCMOD_MFREQ_SHIFT) >> (s >> 1)) 108 + #define CS42XX8_FUNCMOD_MFREQ_768(s) ((3 << CS42XX8_FUNCMOD_MFREQ_SHIFT) >> (s >> 1)) 109 + #define CS42XX8_FUNCMOD_MFREQ_1024(s) ((4 << CS42XX8_FUNCMOD_MFREQ_SHIFT) >> (s >> 1)) 110 + 111 + #define CS42XX8_FM_SINGLE 0 112 + #define CS42XX8_FM_DOUBLE 1 113 + #define CS42XX8_FM_QUAD 2 114 + #define CS42XX8_FM_AUTO 3 115 + 116 + /* Interface Formats (Address 04h) */ 117 + #define CS42XX8_INTF_FREEZE_SHIFT 7 118 + #define CS42XX8_INTF_FREEZE_MASK (1 << CS42XX8_INTF_FREEZE_SHIFT) 119 + #define CS42XX8_INTF_FREEZE (1 << CS42XX8_INTF_FREEZE_SHIFT) 120 + #define CS42XX8_INTF_AUX_DIF_SHIFT 6 121 + #define CS42XX8_INTF_AUX_DIF_MASK (1 << CS42XX8_INTF_AUX_DIF_SHIFT) 122 + #define CS42XX8_INTF_AUX_DIF (1 << CS42XX8_INTF_AUX_DIF_SHIFT) 123 + #define CS42XX8_INTF_DAC_DIF_SHIFT 3 124 + #define CS42XX8_INTF_DAC_DIF_WIDTH 3 125 + #define CS42XX8_INTF_DAC_DIF_MASK (((1 << CS42XX8_INTF_DAC_DIF_WIDTH) - 1) << CS42XX8_INTF_DAC_DIF_SHIFT) 126 + #define CS42XX8_INTF_DAC_DIF_LEFTJ (0 << CS42XX8_INTF_DAC_DIF_SHIFT) 127 + #define CS42XX8_INTF_DAC_DIF_I2S (1 << CS42XX8_INTF_DAC_DIF_SHIFT) 128 + #define CS42XX8_INTF_DAC_DIF_RIGHTJ (2 << CS42XX8_INTF_DAC_DIF_SHIFT) 129 + #define CS42XX8_INTF_DAC_DIF_RIGHTJ_16 (3 << CS42XX8_INTF_DAC_DIF_SHIFT) 130 + #define CS42XX8_INTF_DAC_DIF_ONELINE_20 (4 << CS42XX8_INTF_DAC_DIF_SHIFT) 131 + #define CS42XX8_INTF_DAC_DIF_ONELINE_24 (6 << CS42XX8_INTF_DAC_DIF_SHIFT) 132 + #define CS42XX8_INTF_DAC_DIF_TDM (7 << CS42XX8_INTF_DAC_DIF_SHIFT) 133 + #define CS42XX8_INTF_ADC_DIF_SHIFT 0 134 + #define CS42XX8_INTF_ADC_DIF_WIDTH 3 135 + #define CS42XX8_INTF_ADC_DIF_MASK (((1 << CS42XX8_INTF_ADC_DIF_WIDTH) - 1) << CS42XX8_INTF_ADC_DIF_SHIFT) 136 + #define CS42XX8_INTF_ADC_DIF_LEFTJ (0 << CS42XX8_INTF_ADC_DIF_SHIFT) 137 + #define CS42XX8_INTF_ADC_DIF_I2S (1 << CS42XX8_INTF_ADC_DIF_SHIFT) 138 + #define CS42XX8_INTF_ADC_DIF_RIGHTJ (2 << CS42XX8_INTF_ADC_DIF_SHIFT) 139 + #define CS42XX8_INTF_ADC_DIF_RIGHTJ_16 (3 << CS42XX8_INTF_ADC_DIF_SHIFT) 140 + #define CS42XX8_INTF_ADC_DIF_ONELINE_20 (4 << CS42XX8_INTF_ADC_DIF_SHIFT) 141 + #define CS42XX8_INTF_ADC_DIF_ONELINE_24 (6 << CS42XX8_INTF_ADC_DIF_SHIFT) 142 + #define CS42XX8_INTF_ADC_DIF_TDM (7 << CS42XX8_INTF_ADC_DIF_SHIFT) 143 + 144 + /* ADC Control & DAC De-Emphasis (Address 05h) */ 145 + #define CS42XX8_ADCCTL_ADC_HPF_FREEZE_SHIFT 7 146 + #define CS42XX8_ADCCTL_ADC_HPF_FREEZE_MASK (1 << CS42XX8_ADCCTL_ADC_HPF_FREEZE_SHIFT) 147 + #define CS42XX8_ADCCTL_ADC_HPF_FREEZE (1 << CS42XX8_ADCCTL_ADC_HPF_FREEZE_SHIFT) 148 + #define CS42XX8_ADCCTL_DAC_DEM_SHIFT 5 149 + #define CS42XX8_ADCCTL_DAC_DEM_MASK (1 << CS42XX8_ADCCTL_DAC_DEM_SHIFT) 150 + #define CS42XX8_ADCCTL_DAC_DEM (1 << CS42XX8_ADCCTL_DAC_DEM_SHIFT) 151 + #define CS42XX8_ADCCTL_ADC1_SINGLE_SHIFT 4 152 + #define CS42XX8_ADCCTL_ADC1_SINGLE_MASK (1 << CS42XX8_ADCCTL_ADC1_SINGLE_SHIFT) 153 + #define CS42XX8_ADCCTL_ADC1_SINGLE (1 << CS42XX8_ADCCTL_ADC1_SINGLE_SHIFT) 154 + #define CS42XX8_ADCCTL_ADC2_SINGLE_SHIFT 3 155 + #define CS42XX8_ADCCTL_ADC2_SINGLE_MASK (1 << CS42XX8_ADCCTL_ADC2_SINGLE_SHIFT) 156 + #define CS42XX8_ADCCTL_ADC2_SINGLE (1 << CS42XX8_ADCCTL_ADC2_SINGLE_SHIFT) 157 + #define CS42XX8_ADCCTL_ADC3_SINGLE_SHIFT 2 158 + #define CS42XX8_ADCCTL_ADC3_SINGLE_MASK (1 << CS42XX8_ADCCTL_ADC3_SINGLE_SHIFT) 159 + #define CS42XX8_ADCCTL_ADC3_SINGLE (1 << CS42XX8_ADCCTL_ADC3_SINGLE_SHIFT) 160 + #define CS42XX8_ADCCTL_AIN5_MUX_SHIFT 1 161 + #define CS42XX8_ADCCTL_AIN5_MUX_MASK (1 << CS42XX8_ADCCTL_AIN5_MUX_SHIFT) 162 + #define CS42XX8_ADCCTL_AIN5_MUX (1 << CS42XX8_ADCCTL_AIN5_MUX_SHIFT) 163 + #define CS42XX8_ADCCTL_AIN6_MUX_SHIFT 0 164 + #define CS42XX8_ADCCTL_AIN6_MUX_MASK (1 << CS42XX8_ADCCTL_AIN6_MUX_SHIFT) 165 + #define CS42XX8_ADCCTL_AIN6_MUX (1 << CS42XX8_ADCCTL_AIN6_MUX_SHIFT) 166 + 167 + /* Transition Control (Address 06h) */ 168 + #define CS42XX8_TXCTL_DAC_SNGVOL_SHIFT 7 169 + #define CS42XX8_TXCTL_DAC_SNGVOL_MASK (1 << CS42XX8_TXCTL_DAC_SNGVOL_SHIFT) 170 + #define CS42XX8_TXCTL_DAC_SNGVOL (1 << CS42XX8_TXCTL_DAC_SNGVOL_SHIFT) 171 + #define CS42XX8_TXCTL_DAC_SZC_SHIFT 5 172 + #define CS42XX8_TXCTL_DAC_SZC_WIDTH 2 173 + #define CS42XX8_TXCTL_DAC_SZC_MASK (((1 << CS42XX8_TXCTL_DAC_SZC_WIDTH) - 1) << CS42XX8_TXCTL_DAC_SZC_SHIFT) 174 + #define CS42XX8_TXCTL_DAC_SZC_IC (0 << CS42XX8_TXCTL_DAC_SZC_SHIFT) 175 + #define CS42XX8_TXCTL_DAC_SZC_ZC (1 << CS42XX8_TXCTL_DAC_SZC_SHIFT) 176 + #define CS42XX8_TXCTL_DAC_SZC_SR (2 << CS42XX8_TXCTL_DAC_SZC_SHIFT) 177 + #define CS42XX8_TXCTL_DAC_SZC_SRZC (3 << CS42XX8_TXCTL_DAC_SZC_SHIFT) 178 + #define CS42XX8_TXCTL_AMUTE_SHIFT 4 179 + #define CS42XX8_TXCTL_AMUTE_MASK (1 << CS42XX8_TXCTL_AMUTE_SHIFT) 180 + #define CS42XX8_TXCTL_AMUTE (1 << CS42XX8_TXCTL_AMUTE_SHIFT) 181 + #define CS42XX8_TXCTL_MUTE_ADC_SP_SHIFT 3 182 + #define CS42XX8_TXCTL_MUTE_ADC_SP_MASK (1 << CS42XX8_TXCTL_MUTE_ADC_SP_SHIFT) 183 + #define CS42XX8_TXCTL_MUTE_ADC_SP (1 << CS42XX8_TXCTL_MUTE_ADC_SP_SHIFT) 184 + #define CS42XX8_TXCTL_ADC_SNGVOL_SHIFT 2 185 + #define CS42XX8_TXCTL_ADC_SNGVOL_MASK (1 << CS42XX8_TXCTL_ADC_SNGVOL_SHIFT) 186 + #define CS42XX8_TXCTL_ADC_SNGVOL (1 << CS42XX8_TXCTL_ADC_SNGVOL_SHIFT) 187 + #define CS42XX8_TXCTL_ADC_SZC_SHIFT 0 188 + #define CS42XX8_TXCTL_ADC_SZC_MASK (((1 << CS42XX8_TXCTL_ADC_SZC_WIDTH) - 1) << CS42XX8_TXCTL_ADC_SZC_SHIFT) 189 + #define CS42XX8_TXCTL_ADC_SZC_IC (0 << CS42XX8_TXCTL_ADC_SZC_SHIFT) 190 + #define CS42XX8_TXCTL_ADC_SZC_ZC (1 << CS42XX8_TXCTL_ADC_SZC_SHIFT) 191 + #define CS42XX8_TXCTL_ADC_SZC_SR (2 << CS42XX8_TXCTL_ADC_SZC_SHIFT) 192 + #define CS42XX8_TXCTL_ADC_SZC_SRZC (3 << CS42XX8_TXCTL_ADC_SZC_SHIFT) 193 + 194 + /* DAC Channel Mute (Address 07h) */ 195 + #define CS42XX8_DACMUTE_AOUT(n) (0x1 << n) 196 + #define CS42XX8_DACMUTE_ALL 0xff 197 + 198 + /* Status Control (Address 18h)*/ 199 + #define CS42XX8_STATUSCTL_INI_SHIFT 2 200 + #define CS42XX8_STATUSCTL_INI_WIDTH 2 201 + #define CS42XX8_STATUSCTL_INI_MASK (((1 << CS42XX8_STATUSCTL_INI_WIDTH) - 1) << CS42XX8_STATUSCTL_INI_SHIFT) 202 + #define CS42XX8_STATUSCTL_INT_ACTIVE_HIGH (0 << CS42XX8_STATUSCTL_INI_SHIFT) 203 + #define CS42XX8_STATUSCTL_INT_ACTIVE_LOW (1 << CS42XX8_STATUSCTL_INI_SHIFT) 204 + #define CS42XX8_STATUSCTL_INT_OPEN_DRAIN (2 << CS42XX8_STATUSCTL_INI_SHIFT) 205 + 206 + /* Status (Address 19h)*/ 207 + #define CS42XX8_STATUS_DAC_CLK_ERR_SHIFT 4 208 + #define CS42XX8_STATUS_DAC_CLK_ERR_MASK (1 << CS42XX8_STATUS_DAC_CLK_ERR_SHIFT) 209 + #define CS42XX8_STATUS_ADC_CLK_ERR_SHIFT 3 210 + #define CS42XX8_STATUS_ADC_CLK_ERR_MASK (1 << CS42XX8_STATUS_ADC_CLK_ERR_SHIFT) 211 + #define CS42XX8_STATUS_ADC3_OVFL_SHIFT 2 212 + #define CS42XX8_STATUS_ADC3_OVFL_MASK (1 << CS42XX8_STATUS_ADC3_OVFL_SHIFT) 213 + #define CS42XX8_STATUS_ADC2_OVFL_SHIFT 1 214 + #define CS42XX8_STATUS_ADC2_OVFL_MASK (1 << CS42XX8_STATUS_ADC2_OVFL_SHIFT) 215 + #define CS42XX8_STATUS_ADC1_OVFL_SHIFT 0 216 + #define CS42XX8_STATUS_ADC1_OVFL_MASK (1 << CS42XX8_STATUS_ADC1_OVFL_SHIFT) 217 + 218 + /* Status Mask (Address 1Ah) */ 219 + #define CS42XX8_STATUS_DAC_CLK_ERR_M_SHIFT 4 220 + #define CS42XX8_STATUS_DAC_CLK_ERR_M_MASK (1 << CS42XX8_STATUS_DAC_CLK_ERR_M_SHIFT) 221 + #define CS42XX8_STATUS_ADC_CLK_ERR_M_SHIFT 3 222 + #define CS42XX8_STATUS_ADC_CLK_ERR_M_MASK (1 << CS42XX8_STATUS_ADC_CLK_ERR_M_SHIFT) 223 + #define CS42XX8_STATUS_ADC3_OVFL_M_SHIFT 2 224 + #define CS42XX8_STATUS_ADC3_OVFL_M_MASK (1 << CS42XX8_STATUS_ADC3_OVFL_M_SHIFT) 225 + #define CS42XX8_STATUS_ADC2_OVFL_M_SHIFT 1 226 + #define CS42XX8_STATUS_ADC2_OVFL_M_MASK (1 << CS42XX8_STATUS_ADC2_OVFL_M_SHIFT) 227 + #define CS42XX8_STATUS_ADC1_OVFL_M_SHIFT 0 228 + #define CS42XX8_STATUS_ADC1_OVFL_M_MASK (1 << CS42XX8_STATUS_ADC1_OVFL_M_SHIFT) 229 + 230 + /* MUTEC Pin Control (Address 1Bh) */ 231 + #define CS42XX8_MUTEC_MCPOLARITY_SHIFT 1 232 + #define CS42XX8_MUTEC_MCPOLARITY_MASK (1 << CS42XX8_MUTEC_MCPOLARITY_SHIFT) 233 + #define CS42XX8_MUTEC_MCPOLARITY_ACTIVE_LOW (0 << CS42XX8_MUTEC_MCPOLARITY_SHIFT) 234 + #define CS42XX8_MUTEC_MCPOLARITY_ACTIVE_HIGH (1 << CS42XX8_MUTEC_MCPOLARITY_SHIFT) 235 + #define CS42XX8_MUTEC_MUTEC_ACTIVE_SHIFT 0 236 + #define CS42XX8_MUTEC_MUTEC_ACTIVE_MASK (1 << CS42XX8_MUTEC_MUTEC_ACTIVE_SHIFT) 237 + #define CS42XX8_MUTEC_MUTEC_ACTIVE (1 << CS42XX8_MUTEC_MUTEC_ACTIVE_SHIFT) 238 + #endif /* _CS42XX8_H */