1 // SPDX-License-Identifier: GPL-2.0 2 // 3 // JZ4725B CODEC driver 4 // 5 // Copyright (C) 2019, Paul Cercueil <paul@crapouillou.net> 6 7 #include <linux/kernel.h> 8 #include <linux/module.h> 9 #include <linux/platform_device.h> 10 #include <linux/slab.h> 11 #include <linux/io.h> 12 #include <linux/iopoll.h> 13 #include <linux/regmap.h> 14 #include <linux/clk.h> 15 16 #include <linux/delay.h> 17 18 #include <sound/core.h> 19 #include <sound/pcm.h> 20 #include <sound/pcm_params.h> 21 #include <sound/initval.h> 22 #include <sound/soc.h> 23 #include <sound/tlv.h> 24 25 #define ICDC_RGADW_OFFSET 0x00 26 #define ICDC_RGDATA_OFFSET 0x04 27 28 /* ICDC internal register access control register(RGADW) */ 29 #define ICDC_RGADW_RGWR BIT(16) 30 31 #define ICDC_RGADW_RGADDR_OFFSET 8 32 #define ICDC_RGADW_RGADDR_MASK GENMASK(14, ICDC_RGADW_RGADDR_OFFSET) 33 34 #define ICDC_RGADW_RGDIN_OFFSET 0 35 #define ICDC_RGADW_RGDIN_MASK GENMASK(7, ICDC_RGADW_RGDIN_OFFSET) 36 37 /* ICDC internal register data output register (RGDATA)*/ 38 #define ICDC_RGDATA_IRQ BIT(8) 39 40 #define ICDC_RGDATA_RGDOUT_OFFSET 0 41 #define ICDC_RGDATA_RGDOUT_MASK GENMASK(7, ICDC_RGDATA_RGDOUT_OFFSET) 42 43 /* JZ internal register space */ 44 enum { 45 JZ4725B_CODEC_REG_AICR, 46 JZ4725B_CODEC_REG_CR1, 47 JZ4725B_CODEC_REG_CR2, 48 JZ4725B_CODEC_REG_CCR1, 49 JZ4725B_CODEC_REG_CCR2, 50 JZ4725B_CODEC_REG_PMR1, 51 JZ4725B_CODEC_REG_PMR2, 52 JZ4725B_CODEC_REG_CRR, 53 JZ4725B_CODEC_REG_ICR, 54 JZ4725B_CODEC_REG_IFR, 55 JZ4725B_CODEC_REG_CGR1, 56 JZ4725B_CODEC_REG_CGR2, 57 JZ4725B_CODEC_REG_CGR3, 58 JZ4725B_CODEC_REG_CGR4, 59 JZ4725B_CODEC_REG_CGR5, 60 JZ4725B_CODEC_REG_CGR6, 61 JZ4725B_CODEC_REG_CGR7, 62 JZ4725B_CODEC_REG_CGR8, 63 JZ4725B_CODEC_REG_CGR9, 64 JZ4725B_CODEC_REG_CGR10, 65 JZ4725B_CODEC_REG_TR1, 66 JZ4725B_CODEC_REG_TR2, 67 JZ4725B_CODEC_REG_CR3, 68 JZ4725B_CODEC_REG_AGC1, 69 JZ4725B_CODEC_REG_AGC2, 70 JZ4725B_CODEC_REG_AGC3, 71 JZ4725B_CODEC_REG_AGC4, 72 JZ4725B_CODEC_REG_AGC5, 73 }; 74 75 #define REG_AICR_CONFIG1_OFFSET 0 76 #define REG_AICR_CONFIG1_MASK (0xf << REG_AICR_CONFIG1_OFFSET) 77 78 #define REG_CR1_SB_MICBIAS_OFFSET 7 79 #define REG_CR1_MONO_OFFSET 6 80 #define REG_CR1_DAC_MUTE_OFFSET 5 81 #define REG_CR1_HP_DIS_OFFSET 4 82 #define REG_CR1_DACSEL_OFFSET 3 83 #define REG_CR1_BYPASS_OFFSET 2 84 85 #define REG_CR2_DAC_DEEMP_OFFSET 7 86 #define REG_CR2_DAC_ADWL_OFFSET 5 87 #define REG_CR2_DAC_ADWL_MASK (0x3 << REG_CR2_DAC_ADWL_OFFSET) 88 #define REG_CR2_ADC_ADWL_OFFSET 3 89 #define REG_CR2_ADC_ADWL_MASK (0x3 << REG_CR2_ADC_ADWL_OFFSET) 90 #define REG_CR2_ADC_HPF_OFFSET 2 91 92 #define REG_CR3_SB_MIC1_OFFSET 7 93 #define REG_CR3_SB_MIC2_OFFSET 6 94 #define REG_CR3_SIDETONE1_OFFSET 5 95 #define REG_CR3_SIDETONE2_OFFSET 4 96 #define REG_CR3_MICDIFF_OFFSET 3 97 #define REG_CR3_MICSTEREO_OFFSET 2 98 #define REG_CR3_INSEL_OFFSET 0 99 #define REG_CR3_INSEL_MASK (0x3 << REG_CR3_INSEL_OFFSET) 100 101 #define REG_CCR1_CONFIG4_OFFSET 0 102 #define REG_CCR1_CONFIG4_MASK (0xf << REG_CCR1_CONFIG4_OFFSET) 103 104 #define REG_CCR2_DFREQ_OFFSET 4 105 #define REG_CCR2_DFREQ_MASK (0xf << REG_CCR2_DFREQ_OFFSET) 106 #define REG_CCR2_AFREQ_OFFSET 0 107 #define REG_CCR2_AFREQ_MASK (0xf << REG_CCR2_AFREQ_OFFSET) 108 109 #define REG_PMR1_SB_DAC_OFFSET 7 110 #define REG_PMR1_SB_OUT_OFFSET 6 111 #define REG_PMR1_SB_MIX_OFFSET 5 112 #define REG_PMR1_SB_ADC_OFFSET 4 113 #define REG_PMR1_SB_LIN_OFFSET 3 114 #define REG_PMR1_SB_IND_OFFSET 0 115 116 #define REG_PMR2_LRGI_OFFSET 7 117 #define REG_PMR2_RLGI_OFFSET 6 118 #define REG_PMR2_LRGOD_OFFSET 5 119 #define REG_PMR2_RLGOD_OFFSET 4 120 #define REG_PMR2_GIM_OFFSET 3 121 #define REG_PMR2_SB_MC_OFFSET 2 122 #define REG_PMR2_SB_OFFSET 1 123 #define REG_PMR2_SB_SLEEP_OFFSET 0 124 125 #define REG_IFR_RAMP_UP_DONE_OFFSET 3 126 #define REG_IFR_RAMP_DOWN_DONE_OFFSET 2 127 128 #define REG_CGR1_GODL_OFFSET 4 129 #define REG_CGR1_GODL_MASK (0xf << REG_CGR1_GODL_OFFSET) 130 #define REG_CGR1_GODR_OFFSET 0 131 #define REG_CGR1_GODR_MASK (0xf << REG_CGR1_GODR_OFFSET) 132 133 #define REG_CGR2_GO1R_OFFSET 0 134 #define REG_CGR2_GO1R_MASK (0x1f << REG_CGR2_GO1R_OFFSET) 135 136 #define REG_CGR3_GO1L_OFFSET 0 137 #define REG_CGR3_GO1L_MASK (0x1f << REG_CGR3_GO1L_OFFSET) 138 139 #define REG_CGR4_GO2R_OFFSET 0 140 #define REG_CGR4_GO2R_MASK (0x1f << REG_CGR4_GO2R_OFFSET) 141 142 #define REG_CGR5_GO2L_OFFSET 0 143 #define REG_CGR5_GO2L_MASK (0x1f << REG_CGR5_GO2L_OFFSET) 144 145 #define REG_CGR6_GO3R_OFFSET 0 146 #define REG_CGR6_GO3R_MASK (0x1f << REG_CGR6_GO3R_OFFSET) 147 148 #define REG_CGR7_GO3L_OFFSET 0 149 #define REG_CGR7_GO3L_MASK (0x1f << REG_CGR7_GO3L_OFFSET) 150 151 #define REG_CGR8_GOR_OFFSET 0 152 #define REG_CGR8_GOR_MASK (0x1f << REG_CGR8_GOR_OFFSET) 153 154 #define REG_CGR9_GOL_OFFSET 0 155 #define REG_CGR9_GOL_MASK (0x1f << REG_CGR9_GOL_OFFSET) 156 157 #define REG_CGR10_GIL_OFFSET 0 158 #define REG_CGR10_GIR_OFFSET 4 159 160 struct jz_icdc { 161 struct regmap *regmap; 162 void __iomem *base; 163 struct clk *clk; 164 }; 165 166 static const SNDRV_CTL_TLVD_DECLARE_DB_SCALE(jz4725b_adc_tlv, 0, 150, 0); 167 static const SNDRV_CTL_TLVD_DECLARE_DB_SCALE(jz4725b_dac_tlv, -2250, 150, 0); 168 static const SNDRV_CTL_TLVD_DECLARE_DB_RANGE(jz4725b_mix_tlv, 169 0, 11, TLV_DB_SCALE_ITEM(-2250, 0, 0), 170 12, 31, TLV_DB_SCALE_ITEM(-2250, 150, 0), 171 ); 172 173 static const SNDRV_CTL_TLVD_DECLARE_DB_RANGE(jz4725b_out_tlv, 174 0, 11, TLV_DB_SCALE_ITEM(-3350, 200, 0), 175 12, 23, TLV_DB_SCALE_ITEM(-1050, 100, 0), 176 24, 31, TLV_DB_SCALE_ITEM( 100, 50, 0), 177 ); 178 static const SNDRV_CTL_TLVD_DECLARE_DB_SCALE(jz4725b_mic_boost_tlv, 0, 2000, 0); 179 180 static const char * const jz4725b_mic_mode_texts[] = { 181 "Single Ended", "Differential", 182 }; 183 184 static const struct soc_enum jz4725b_mic_mode_enum = 185 SOC_ENUM_SINGLE(JZ4725B_CODEC_REG_CR3, REG_CR3_MICDIFF_OFFSET, 186 2, jz4725b_mic_mode_texts); 187 188 static const struct snd_kcontrol_new jz4725b_codec_controls[] = { 189 SOC_DOUBLE_TLV("DAC Playback Volume", 190 JZ4725B_CODEC_REG_CGR1, 191 REG_CGR1_GODL_OFFSET, 192 REG_CGR1_GODR_OFFSET, 193 0xf, 1, jz4725b_dac_tlv), 194 SOC_DOUBLE_TLV("Master Capture Volume", 195 JZ4725B_CODEC_REG_CGR10, 196 REG_CGR10_GIL_OFFSET, 197 REG_CGR10_GIR_OFFSET, 198 0xf, 0, jz4725b_adc_tlv), 199 SOC_DOUBLE_R_TLV("Mixer Line In Bypass Playback Volume", 200 JZ4725B_CODEC_REG_CGR3, 201 JZ4725B_CODEC_REG_CGR2, 202 REG_CGR2_GO1R_OFFSET, 203 0x1f, 1, jz4725b_mix_tlv), 204 SOC_DOUBLE_R_TLV("Mixer Mic 1 Bypass Playback Volume", 205 JZ4725B_CODEC_REG_CGR5, 206 JZ4725B_CODEC_REG_CGR4, 207 REG_CGR4_GO2R_OFFSET, 208 0x1f, 1, jz4725b_mix_tlv), 209 SOC_DOUBLE_R_TLV("Mixer Mic 2 Bypass Playback Volume", 210 JZ4725B_CODEC_REG_CGR7, 211 JZ4725B_CODEC_REG_CGR6, 212 REG_CGR6_GO3R_OFFSET, 213 0x1f, 1, jz4725b_mix_tlv), 214 215 SOC_DOUBLE_R_TLV("Master Playback Volume", 216 JZ4725B_CODEC_REG_CGR9, 217 JZ4725B_CODEC_REG_CGR8, 218 REG_CGR8_GOR_OFFSET, 219 0x1f, 1, jz4725b_out_tlv), 220 221 SOC_SINGLE("DAC Playback Switch", JZ4725B_CODEC_REG_CR1, 222 REG_CR1_DAC_MUTE_OFFSET, 1, 1), 223 224 SOC_SINGLE("Deemphasize Filter Playback Switch", 225 JZ4725B_CODEC_REG_CR2, 226 REG_CR2_DAC_DEEMP_OFFSET, 1, 0), 227 228 SOC_SINGLE("High-Pass Filter Capture Switch", 229 JZ4725B_CODEC_REG_CR2, 230 REG_CR2_ADC_HPF_OFFSET, 1, 0), 231 232 SOC_ENUM("Mic Mode Capture Switch", jz4725b_mic_mode_enum), 233 234 SOC_SINGLE_TLV("Mic1 Boost Capture Volume", 235 JZ4725B_CODEC_REG_PMR2, 236 REG_PMR2_GIM_OFFSET, 237 1, 0, jz4725b_mic_boost_tlv), 238 }; 239 240 static const char * const jz4725b_codec_adc_src_texts[] = { 241 "Mic 1", "Mic 2", "Line In", "Mixer", 242 }; 243 static const unsigned int jz4725b_codec_adc_src_values[] = { 0, 1, 2, 3, }; 244 static SOC_VALUE_ENUM_SINGLE_DECL(jz4725b_codec_adc_src_enum, 245 JZ4725B_CODEC_REG_CR3, 246 REG_CR3_INSEL_OFFSET, 247 REG_CR3_INSEL_MASK, 248 jz4725b_codec_adc_src_texts, 249 jz4725b_codec_adc_src_values); 250 static const struct snd_kcontrol_new jz4725b_codec_adc_src_ctrl = 251 SOC_DAPM_ENUM("ADC Source Capture Route", jz4725b_codec_adc_src_enum); 252 253 static const struct snd_kcontrol_new jz4725b_codec_mixer_controls[] = { 254 SOC_DAPM_SINGLE("Line In Bypass Playback Switch", JZ4725B_CODEC_REG_CR1, 255 REG_CR1_BYPASS_OFFSET, 1, 0), 256 SOC_DAPM_SINGLE("Mic 1 Bypass Playback Switch", JZ4725B_CODEC_REG_CR3, 257 REG_CR3_SIDETONE1_OFFSET, 1, 0), 258 SOC_DAPM_SINGLE("Mic 2 Bypass Playback Switch", JZ4725B_CODEC_REG_CR3, 259 REG_CR3_SIDETONE2_OFFSET, 1, 0), 260 }; 261 262 static int jz4725b_out_stage_enable(struct snd_soc_dapm_widget *w, 263 struct snd_kcontrol *kcontrol, 264 int event) 265 { 266 struct snd_soc_component *codec = snd_soc_dapm_to_component(w->dapm); 267 struct jz_icdc *icdc = snd_soc_component_get_drvdata(codec); 268 struct regmap *map = icdc->regmap; 269 unsigned int val; 270 271 switch (event) { 272 case SND_SOC_DAPM_PRE_PMU: 273 return regmap_clear_bits(map, JZ4725B_CODEC_REG_IFR, 274 BIT(REG_IFR_RAMP_UP_DONE_OFFSET)); 275 case SND_SOC_DAPM_POST_PMU: 276 return regmap_read_poll_timeout(map, JZ4725B_CODEC_REG_IFR, 277 val, val & BIT(REG_IFR_RAMP_UP_DONE_OFFSET), 278 100000, 500000); 279 case SND_SOC_DAPM_PRE_PMD: 280 return regmap_clear_bits(map, JZ4725B_CODEC_REG_IFR, 281 BIT(REG_IFR_RAMP_DOWN_DONE_OFFSET)); 282 case SND_SOC_DAPM_POST_PMD: 283 return regmap_read_poll_timeout(map, JZ4725B_CODEC_REG_IFR, 284 val, val & BIT(REG_IFR_RAMP_DOWN_DONE_OFFSET), 285 100000, 500000); 286 default: 287 return -EINVAL; 288 } 289 } 290 291 static const struct snd_soc_dapm_widget jz4725b_codec_dapm_widgets[] = { 292 /* DAC */ 293 SND_SOC_DAPM_DAC("DAC", "Playback", 294 JZ4725B_CODEC_REG_PMR1, REG_PMR1_SB_DAC_OFFSET, 1), 295 296 /* ADC */ 297 SND_SOC_DAPM_ADC("ADC", "Capture", 298 JZ4725B_CODEC_REG_PMR1, REG_PMR1_SB_ADC_OFFSET, 1), 299 300 SND_SOC_DAPM_MUX("ADC Source Capture Route", SND_SOC_NOPM, 0, 0, 301 &jz4725b_codec_adc_src_ctrl), 302 303 /* Mixer */ 304 SND_SOC_DAPM_MIXER("Mixer", JZ4725B_CODEC_REG_PMR1, 305 REG_PMR1_SB_MIX_OFFSET, 1, 306 jz4725b_codec_mixer_controls, 307 ARRAY_SIZE(jz4725b_codec_mixer_controls)), 308 SND_SOC_DAPM_MIXER("DAC to Mixer", JZ4725B_CODEC_REG_CR1, 309 REG_CR1_DACSEL_OFFSET, 0, NULL, 0), 310 311 SND_SOC_DAPM_MIXER("Line In", JZ4725B_CODEC_REG_PMR1, 312 REG_PMR1_SB_LIN_OFFSET, 1, NULL, 0), 313 SND_SOC_DAPM_MIXER("HP Out", JZ4725B_CODEC_REG_CR1, 314 REG_CR1_HP_DIS_OFFSET, 1, NULL, 0), 315 316 SND_SOC_DAPM_MIXER("Mic 1", JZ4725B_CODEC_REG_CR3, 317 REG_CR3_SB_MIC1_OFFSET, 1, NULL, 0), 318 SND_SOC_DAPM_MIXER("Mic 2", JZ4725B_CODEC_REG_CR3, 319 REG_CR3_SB_MIC2_OFFSET, 1, NULL, 0), 320 321 SND_SOC_DAPM_MIXER_E("Out Stage", JZ4725B_CODEC_REG_PMR1, 322 REG_PMR1_SB_OUT_OFFSET, 1, NULL, 0, 323 jz4725b_out_stage_enable, 324 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU | 325 SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD), 326 SND_SOC_DAPM_MIXER("Mixer to ADC", JZ4725B_CODEC_REG_PMR1, 327 REG_PMR1_SB_IND_OFFSET, 1, NULL, 0), 328 329 SND_SOC_DAPM_SUPPLY("Mic Bias", JZ4725B_CODEC_REG_CR1, 330 REG_CR1_SB_MICBIAS_OFFSET, 1, NULL, 0), 331 332 /* Pins */ 333 SND_SOC_DAPM_INPUT("MIC1P"), 334 SND_SOC_DAPM_INPUT("MIC1N"), 335 SND_SOC_DAPM_INPUT("MIC2P"), 336 SND_SOC_DAPM_INPUT("MIC2N"), 337 338 SND_SOC_DAPM_INPUT("LLINEIN"), 339 SND_SOC_DAPM_INPUT("RLINEIN"), 340 341 SND_SOC_DAPM_OUTPUT("LHPOUT"), 342 SND_SOC_DAPM_OUTPUT("RHPOUT"), 343 }; 344 345 static const struct snd_soc_dapm_route jz4725b_codec_dapm_routes[] = { 346 {"Mic 1", NULL, "MIC1P"}, 347 {"Mic 1", NULL, "MIC1N"}, 348 {"Mic 2", NULL, "MIC2P"}, 349 {"Mic 2", NULL, "MIC2N"}, 350 351 {"Line In", NULL, "LLINEIN"}, 352 {"Line In", NULL, "RLINEIN"}, 353 354 {"Mixer", "Mic 1 Bypass Playback Switch", "Mic 1"}, 355 {"Mixer", "Mic 2 Bypass Playback Switch", "Mic 2"}, 356 {"Mixer", "Line In Bypass Playback Switch", "Line In"}, 357 {"DAC to Mixer", NULL, "DAC"}, 358 {"Mixer", NULL, "DAC to Mixer"}, 359 360 {"Mixer to ADC", NULL, "Mixer"}, 361 {"ADC Source Capture Route", "Mixer", "Mixer to ADC"}, 362 {"ADC Source Capture Route", "Line In", "Line In"}, 363 {"ADC Source Capture Route", "Mic 1", "Mic 1"}, 364 {"ADC Source Capture Route", "Mic 2", "Mic 2"}, 365 {"ADC", NULL, "ADC Source Capture Route"}, 366 367 {"Out Stage", NULL, "Mixer"}, 368 {"HP Out", NULL, "Out Stage"}, 369 {"LHPOUT", NULL, "HP Out"}, 370 {"RHPOUT", NULL, "HP Out"}, 371 }; 372 373 static int jz4725b_codec_set_bias_level(struct snd_soc_component *component, 374 enum snd_soc_bias_level level) 375 { 376 struct jz_icdc *icdc = snd_soc_component_get_drvdata(component); 377 struct regmap *map = icdc->regmap; 378 379 switch (level) { 380 case SND_SOC_BIAS_ON: 381 regmap_clear_bits(map, JZ4725B_CODEC_REG_PMR2, 382 BIT(REG_PMR2_SB_SLEEP_OFFSET)); 383 break; 384 case SND_SOC_BIAS_PREPARE: 385 /* Enable sound hardware */ 386 regmap_clear_bits(map, JZ4725B_CODEC_REG_PMR2, 387 BIT(REG_PMR2_SB_OFFSET)); 388 msleep(224); 389 break; 390 case SND_SOC_BIAS_STANDBY: 391 regmap_set_bits(map, JZ4725B_CODEC_REG_PMR2, 392 BIT(REG_PMR2_SB_SLEEP_OFFSET)); 393 break; 394 case SND_SOC_BIAS_OFF: 395 regmap_set_bits(map, JZ4725B_CODEC_REG_PMR2, 396 BIT(REG_PMR2_SB_OFFSET)); 397 break; 398 } 399 400 return 0; 401 } 402 403 static int jz4725b_codec_dev_probe(struct snd_soc_component *component) 404 { 405 struct jz_icdc *icdc = snd_soc_component_get_drvdata(component); 406 struct regmap *map = icdc->regmap; 407 408 clk_prepare_enable(icdc->clk); 409 410 /* Write CONFIGn (n=1 to 8) bits. 411 * The value 0x0f is specified in the datasheet as a requirement. 412 */ 413 regmap_write(map, JZ4725B_CODEC_REG_AICR, 414 0xf << REG_AICR_CONFIG1_OFFSET); 415 regmap_write(map, JZ4725B_CODEC_REG_CCR1, 416 0x0 << REG_CCR1_CONFIG4_OFFSET); 417 418 return 0; 419 } 420 421 static void jz4725b_codec_dev_remove(struct snd_soc_component *component) 422 { 423 struct jz_icdc *icdc = snd_soc_component_get_drvdata(component); 424 425 clk_disable_unprepare(icdc->clk); 426 } 427 428 static const struct snd_soc_component_driver jz4725b_codec = { 429 .probe = jz4725b_codec_dev_probe, 430 .remove = jz4725b_codec_dev_remove, 431 .set_bias_level = jz4725b_codec_set_bias_level, 432 .controls = jz4725b_codec_controls, 433 .num_controls = ARRAY_SIZE(jz4725b_codec_controls), 434 .dapm_widgets = jz4725b_codec_dapm_widgets, 435 .num_dapm_widgets = ARRAY_SIZE(jz4725b_codec_dapm_widgets), 436 .dapm_routes = jz4725b_codec_dapm_routes, 437 .num_dapm_routes = ARRAY_SIZE(jz4725b_codec_dapm_routes), 438 .suspend_bias_off = 1, 439 .use_pmdown_time = 1, 440 }; 441 442 static const unsigned int jz4725b_codec_sample_rates[] = { 443 96000, 48000, 44100, 32000, 444 24000, 22050, 16000, 12000, 445 11025, 9600, 8000, 446 }; 447 448 static int jz4725b_codec_hw_params(struct snd_pcm_substream *substream, 449 struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) 450 { 451 struct jz_icdc *icdc = snd_soc_component_get_drvdata(dai->component); 452 unsigned int rate, bit_width; 453 454 switch (params_format(params)) { 455 case SNDRV_PCM_FORMAT_S16_LE: 456 bit_width = 0; 457 break; 458 case SNDRV_PCM_FORMAT_S18_3LE: 459 bit_width = 1; 460 break; 461 case SNDRV_PCM_FORMAT_S20_3LE: 462 bit_width = 2; 463 break; 464 case SNDRV_PCM_FORMAT_S24_3LE: 465 bit_width = 3; 466 break; 467 default: 468 return -EINVAL; 469 } 470 471 for (rate = 0; rate < ARRAY_SIZE(jz4725b_codec_sample_rates); rate++) { 472 if (jz4725b_codec_sample_rates[rate] == params_rate(params)) 473 break; 474 } 475 476 if (rate == ARRAY_SIZE(jz4725b_codec_sample_rates)) 477 return -EINVAL; 478 479 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { 480 regmap_update_bits(icdc->regmap, 481 JZ4725B_CODEC_REG_CR2, 482 REG_CR2_DAC_ADWL_MASK, 483 bit_width << REG_CR2_DAC_ADWL_OFFSET); 484 485 regmap_update_bits(icdc->regmap, 486 JZ4725B_CODEC_REG_CCR2, 487 REG_CCR2_DFREQ_MASK, 488 rate << REG_CCR2_DFREQ_OFFSET); 489 } else { 490 regmap_update_bits(icdc->regmap, 491 JZ4725B_CODEC_REG_CR2, 492 REG_CR2_ADC_ADWL_MASK, 493 bit_width << REG_CR2_ADC_ADWL_OFFSET); 494 495 regmap_update_bits(icdc->regmap, 496 JZ4725B_CODEC_REG_CCR2, 497 REG_CCR2_AFREQ_MASK, 498 rate << REG_CCR2_AFREQ_OFFSET); 499 } 500 501 return 0; 502 } 503 504 static const struct snd_soc_dai_ops jz4725b_codec_dai_ops = { 505 .hw_params = jz4725b_codec_hw_params, 506 }; 507 508 #define JZ_ICDC_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S18_3LE | \ 509 SNDRV_PCM_FMTBIT_S20_3LE | SNDRV_PCM_FMTBIT_S24_3LE) 510 511 static struct snd_soc_dai_driver jz4725b_codec_dai = { 512 .name = "jz4725b-hifi", 513 .playback = { 514 .stream_name = "Playback", 515 .channels_min = 2, 516 .channels_max = 2, 517 .rates = SNDRV_PCM_RATE_8000_96000, 518 .formats = JZ_ICDC_FORMATS, 519 }, 520 .capture = { 521 .stream_name = "Capture", 522 .channels_min = 2, 523 .channels_max = 2, 524 .rates = SNDRV_PCM_RATE_8000_96000, 525 .formats = JZ_ICDC_FORMATS, 526 }, 527 .ops = &jz4725b_codec_dai_ops, 528 }; 529 530 static bool jz4725b_codec_volatile(struct device *dev, unsigned int reg) 531 { 532 return reg == JZ4725B_CODEC_REG_IFR; 533 } 534 535 static bool jz4725b_codec_can_access_reg(struct device *dev, unsigned int reg) 536 { 537 return (reg != JZ4725B_CODEC_REG_TR1) && (reg != JZ4725B_CODEC_REG_TR2); 538 } 539 540 static int jz4725b_codec_io_wait(struct jz_icdc *icdc) 541 { 542 u32 reg; 543 544 return readl_poll_timeout(icdc->base + ICDC_RGADW_OFFSET, reg, 545 !(reg & ICDC_RGADW_RGWR), 1000, 10000); 546 } 547 548 static int jz4725b_codec_reg_read(void *context, unsigned int reg, 549 unsigned int *val) 550 { 551 struct jz_icdc *icdc = context; 552 unsigned int i; 553 u32 tmp; 554 int ret; 555 556 ret = jz4725b_codec_io_wait(icdc); 557 if (ret) 558 return ret; 559 560 tmp = readl(icdc->base + ICDC_RGADW_OFFSET); 561 tmp = (tmp & ~ICDC_RGADW_RGADDR_MASK) 562 | (reg << ICDC_RGADW_RGADDR_OFFSET); 563 writel(tmp, icdc->base + ICDC_RGADW_OFFSET); 564 565 /* wait 6+ cycles */ 566 for (i = 0; i < 6; i++) 567 *val = readl(icdc->base + ICDC_RGDATA_OFFSET) & 568 ICDC_RGDATA_RGDOUT_MASK; 569 570 return 0; 571 } 572 573 static int jz4725b_codec_reg_write(void *context, unsigned int reg, 574 unsigned int val) 575 { 576 struct jz_icdc *icdc = context; 577 int ret; 578 579 ret = jz4725b_codec_io_wait(icdc); 580 if (ret) 581 return ret; 582 583 writel(ICDC_RGADW_RGWR | (reg << ICDC_RGADW_RGADDR_OFFSET) | val, 584 icdc->base + ICDC_RGADW_OFFSET); 585 586 ret = jz4725b_codec_io_wait(icdc); 587 if (ret) 588 return ret; 589 590 return 0; 591 } 592 593 static const u8 jz4725b_codec_reg_defaults[] = { 594 0x0c, 0xaa, 0x78, 0x00, 0x00, 0xff, 0x03, 0x51, 595 0x3f, 0x00, 0x00, 0x04, 0x04, 0x04, 0x04, 0x04, 596 0x04, 0x0a, 0x0a, 0x00, 0x00, 0x00, 0xc0, 0x34, 597 0x07, 0x44, 0x1f, 0x00, 598 }; 599 600 static const struct regmap_config jz4725b_codec_regmap_config = { 601 .reg_bits = 7, 602 .val_bits = 8, 603 604 .max_register = JZ4725B_CODEC_REG_AGC5, 605 .volatile_reg = jz4725b_codec_volatile, 606 .readable_reg = jz4725b_codec_can_access_reg, 607 .writeable_reg = jz4725b_codec_can_access_reg, 608 609 .reg_read = jz4725b_codec_reg_read, 610 .reg_write = jz4725b_codec_reg_write, 611 612 .reg_defaults_raw = jz4725b_codec_reg_defaults, 613 .num_reg_defaults_raw = ARRAY_SIZE(jz4725b_codec_reg_defaults), 614 .cache_type = REGCACHE_FLAT, 615 }; 616 617 static int jz4725b_codec_probe(struct platform_device *pdev) 618 { 619 struct device *dev = &pdev->dev; 620 struct jz_icdc *icdc; 621 int ret; 622 623 icdc = devm_kzalloc(dev, sizeof(*icdc), GFP_KERNEL); 624 if (!icdc) 625 return -ENOMEM; 626 627 icdc->base = devm_platform_ioremap_resource(pdev, 0); 628 if (IS_ERR(icdc->base)) 629 return PTR_ERR(icdc->base); 630 631 icdc->regmap = devm_regmap_init(dev, NULL, icdc, 632 &jz4725b_codec_regmap_config); 633 if (IS_ERR(icdc->regmap)) 634 return PTR_ERR(icdc->regmap); 635 636 icdc->clk = devm_clk_get(&pdev->dev, "aic"); 637 if (IS_ERR(icdc->clk)) 638 return PTR_ERR(icdc->clk); 639 640 platform_set_drvdata(pdev, icdc); 641 642 ret = devm_snd_soc_register_component(dev, &jz4725b_codec, 643 &jz4725b_codec_dai, 1); 644 if (ret) 645 dev_err(dev, "Failed to register codec\n"); 646 647 return ret; 648 } 649 650 static const struct of_device_id jz4725b_codec_of_matches[] = { 651 { .compatible = "ingenic,jz4725b-codec", }, 652 { } 653 }; 654 MODULE_DEVICE_TABLE(of, jz4725b_codec_of_matches); 655 656 static struct platform_driver jz4725b_codec_driver = { 657 .probe = jz4725b_codec_probe, 658 .driver = { 659 .name = "jz4725b-codec", 660 .of_match_table = jz4725b_codec_of_matches, 661 }, 662 }; 663 module_platform_driver(jz4725b_codec_driver); 664 665 MODULE_DESCRIPTION("JZ4725B SoC internal codec driver"); 666 MODULE_AUTHOR("Paul Cercueil <paul@crapouillou.net>"); 667 MODULE_LICENSE("GPL v2"); 668
Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.