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_CGR8_GOR_OFFSET 0 140 #define REG_CGR8_GOR_MASK (0x1f << REG_CGR8_GOR_OFFSET) 141 142 #define REG_CGR9_GOL_OFFSET 0 143 #define REG_CGR9_GOL_MASK (0x1f << REG_CGR9_GOL_OFFSET) 144 145 #define REG_CGR10_GIL_OFFSET 0 146 #define REG_CGR10_GIR_OFFSET 4 147 148 struct jz_icdc { 149 struct regmap *regmap; 150 void __iomem *base; 151 struct clk *clk; 152 }; 153 154 static const SNDRV_CTL_TLVD_DECLARE_DB_SCALE(jz4725b_adc_tlv, 0, 150, 0); 155 static const SNDRV_CTL_TLVD_DECLARE_DB_SCALE(jz4725b_dac_tlv, -2250, 150, 0); 156 static const SNDRV_CTL_TLVD_DECLARE_DB_RANGE(jz4725b_out_tlv, 157 0, 11, TLV_DB_SCALE_ITEM(-3350, 200, 0), 158 12, 23, TLV_DB_SCALE_ITEM(-1050, 100, 0), 159 24, 31, TLV_DB_SCALE_ITEM( 100, 50, 0), 160 ); 161 162 static const struct snd_kcontrol_new jz4725b_codec_controls[] = { 163 SOC_DOUBLE_TLV("DAC Playback Volume", 164 JZ4725B_CODEC_REG_CGR1, 165 REG_CGR1_GODL_OFFSET, 166 REG_CGR1_GODR_OFFSET, 167 0xf, 1, jz4725b_dac_tlv), 168 SOC_DOUBLE_TLV("Master Capture Volume", 169 JZ4725B_CODEC_REG_CGR10, 170 REG_CGR10_GIL_OFFSET, 171 REG_CGR10_GIR_OFFSET, 172 0xf, 0, jz4725b_adc_tlv), 173 174 SOC_DOUBLE_R_TLV("Master Playback Volume", 175 JZ4725B_CODEC_REG_CGR9, 176 JZ4725B_CODEC_REG_CGR8, 177 REG_CGR8_GOR_OFFSET, 178 0x1f, 1, jz4725b_out_tlv), 179 180 SOC_SINGLE("DAC Playback Switch", JZ4725B_CODEC_REG_CR1, 181 REG_CR1_DAC_MUTE_OFFSET, 1, 1), 182 183 SOC_SINGLE("Deemphasize Filter Playback Switch", 184 JZ4725B_CODEC_REG_CR2, 185 REG_CR2_DAC_DEEMP_OFFSET, 1, 0), 186 187 SOC_SINGLE("High-Pass Filter Capture Switch", 188 JZ4725B_CODEC_REG_CR2, 189 REG_CR2_ADC_HPF_OFFSET, 1, 0), 190 }; 191 192 static const char * const jz4725b_codec_adc_src_texts[] = { 193 "Mic 1", "Mic 2", "Line In", "Mixer", 194 }; 195 static const unsigned int jz4725b_codec_adc_src_values[] = { 0, 1, 2, 3, }; 196 static SOC_VALUE_ENUM_SINGLE_DECL(jz4725b_codec_adc_src_enum, 197 JZ4725B_CODEC_REG_CR3, 198 REG_CR3_INSEL_OFFSET, 199 REG_CR3_INSEL_MASK, 200 jz4725b_codec_adc_src_texts, 201 jz4725b_codec_adc_src_values); 202 static const struct snd_kcontrol_new jz4725b_codec_adc_src_ctrl = 203 SOC_DAPM_ENUM("ADC Source Capture Route", jz4725b_codec_adc_src_enum); 204 205 static const struct snd_kcontrol_new jz4725b_codec_mixer_controls[] = { 206 SOC_DAPM_SINGLE("Line In Bypass", JZ4725B_CODEC_REG_CR1, 207 REG_CR1_BYPASS_OFFSET, 1, 0), 208 }; 209 210 static int jz4725b_out_stage_enable(struct snd_soc_dapm_widget *w, 211 struct snd_kcontrol *kcontrol, 212 int event) 213 { 214 struct snd_soc_component *codec = snd_soc_dapm_to_component(w->dapm); 215 struct jz_icdc *icdc = snd_soc_component_get_drvdata(codec); 216 struct regmap *map = icdc->regmap; 217 unsigned int val; 218 219 switch (event) { 220 case SND_SOC_DAPM_PRE_PMU: 221 return regmap_clear_bits(map, JZ4725B_CODEC_REG_IFR, 222 BIT(REG_IFR_RAMP_UP_DONE_OFFSET)); 223 case SND_SOC_DAPM_POST_PMU: 224 return regmap_read_poll_timeout(map, JZ4725B_CODEC_REG_IFR, 225 val, val & BIT(REG_IFR_RAMP_UP_DONE_OFFSET), 226 100000, 500000); 227 case SND_SOC_DAPM_PRE_PMD: 228 return regmap_clear_bits(map, JZ4725B_CODEC_REG_IFR, 229 BIT(REG_IFR_RAMP_DOWN_DONE_OFFSET)); 230 case SND_SOC_DAPM_POST_PMD: 231 return regmap_read_poll_timeout(map, JZ4725B_CODEC_REG_IFR, 232 val, val & BIT(REG_IFR_RAMP_DOWN_DONE_OFFSET), 233 100000, 500000); 234 default: 235 return -EINVAL; 236 } 237 } 238 239 static const struct snd_soc_dapm_widget jz4725b_codec_dapm_widgets[] = { 240 /* DAC */ 241 SND_SOC_DAPM_DAC("DAC", "Playback", 242 JZ4725B_CODEC_REG_PMR1, REG_PMR1_SB_DAC_OFFSET, 1), 243 244 /* ADC */ 245 SND_SOC_DAPM_ADC("ADC", "Capture", 246 JZ4725B_CODEC_REG_PMR1, REG_PMR1_SB_ADC_OFFSET, 1), 247 248 SND_SOC_DAPM_MUX("ADC Source Capture Route", SND_SOC_NOPM, 0, 0, 249 &jz4725b_codec_adc_src_ctrl), 250 251 /* Mixer */ 252 SND_SOC_DAPM_MIXER("Mixer", JZ4725B_CODEC_REG_PMR1, 253 REG_PMR1_SB_MIX_OFFSET, 1, 254 jz4725b_codec_mixer_controls, 255 ARRAY_SIZE(jz4725b_codec_mixer_controls)), 256 SND_SOC_DAPM_MIXER("DAC to Mixer", JZ4725B_CODEC_REG_CR1, 257 REG_CR1_DACSEL_OFFSET, 0, NULL, 0), 258 259 SND_SOC_DAPM_MIXER("Line In", JZ4725B_CODEC_REG_PMR1, 260 REG_PMR1_SB_LIN_OFFSET, 1, NULL, 0), 261 SND_SOC_DAPM_MIXER("HP Out", JZ4725B_CODEC_REG_CR1, 262 REG_CR1_HP_DIS_OFFSET, 1, NULL, 0), 263 264 SND_SOC_DAPM_MIXER("Mic 1", JZ4725B_CODEC_REG_CR3, 265 REG_CR3_SB_MIC1_OFFSET, 1, NULL, 0), 266 SND_SOC_DAPM_MIXER("Mic 2", JZ4725B_CODEC_REG_CR3, 267 REG_CR3_SB_MIC2_OFFSET, 1, NULL, 0), 268 269 SND_SOC_DAPM_MIXER_E("Out Stage", JZ4725B_CODEC_REG_PMR1, 270 REG_PMR1_SB_OUT_OFFSET, 1, NULL, 0, 271 jz4725b_out_stage_enable, 272 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU | 273 SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD), 274 SND_SOC_DAPM_MIXER("Mixer to ADC", JZ4725B_CODEC_REG_PMR1, 275 REG_PMR1_SB_IND_OFFSET, 1, NULL, 0), 276 277 SND_SOC_DAPM_SUPPLY("Mic Bias", JZ4725B_CODEC_REG_CR1, 278 REG_CR1_SB_MICBIAS_OFFSET, 1, NULL, 0), 279 280 /* Pins */ 281 SND_SOC_DAPM_INPUT("MIC1P"), 282 SND_SOC_DAPM_INPUT("MIC1N"), 283 SND_SOC_DAPM_INPUT("MIC2P"), 284 SND_SOC_DAPM_INPUT("MIC2N"), 285 286 SND_SOC_DAPM_INPUT("LLINEIN"), 287 SND_SOC_DAPM_INPUT("RLINEIN"), 288 289 SND_SOC_DAPM_OUTPUT("LHPOUT"), 290 SND_SOC_DAPM_OUTPUT("RHPOUT"), 291 }; 292 293 static const struct snd_soc_dapm_route jz4725b_codec_dapm_routes[] = { 294 {"Mic 1", NULL, "MIC1P"}, 295 {"Mic 1", NULL, "MIC1N"}, 296 {"Mic 2", NULL, "MIC2P"}, 297 {"Mic 2", NULL, "MIC2N"}, 298 299 {"Line In", NULL, "LLINEIN"}, 300 {"Line In", NULL, "RLINEIN"}, 301 302 {"Mixer", "Line In Bypass", "Line In"}, 303 {"DAC to Mixer", NULL, "DAC"}, 304 {"Mixer", NULL, "DAC to Mixer"}, 305 306 {"Mixer to ADC", NULL, "Mixer"}, 307 {"ADC Source Capture Route", "Mixer", "Mixer to ADC"}, 308 {"ADC Sourc Capture Routee", "Line In", "Line In"}, 309 {"ADC Source Capture Route", "Mic 1", "Mic 1"}, 310 {"ADC Source Capture Route", "Mic 2", "Mic 2"}, 311 {"ADC", NULL, "ADC Source Capture Route"}, 312 313 {"Out Stage", NULL, "Mixer"}, 314 {"HP Out", NULL, "Out Stage"}, 315 {"LHPOUT", NULL, "HP Out"}, 316 {"RHPOUT", NULL, "HP Out"}, 317 }; 318 319 static int jz4725b_codec_set_bias_level(struct snd_soc_component *component, 320 enum snd_soc_bias_level level) 321 { 322 struct jz_icdc *icdc = snd_soc_component_get_drvdata(component); 323 struct regmap *map = icdc->regmap; 324 325 switch (level) { 326 case SND_SOC_BIAS_ON: 327 regmap_clear_bits(map, JZ4725B_CODEC_REG_PMR2, 328 BIT(REG_PMR2_SB_SLEEP_OFFSET)); 329 break; 330 case SND_SOC_BIAS_PREPARE: 331 /* Enable sound hardware */ 332 regmap_clear_bits(map, JZ4725B_CODEC_REG_PMR2, 333 BIT(REG_PMR2_SB_OFFSET)); 334 msleep(224); 335 break; 336 case SND_SOC_BIAS_STANDBY: 337 regmap_set_bits(map, JZ4725B_CODEC_REG_PMR2, 338 BIT(REG_PMR2_SB_SLEEP_OFFSET)); 339 break; 340 case SND_SOC_BIAS_OFF: 341 regmap_set_bits(map, JZ4725B_CODEC_REG_PMR2, 342 BIT(REG_PMR2_SB_OFFSET)); 343 break; 344 } 345 346 return 0; 347 } 348 349 static int jz4725b_codec_dev_probe(struct snd_soc_component *component) 350 { 351 struct jz_icdc *icdc = snd_soc_component_get_drvdata(component); 352 struct regmap *map = icdc->regmap; 353 354 clk_prepare_enable(icdc->clk); 355 356 /* Write CONFIGn (n=1 to 8) bits. 357 * The value 0x0f is specified in the datasheet as a requirement. 358 */ 359 regmap_write(map, JZ4725B_CODEC_REG_AICR, 360 0xf << REG_AICR_CONFIG1_OFFSET); 361 regmap_write(map, JZ4725B_CODEC_REG_CCR1, 362 0x0 << REG_CCR1_CONFIG4_OFFSET); 363 364 return 0; 365 } 366 367 static void jz4725b_codec_dev_remove(struct snd_soc_component *component) 368 { 369 struct jz_icdc *icdc = snd_soc_component_get_drvdata(component); 370 371 clk_disable_unprepare(icdc->clk); 372 } 373 374 static const struct snd_soc_component_driver jz4725b_codec = { 375 .probe = jz4725b_codec_dev_probe, 376 .remove = jz4725b_codec_dev_remove, 377 .set_bias_level = jz4725b_codec_set_bias_level, 378 .controls = jz4725b_codec_controls, 379 .num_controls = ARRAY_SIZE(jz4725b_codec_controls), 380 .dapm_widgets = jz4725b_codec_dapm_widgets, 381 .num_dapm_widgets = ARRAY_SIZE(jz4725b_codec_dapm_widgets), 382 .dapm_routes = jz4725b_codec_dapm_routes, 383 .num_dapm_routes = ARRAY_SIZE(jz4725b_codec_dapm_routes), 384 .suspend_bias_off = 1, 385 .use_pmdown_time = 1, 386 }; 387 388 static const unsigned int jz4725b_codec_sample_rates[] = { 389 96000, 48000, 44100, 32000, 390 24000, 22050, 16000, 12000, 391 11025, 9600, 8000, 392 }; 393 394 static int jz4725b_codec_hw_params(struct snd_pcm_substream *substream, 395 struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) 396 { 397 struct jz_icdc *icdc = snd_soc_component_get_drvdata(dai->component); 398 unsigned int rate, bit_width; 399 400 switch (params_format(params)) { 401 case SNDRV_PCM_FORMAT_S16_LE: 402 bit_width = 0; 403 break; 404 case SNDRV_PCM_FORMAT_S18_3LE: 405 bit_width = 1; 406 break; 407 case SNDRV_PCM_FORMAT_S20_3LE: 408 bit_width = 2; 409 break; 410 case SNDRV_PCM_FORMAT_S24_3LE: 411 bit_width = 3; 412 break; 413 default: 414 return -EINVAL; 415 } 416 417 for (rate = 0; rate < ARRAY_SIZE(jz4725b_codec_sample_rates); rate++) { 418 if (jz4725b_codec_sample_rates[rate] == params_rate(params)) 419 break; 420 } 421 422 if (rate == ARRAY_SIZE(jz4725b_codec_sample_rates)) 423 return -EINVAL; 424 425 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { 426 regmap_update_bits(icdc->regmap, 427 JZ4725B_CODEC_REG_CR2, 428 REG_CR2_DAC_ADWL_MASK, 429 bit_width << REG_CR2_DAC_ADWL_OFFSET); 430 431 regmap_update_bits(icdc->regmap, 432 JZ4725B_CODEC_REG_CCR2, 433 REG_CCR2_DFREQ_MASK, 434 rate << REG_CCR2_DFREQ_OFFSET); 435 } else { 436 regmap_update_bits(icdc->regmap, 437 JZ4725B_CODEC_REG_CR2, 438 REG_CR2_ADC_ADWL_MASK, 439 bit_width << REG_CR2_ADC_ADWL_OFFSET); 440 441 regmap_update_bits(icdc->regmap, 442 JZ4725B_CODEC_REG_CCR2, 443 REG_CCR2_AFREQ_MASK, 444 rate << REG_CCR2_AFREQ_OFFSET); 445 } 446 447 return 0; 448 } 449 450 static const struct snd_soc_dai_ops jz4725b_codec_dai_ops = { 451 .hw_params = jz4725b_codec_hw_params, 452 }; 453 454 #define JZ_ICDC_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S18_3LE | \ 455 SNDRV_PCM_FMTBIT_S20_3LE | SNDRV_PCM_FMTBIT_S24_3LE) 456 457 static struct snd_soc_dai_driver jz4725b_codec_dai = { 458 .name = "jz4725b-hifi", 459 .playback = { 460 .stream_name = "Playback", 461 .channels_min = 2, 462 .channels_max = 2, 463 .rates = SNDRV_PCM_RATE_8000_96000, 464 .formats = JZ_ICDC_FORMATS, 465 }, 466 .capture = { 467 .stream_name = "Capture", 468 .channels_min = 2, 469 .channels_max = 2, 470 .rates = SNDRV_PCM_RATE_8000_96000, 471 .formats = JZ_ICDC_FORMATS, 472 }, 473 .ops = &jz4725b_codec_dai_ops, 474 }; 475 476 static bool jz4725b_codec_volatile(struct device *dev, unsigned int reg) 477 { 478 return reg == JZ4725B_CODEC_REG_IFR; 479 } 480 481 static bool jz4725b_codec_can_access_reg(struct device *dev, unsigned int reg) 482 { 483 return (reg != JZ4725B_CODEC_REG_TR1) && (reg != JZ4725B_CODEC_REG_TR2); 484 } 485 486 static int jz4725b_codec_io_wait(struct jz_icdc *icdc) 487 { 488 u32 reg; 489 490 return readl_poll_timeout(icdc->base + ICDC_RGADW_OFFSET, reg, 491 !(reg & ICDC_RGADW_RGWR), 1000, 10000); 492 } 493 494 static int jz4725b_codec_reg_read(void *context, unsigned int reg, 495 unsigned int *val) 496 { 497 struct jz_icdc *icdc = context; 498 unsigned int i; 499 u32 tmp; 500 int ret; 501 502 ret = jz4725b_codec_io_wait(icdc); 503 if (ret) 504 return ret; 505 506 tmp = readl(icdc->base + ICDC_RGADW_OFFSET); 507 tmp = (tmp & ~ICDC_RGADW_RGADDR_MASK) 508 | (reg << ICDC_RGADW_RGADDR_OFFSET); 509 writel(tmp, icdc->base + ICDC_RGADW_OFFSET); 510 511 /* wait 6+ cycles */ 512 for (i = 0; i < 6; i++) 513 *val = readl(icdc->base + ICDC_RGDATA_OFFSET) & 514 ICDC_RGDATA_RGDOUT_MASK; 515 516 return 0; 517 } 518 519 static int jz4725b_codec_reg_write(void *context, unsigned int reg, 520 unsigned int val) 521 { 522 struct jz_icdc *icdc = context; 523 int ret; 524 525 ret = jz4725b_codec_io_wait(icdc); 526 if (ret) 527 return ret; 528 529 writel(ICDC_RGADW_RGWR | (reg << ICDC_RGADW_RGADDR_OFFSET) | val, 530 icdc->base + ICDC_RGADW_OFFSET); 531 532 ret = jz4725b_codec_io_wait(icdc); 533 if (ret) 534 return ret; 535 536 return 0; 537 } 538 539 static const u8 jz4725b_codec_reg_defaults[] = { 540 0x0c, 0xaa, 0x78, 0x00, 0x00, 0xff, 0x03, 0x51, 541 0x3f, 0x00, 0x00, 0x04, 0x04, 0x04, 0x04, 0x04, 542 0x04, 0x0a, 0x0a, 0x00, 0x00, 0x00, 0xc0, 0x34, 543 0x07, 0x44, 0x1f, 0x00, 544 }; 545 546 static const struct regmap_config jz4725b_codec_regmap_config = { 547 .reg_bits = 7, 548 .val_bits = 8, 549 550 .max_register = JZ4725B_CODEC_REG_AGC5, 551 .volatile_reg = jz4725b_codec_volatile, 552 .readable_reg = jz4725b_codec_can_access_reg, 553 .writeable_reg = jz4725b_codec_can_access_reg, 554 555 .reg_read = jz4725b_codec_reg_read, 556 .reg_write = jz4725b_codec_reg_write, 557 558 .reg_defaults_raw = jz4725b_codec_reg_defaults, 559 .num_reg_defaults_raw = ARRAY_SIZE(jz4725b_codec_reg_defaults), 560 .cache_type = REGCACHE_FLAT, 561 }; 562 563 static int jz4725b_codec_probe(struct platform_device *pdev) 564 { 565 struct device *dev = &pdev->dev; 566 struct jz_icdc *icdc; 567 int ret; 568 569 icdc = devm_kzalloc(dev, sizeof(*icdc), GFP_KERNEL); 570 if (!icdc) 571 return -ENOMEM; 572 573 icdc->base = devm_platform_ioremap_resource(pdev, 0); 574 if (IS_ERR(icdc->base)) 575 return PTR_ERR(icdc->base); 576 577 icdc->regmap = devm_regmap_init(dev, NULL, icdc, 578 &jz4725b_codec_regmap_config); 579 if (IS_ERR(icdc->regmap)) 580 return PTR_ERR(icdc->regmap); 581 582 icdc->clk = devm_clk_get(&pdev->dev, "aic"); 583 if (IS_ERR(icdc->clk)) 584 return PTR_ERR(icdc->clk); 585 586 platform_set_drvdata(pdev, icdc); 587 588 ret = devm_snd_soc_register_component(dev, &jz4725b_codec, 589 &jz4725b_codec_dai, 1); 590 if (ret) 591 dev_err(dev, "Failed to register codec\n"); 592 593 return ret; 594 } 595 596 static const struct of_device_id jz4725b_codec_of_matches[] = { 597 { .compatible = "ingenic,jz4725b-codec", }, 598 { } 599 }; 600 MODULE_DEVICE_TABLE(of, jz4725b_codec_of_matches); 601 602 static struct platform_driver jz4725b_codec_driver = { 603 .probe = jz4725b_codec_probe, 604 .driver = { 605 .name = "jz4725b-codec", 606 .of_match_table = jz4725b_codec_of_matches, 607 }, 608 }; 609 module_platform_driver(jz4725b_codec_driver); 610 611 MODULE_DESCRIPTION("JZ4725B SoC internal codec driver"); 612 MODULE_AUTHOR("Paul Cercueil <paul@crapouillou.net>"); 613 MODULE_LICENSE("GPL v2"); 614