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