0001
0002
0003
0004
0005
0006
0007 #include <linux/kernel.h>
0008 #include <linux/module.h>
0009 #include <linux/platform_device.h>
0010 #include <linux/slab.h>
0011 #include <linux/io.h>
0012 #include <linux/iopoll.h>
0013 #include <linux/regmap.h>
0014 #include <linux/clk.h>
0015
0016 #include <linux/delay.h>
0017
0018 #include <sound/core.h>
0019 #include <sound/pcm.h>
0020 #include <sound/pcm_params.h>
0021 #include <sound/initval.h>
0022 #include <sound/soc.h>
0023 #include <sound/tlv.h>
0024
0025 #define ICDC_RGADW_OFFSET 0x00
0026 #define ICDC_RGDATA_OFFSET 0x04
0027
0028
0029 #define ICDC_RGADW_RGWR BIT(16)
0030
0031 #define ICDC_RGADW_RGADDR_OFFSET 8
0032 #define ICDC_RGADW_RGADDR_MASK GENMASK(14, ICDC_RGADW_RGADDR_OFFSET)
0033
0034 #define ICDC_RGADW_RGDIN_OFFSET 0
0035 #define ICDC_RGADW_RGDIN_MASK GENMASK(7, ICDC_RGADW_RGDIN_OFFSET)
0036
0037
0038 #define ICDC_RGDATA_IRQ BIT(8)
0039
0040 #define ICDC_RGDATA_RGDOUT_OFFSET 0
0041 #define ICDC_RGDATA_RGDOUT_MASK GENMASK(7, ICDC_RGDATA_RGDOUT_OFFSET)
0042
0043
0044 enum {
0045 JZ4725B_CODEC_REG_AICR,
0046 JZ4725B_CODEC_REG_CR1,
0047 JZ4725B_CODEC_REG_CR2,
0048 JZ4725B_CODEC_REG_CCR1,
0049 JZ4725B_CODEC_REG_CCR2,
0050 JZ4725B_CODEC_REG_PMR1,
0051 JZ4725B_CODEC_REG_PMR2,
0052 JZ4725B_CODEC_REG_CRR,
0053 JZ4725B_CODEC_REG_ICR,
0054 JZ4725B_CODEC_REG_IFR,
0055 JZ4725B_CODEC_REG_CGR1,
0056 JZ4725B_CODEC_REG_CGR2,
0057 JZ4725B_CODEC_REG_CGR3,
0058 JZ4725B_CODEC_REG_CGR4,
0059 JZ4725B_CODEC_REG_CGR5,
0060 JZ4725B_CODEC_REG_CGR6,
0061 JZ4725B_CODEC_REG_CGR7,
0062 JZ4725B_CODEC_REG_CGR8,
0063 JZ4725B_CODEC_REG_CGR9,
0064 JZ4725B_CODEC_REG_CGR10,
0065 JZ4725B_CODEC_REG_TR1,
0066 JZ4725B_CODEC_REG_TR2,
0067 JZ4725B_CODEC_REG_CR3,
0068 JZ4725B_CODEC_REG_AGC1,
0069 JZ4725B_CODEC_REG_AGC2,
0070 JZ4725B_CODEC_REG_AGC3,
0071 JZ4725B_CODEC_REG_AGC4,
0072 JZ4725B_CODEC_REG_AGC5,
0073 };
0074
0075 #define REG_AICR_CONFIG1_OFFSET 0
0076 #define REG_AICR_CONFIG1_MASK (0xf << REG_AICR_CONFIG1_OFFSET)
0077
0078 #define REG_CR1_SB_MICBIAS_OFFSET 7
0079 #define REG_CR1_MONO_OFFSET 6
0080 #define REG_CR1_DAC_MUTE_OFFSET 5
0081 #define REG_CR1_HP_DIS_OFFSET 4
0082 #define REG_CR1_DACSEL_OFFSET 3
0083 #define REG_CR1_BYPASS_OFFSET 2
0084
0085 #define REG_CR2_DAC_DEEMP_OFFSET 7
0086 #define REG_CR2_DAC_ADWL_OFFSET 5
0087 #define REG_CR2_DAC_ADWL_MASK (0x3 << REG_CR2_DAC_ADWL_OFFSET)
0088 #define REG_CR2_ADC_ADWL_OFFSET 3
0089 #define REG_CR2_ADC_ADWL_MASK (0x3 << REG_CR2_ADC_ADWL_OFFSET)
0090 #define REG_CR2_ADC_HPF_OFFSET 2
0091
0092 #define REG_CR3_SB_MIC1_OFFSET 7
0093 #define REG_CR3_SB_MIC2_OFFSET 6
0094 #define REG_CR3_SIDETONE1_OFFSET 5
0095 #define REG_CR3_SIDETONE2_OFFSET 4
0096 #define REG_CR3_MICDIFF_OFFSET 3
0097 #define REG_CR3_MICSTEREO_OFFSET 2
0098 #define REG_CR3_INSEL_OFFSET 0
0099 #define REG_CR3_INSEL_MASK (0x3 << REG_CR3_INSEL_OFFSET)
0100
0101 #define REG_CCR1_CONFIG4_OFFSET 0
0102 #define REG_CCR1_CONFIG4_MASK (0xf << REG_CCR1_CONFIG4_OFFSET)
0103
0104 #define REG_CCR2_DFREQ_OFFSET 4
0105 #define REG_CCR2_DFREQ_MASK (0xf << REG_CCR2_DFREQ_OFFSET)
0106 #define REG_CCR2_AFREQ_OFFSET 0
0107 #define REG_CCR2_AFREQ_MASK (0xf << REG_CCR2_AFREQ_OFFSET)
0108
0109 #define REG_PMR1_SB_DAC_OFFSET 7
0110 #define REG_PMR1_SB_OUT_OFFSET 6
0111 #define REG_PMR1_SB_MIX_OFFSET 5
0112 #define REG_PMR1_SB_ADC_OFFSET 4
0113 #define REG_PMR1_SB_LIN_OFFSET 3
0114 #define REG_PMR1_SB_IND_OFFSET 0
0115
0116 #define REG_PMR2_LRGI_OFFSET 7
0117 #define REG_PMR2_RLGI_OFFSET 6
0118 #define REG_PMR2_LRGOD_OFFSET 5
0119 #define REG_PMR2_RLGOD_OFFSET 4
0120 #define REG_PMR2_GIM_OFFSET 3
0121 #define REG_PMR2_SB_MC_OFFSET 2
0122 #define REG_PMR2_SB_OFFSET 1
0123 #define REG_PMR2_SB_SLEEP_OFFSET 0
0124
0125 #define REG_IFR_RAMP_UP_DONE_OFFSET 3
0126 #define REG_IFR_RAMP_DOWN_DONE_OFFSET 2
0127
0128 #define REG_CGR1_GODL_OFFSET 4
0129 #define REG_CGR1_GODL_MASK (0xf << REG_CGR1_GODL_OFFSET)
0130 #define REG_CGR1_GODR_OFFSET 0
0131 #define REG_CGR1_GODR_MASK (0xf << REG_CGR1_GODR_OFFSET)
0132
0133 #define REG_CGR2_GO1R_OFFSET 0
0134 #define REG_CGR2_GO1R_MASK (0x1f << REG_CGR2_GO1R_OFFSET)
0135
0136 #define REG_CGR3_GO1L_OFFSET 0
0137 #define REG_CGR3_GO1L_MASK (0x1f << REG_CGR3_GO1L_OFFSET)
0138
0139 struct jz_icdc {
0140 struct regmap *regmap;
0141 void __iomem *base;
0142 struct clk *clk;
0143 };
0144
0145 static const SNDRV_CTL_TLVD_DECLARE_DB_LINEAR(jz4725b_dac_tlv, -2250, 0);
0146 static const SNDRV_CTL_TLVD_DECLARE_DB_LINEAR(jz4725b_line_tlv, -1500, 600);
0147
0148 static const struct snd_kcontrol_new jz4725b_codec_controls[] = {
0149 SOC_DOUBLE_TLV("Master Playback Volume",
0150 JZ4725B_CODEC_REG_CGR1,
0151 REG_CGR1_GODL_OFFSET,
0152 REG_CGR1_GODR_OFFSET,
0153 0xf, 1, jz4725b_dac_tlv),
0154 SOC_DOUBLE_R_TLV("Master Capture Volume",
0155 JZ4725B_CODEC_REG_CGR3,
0156 JZ4725B_CODEC_REG_CGR2,
0157 REG_CGR2_GO1R_OFFSET,
0158 0x1f, 1, jz4725b_line_tlv),
0159
0160 SOC_SINGLE("Master Playback Switch", JZ4725B_CODEC_REG_CR1,
0161 REG_CR1_DAC_MUTE_OFFSET, 1, 1),
0162
0163 SOC_SINGLE("Deemphasize Filter Playback Switch",
0164 JZ4725B_CODEC_REG_CR2,
0165 REG_CR2_DAC_DEEMP_OFFSET, 1, 0),
0166
0167 SOC_SINGLE("High-Pass Filter Capture Switch",
0168 JZ4725B_CODEC_REG_CR2,
0169 REG_CR2_ADC_HPF_OFFSET, 1, 0),
0170 };
0171
0172 static const char * const jz4725b_codec_adc_src_texts[] = {
0173 "Mic 1", "Mic 2", "Line In", "Mixer",
0174 };
0175 static const unsigned int jz4725b_codec_adc_src_values[] = { 0, 1, 2, 3, };
0176 static SOC_VALUE_ENUM_SINGLE_DECL(jz4725b_codec_adc_src_enum,
0177 JZ4725B_CODEC_REG_CR3,
0178 REG_CR3_INSEL_OFFSET,
0179 REG_CR3_INSEL_MASK,
0180 jz4725b_codec_adc_src_texts,
0181 jz4725b_codec_adc_src_values);
0182 static const struct snd_kcontrol_new jz4725b_codec_adc_src_ctrl =
0183 SOC_DAPM_ENUM("Route", jz4725b_codec_adc_src_enum);
0184
0185 static const struct snd_kcontrol_new jz4725b_codec_mixer_controls[] = {
0186 SOC_DAPM_SINGLE("Line In Bypass", JZ4725B_CODEC_REG_CR1,
0187 REG_CR1_BYPASS_OFFSET, 1, 0),
0188 };
0189
0190 static int jz4725b_out_stage_enable(struct snd_soc_dapm_widget *w,
0191 struct snd_kcontrol *kcontrol,
0192 int event)
0193 {
0194 struct snd_soc_component *codec = snd_soc_dapm_to_component(w->dapm);
0195 struct jz_icdc *icdc = snd_soc_component_get_drvdata(codec);
0196 struct regmap *map = icdc->regmap;
0197 unsigned int val;
0198
0199 switch (event) {
0200 case SND_SOC_DAPM_PRE_PMU:
0201 return regmap_clear_bits(map, JZ4725B_CODEC_REG_IFR,
0202 BIT(REG_IFR_RAMP_UP_DONE_OFFSET));
0203 case SND_SOC_DAPM_POST_PMU:
0204 return regmap_read_poll_timeout(map, JZ4725B_CODEC_REG_IFR,
0205 val, val & BIT(REG_IFR_RAMP_UP_DONE_OFFSET),
0206 100000, 500000);
0207 case SND_SOC_DAPM_PRE_PMD:
0208 return regmap_clear_bits(map, JZ4725B_CODEC_REG_IFR,
0209 BIT(REG_IFR_RAMP_DOWN_DONE_OFFSET));
0210 case SND_SOC_DAPM_POST_PMD:
0211 return regmap_read_poll_timeout(map, JZ4725B_CODEC_REG_IFR,
0212 val, val & BIT(REG_IFR_RAMP_DOWN_DONE_OFFSET),
0213 100000, 500000);
0214 default:
0215 return -EINVAL;
0216 }
0217 }
0218
0219 static const struct snd_soc_dapm_widget jz4725b_codec_dapm_widgets[] = {
0220
0221 SND_SOC_DAPM_DAC("DAC", "Playback",
0222 JZ4725B_CODEC_REG_PMR1, REG_PMR1_SB_DAC_OFFSET, 1),
0223
0224
0225 SND_SOC_DAPM_ADC("ADC", "Capture",
0226 JZ4725B_CODEC_REG_PMR1, REG_PMR1_SB_ADC_OFFSET, 1),
0227
0228 SND_SOC_DAPM_MUX("ADC Source", SND_SOC_NOPM, 0, 0,
0229 &jz4725b_codec_adc_src_ctrl),
0230
0231
0232 SND_SOC_DAPM_MIXER("Mixer", JZ4725B_CODEC_REG_PMR1,
0233 REG_PMR1_SB_MIX_OFFSET, 1,
0234 jz4725b_codec_mixer_controls,
0235 ARRAY_SIZE(jz4725b_codec_mixer_controls)),
0236 SND_SOC_DAPM_MIXER("DAC to Mixer", JZ4725B_CODEC_REG_CR1,
0237 REG_CR1_DACSEL_OFFSET, 0, NULL, 0),
0238
0239 SND_SOC_DAPM_MIXER("Line In", SND_SOC_NOPM, 0, 0, NULL, 0),
0240 SND_SOC_DAPM_MIXER("HP Out", JZ4725B_CODEC_REG_CR1,
0241 REG_CR1_HP_DIS_OFFSET, 1, NULL, 0),
0242
0243 SND_SOC_DAPM_MIXER("Mic 1", JZ4725B_CODEC_REG_CR3,
0244 REG_CR3_SB_MIC1_OFFSET, 1, NULL, 0),
0245 SND_SOC_DAPM_MIXER("Mic 2", JZ4725B_CODEC_REG_CR3,
0246 REG_CR3_SB_MIC2_OFFSET, 1, NULL, 0),
0247
0248 SND_SOC_DAPM_MIXER_E("Out Stage", JZ4725B_CODEC_REG_PMR1,
0249 REG_PMR1_SB_OUT_OFFSET, 1, NULL, 0,
0250 jz4725b_out_stage_enable,
0251 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
0252 SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
0253 SND_SOC_DAPM_MIXER("Mixer to ADC", JZ4725B_CODEC_REG_PMR1,
0254 REG_PMR1_SB_IND_OFFSET, 1, NULL, 0),
0255
0256 SND_SOC_DAPM_SUPPLY("Mic Bias", JZ4725B_CODEC_REG_CR1,
0257 REG_CR1_SB_MICBIAS_OFFSET, 1, NULL, 0),
0258
0259
0260 SND_SOC_DAPM_INPUT("MIC1P"),
0261 SND_SOC_DAPM_INPUT("MIC1N"),
0262 SND_SOC_DAPM_INPUT("MIC2P"),
0263 SND_SOC_DAPM_INPUT("MIC2N"),
0264
0265 SND_SOC_DAPM_INPUT("LLINEIN"),
0266 SND_SOC_DAPM_INPUT("RLINEIN"),
0267
0268 SND_SOC_DAPM_OUTPUT("LHPOUT"),
0269 SND_SOC_DAPM_OUTPUT("RHPOUT"),
0270 };
0271
0272 static const struct snd_soc_dapm_route jz4725b_codec_dapm_routes[] = {
0273 {"Mic 1", NULL, "MIC1P"},
0274 {"Mic 1", NULL, "MIC1N"},
0275 {"Mic 2", NULL, "MIC2P"},
0276 {"Mic 2", NULL, "MIC2N"},
0277
0278 {"Line In", NULL, "LLINEIN"},
0279 {"Line In", NULL, "RLINEIN"},
0280
0281 {"Mixer", "Line In Bypass", "Line In"},
0282 {"DAC to Mixer", NULL, "DAC"},
0283 {"Mixer", NULL, "DAC to Mixer"},
0284
0285 {"Mixer to ADC", NULL, "Mixer"},
0286 {"ADC Source", "Mixer", "Mixer to ADC"},
0287 {"ADC Source", "Line In", "Line In"},
0288 {"ADC Source", "Mic 1", "Mic 1"},
0289 {"ADC Source", "Mic 2", "Mic 2"},
0290 {"ADC", NULL, "ADC Source"},
0291
0292 {"Out Stage", NULL, "Mixer"},
0293 {"HP Out", NULL, "Out Stage"},
0294 {"LHPOUT", NULL, "HP Out"},
0295 {"RHPOUT", NULL, "HP Out"},
0296 };
0297
0298 static int jz4725b_codec_set_bias_level(struct snd_soc_component *component,
0299 enum snd_soc_bias_level level)
0300 {
0301 struct jz_icdc *icdc = snd_soc_component_get_drvdata(component);
0302 struct regmap *map = icdc->regmap;
0303
0304 switch (level) {
0305 case SND_SOC_BIAS_ON:
0306 regmap_clear_bits(map, JZ4725B_CODEC_REG_PMR2,
0307 BIT(REG_PMR2_SB_SLEEP_OFFSET));
0308 break;
0309 case SND_SOC_BIAS_PREPARE:
0310
0311 regmap_clear_bits(map, JZ4725B_CODEC_REG_PMR2,
0312 BIT(REG_PMR2_SB_OFFSET));
0313 msleep(224);
0314 break;
0315 case SND_SOC_BIAS_STANDBY:
0316 regmap_set_bits(map, JZ4725B_CODEC_REG_PMR2,
0317 BIT(REG_PMR2_SB_SLEEP_OFFSET));
0318 break;
0319 case SND_SOC_BIAS_OFF:
0320 regmap_set_bits(map, JZ4725B_CODEC_REG_PMR2,
0321 BIT(REG_PMR2_SB_OFFSET));
0322 break;
0323 }
0324
0325 return 0;
0326 }
0327
0328 static int jz4725b_codec_dev_probe(struct snd_soc_component *component)
0329 {
0330 struct jz_icdc *icdc = snd_soc_component_get_drvdata(component);
0331 struct regmap *map = icdc->regmap;
0332
0333 clk_prepare_enable(icdc->clk);
0334
0335
0336
0337
0338 regmap_write(map, JZ4725B_CODEC_REG_AICR,
0339 0xf << REG_AICR_CONFIG1_OFFSET);
0340 regmap_write(map, JZ4725B_CODEC_REG_CCR1,
0341 0x0 << REG_CCR1_CONFIG4_OFFSET);
0342
0343 return 0;
0344 }
0345
0346 static void jz4725b_codec_dev_remove(struct snd_soc_component *component)
0347 {
0348 struct jz_icdc *icdc = snd_soc_component_get_drvdata(component);
0349
0350 clk_disable_unprepare(icdc->clk);
0351 }
0352
0353 static const struct snd_soc_component_driver jz4725b_codec = {
0354 .probe = jz4725b_codec_dev_probe,
0355 .remove = jz4725b_codec_dev_remove,
0356 .set_bias_level = jz4725b_codec_set_bias_level,
0357 .controls = jz4725b_codec_controls,
0358 .num_controls = ARRAY_SIZE(jz4725b_codec_controls),
0359 .dapm_widgets = jz4725b_codec_dapm_widgets,
0360 .num_dapm_widgets = ARRAY_SIZE(jz4725b_codec_dapm_widgets),
0361 .dapm_routes = jz4725b_codec_dapm_routes,
0362 .num_dapm_routes = ARRAY_SIZE(jz4725b_codec_dapm_routes),
0363 .suspend_bias_off = 1,
0364 .use_pmdown_time = 1,
0365 };
0366
0367 static const unsigned int jz4725b_codec_sample_rates[] = {
0368 96000, 48000, 44100, 32000,
0369 24000, 22050, 16000, 12000,
0370 11025, 9600, 8000,
0371 };
0372
0373 static int jz4725b_codec_hw_params(struct snd_pcm_substream *substream,
0374 struct snd_pcm_hw_params *params, struct snd_soc_dai *dai)
0375 {
0376 struct jz_icdc *icdc = snd_soc_component_get_drvdata(dai->component);
0377 unsigned int rate, bit_width;
0378
0379 switch (params_format(params)) {
0380 case SNDRV_PCM_FORMAT_S16_LE:
0381 bit_width = 0;
0382 break;
0383 case SNDRV_PCM_FORMAT_S18_3LE:
0384 bit_width = 1;
0385 break;
0386 case SNDRV_PCM_FORMAT_S20_3LE:
0387 bit_width = 2;
0388 break;
0389 case SNDRV_PCM_FORMAT_S24_3LE:
0390 bit_width = 3;
0391 break;
0392 default:
0393 return -EINVAL;
0394 }
0395
0396 for (rate = 0; rate < ARRAY_SIZE(jz4725b_codec_sample_rates); rate++) {
0397 if (jz4725b_codec_sample_rates[rate] == params_rate(params))
0398 break;
0399 }
0400
0401 if (rate == ARRAY_SIZE(jz4725b_codec_sample_rates))
0402 return -EINVAL;
0403
0404 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
0405 regmap_update_bits(icdc->regmap,
0406 JZ4725B_CODEC_REG_CR2,
0407 REG_CR2_DAC_ADWL_MASK,
0408 bit_width << REG_CR2_DAC_ADWL_OFFSET);
0409
0410 regmap_update_bits(icdc->regmap,
0411 JZ4725B_CODEC_REG_CCR2,
0412 REG_CCR2_DFREQ_MASK,
0413 rate << REG_CCR2_DFREQ_OFFSET);
0414 } else {
0415 regmap_update_bits(icdc->regmap,
0416 JZ4725B_CODEC_REG_CR2,
0417 REG_CR2_ADC_ADWL_MASK,
0418 bit_width << REG_CR2_ADC_ADWL_OFFSET);
0419
0420 regmap_update_bits(icdc->regmap,
0421 JZ4725B_CODEC_REG_CCR2,
0422 REG_CCR2_AFREQ_MASK,
0423 rate << REG_CCR2_AFREQ_OFFSET);
0424 }
0425
0426 return 0;
0427 }
0428
0429 static const struct snd_soc_dai_ops jz4725b_codec_dai_ops = {
0430 .hw_params = jz4725b_codec_hw_params,
0431 };
0432
0433 #define JZ_ICDC_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S18_3LE | \
0434 SNDRV_PCM_FMTBIT_S20_3LE | SNDRV_PCM_FMTBIT_S24_3LE)
0435
0436 static struct snd_soc_dai_driver jz4725b_codec_dai = {
0437 .name = "jz4725b-hifi",
0438 .playback = {
0439 .stream_name = "Playback",
0440 .channels_min = 2,
0441 .channels_max = 2,
0442 .rates = SNDRV_PCM_RATE_8000_96000,
0443 .formats = JZ_ICDC_FORMATS,
0444 },
0445 .capture = {
0446 .stream_name = "Capture",
0447 .channels_min = 2,
0448 .channels_max = 2,
0449 .rates = SNDRV_PCM_RATE_8000_96000,
0450 .formats = JZ_ICDC_FORMATS,
0451 },
0452 .ops = &jz4725b_codec_dai_ops,
0453 };
0454
0455 static bool jz4725b_codec_volatile(struct device *dev, unsigned int reg)
0456 {
0457 return reg == JZ4725B_CODEC_REG_IFR;
0458 }
0459
0460 static bool jz4725b_codec_can_access_reg(struct device *dev, unsigned int reg)
0461 {
0462 return (reg != JZ4725B_CODEC_REG_TR1) && (reg != JZ4725B_CODEC_REG_TR2);
0463 }
0464
0465 static int jz4725b_codec_io_wait(struct jz_icdc *icdc)
0466 {
0467 u32 reg;
0468
0469 return readl_poll_timeout(icdc->base + ICDC_RGADW_OFFSET, reg,
0470 !(reg & ICDC_RGADW_RGWR), 1000, 10000);
0471 }
0472
0473 static int jz4725b_codec_reg_read(void *context, unsigned int reg,
0474 unsigned int *val)
0475 {
0476 struct jz_icdc *icdc = context;
0477 unsigned int i;
0478 u32 tmp;
0479 int ret;
0480
0481 ret = jz4725b_codec_io_wait(icdc);
0482 if (ret)
0483 return ret;
0484
0485 tmp = readl(icdc->base + ICDC_RGADW_OFFSET);
0486 tmp = (tmp & ~ICDC_RGADW_RGADDR_MASK)
0487 | (reg << ICDC_RGADW_RGADDR_OFFSET);
0488 writel(tmp, icdc->base + ICDC_RGADW_OFFSET);
0489
0490
0491 for (i = 0; i < 6; i++)
0492 *val = readl(icdc->base + ICDC_RGDATA_OFFSET) &
0493 ICDC_RGDATA_RGDOUT_MASK;
0494
0495 return 0;
0496 }
0497
0498 static int jz4725b_codec_reg_write(void *context, unsigned int reg,
0499 unsigned int val)
0500 {
0501 struct jz_icdc *icdc = context;
0502 int ret;
0503
0504 ret = jz4725b_codec_io_wait(icdc);
0505 if (ret)
0506 return ret;
0507
0508 writel(ICDC_RGADW_RGWR | (reg << ICDC_RGADW_RGADDR_OFFSET) | val,
0509 icdc->base + ICDC_RGADW_OFFSET);
0510
0511 ret = jz4725b_codec_io_wait(icdc);
0512 if (ret)
0513 return ret;
0514
0515 return 0;
0516 }
0517
0518 static const u8 jz4725b_codec_reg_defaults[] = {
0519 0x0c, 0xaa, 0x78, 0x00, 0x00, 0xff, 0x03, 0x51,
0520 0x3f, 0x00, 0x00, 0x04, 0x04, 0x04, 0x04, 0x04,
0521 0x04, 0x0a, 0x0a, 0x00, 0x00, 0x00, 0xc0, 0x34,
0522 0x07, 0x44, 0x1f, 0x00,
0523 };
0524
0525 static const struct regmap_config jz4725b_codec_regmap_config = {
0526 .reg_bits = 7,
0527 .val_bits = 8,
0528
0529 .max_register = JZ4725B_CODEC_REG_AGC5,
0530 .volatile_reg = jz4725b_codec_volatile,
0531 .readable_reg = jz4725b_codec_can_access_reg,
0532 .writeable_reg = jz4725b_codec_can_access_reg,
0533
0534 .reg_read = jz4725b_codec_reg_read,
0535 .reg_write = jz4725b_codec_reg_write,
0536
0537 .reg_defaults_raw = jz4725b_codec_reg_defaults,
0538 .num_reg_defaults_raw = ARRAY_SIZE(jz4725b_codec_reg_defaults),
0539 .cache_type = REGCACHE_FLAT,
0540 };
0541
0542 static int jz4725b_codec_probe(struct platform_device *pdev)
0543 {
0544 struct device *dev = &pdev->dev;
0545 struct jz_icdc *icdc;
0546 int ret;
0547
0548 icdc = devm_kzalloc(dev, sizeof(*icdc), GFP_KERNEL);
0549 if (!icdc)
0550 return -ENOMEM;
0551
0552 icdc->base = devm_platform_ioremap_resource(pdev, 0);
0553 if (IS_ERR(icdc->base))
0554 return PTR_ERR(icdc->base);
0555
0556 icdc->regmap = devm_regmap_init(dev, NULL, icdc,
0557 &jz4725b_codec_regmap_config);
0558 if (IS_ERR(icdc->regmap))
0559 return PTR_ERR(icdc->regmap);
0560
0561 icdc->clk = devm_clk_get(&pdev->dev, "aic");
0562 if (IS_ERR(icdc->clk))
0563 return PTR_ERR(icdc->clk);
0564
0565 platform_set_drvdata(pdev, icdc);
0566
0567 ret = devm_snd_soc_register_component(dev, &jz4725b_codec,
0568 &jz4725b_codec_dai, 1);
0569 if (ret)
0570 dev_err(dev, "Failed to register codec\n");
0571
0572 return ret;
0573 }
0574
0575 static const struct of_device_id jz4725b_codec_of_matches[] = {
0576 { .compatible = "ingenic,jz4725b-codec", },
0577 { }
0578 };
0579 MODULE_DEVICE_TABLE(of, jz4725b_codec_of_matches);
0580
0581 static struct platform_driver jz4725b_codec_driver = {
0582 .probe = jz4725b_codec_probe,
0583 .driver = {
0584 .name = "jz4725b-codec",
0585 .of_match_table = jz4725b_codec_of_matches,
0586 },
0587 };
0588 module_platform_driver(jz4725b_codec_driver);
0589
0590 MODULE_DESCRIPTION("JZ4725B SoC internal codec driver");
0591 MODULE_AUTHOR("Paul Cercueil <paul@crapouillou.net>");
0592 MODULE_LICENSE("GPL v2");