0001
0002
0003
0004
0005
0006
0007
0008 #include <linux/clk.h>
0009 #include <linux/delay.h>
0010 #include <linux/iopoll.h>
0011 #include <linux/module.h>
0012 #include <linux/regmap.h>
0013 #include <linux/time64.h>
0014
0015 #include <sound/pcm_params.h>
0016 #include <sound/soc.h>
0017 #include <sound/soc-dai.h>
0018 #include <sound/soc-dapm.h>
0019 #include <sound/tlv.h>
0020
0021 #define ICDC_RGADW_OFFSET 0x00
0022 #define ICDC_RGDATA_OFFSET 0x04
0023
0024
0025 #define ICDC_RGADW_RGWR BIT(16)
0026
0027 #define ICDC_RGADW_RGADDR_OFFSET 8
0028 #define ICDC_RGADW_RGADDR_MASK GENMASK(14, ICDC_RGADW_RGADDR_OFFSET)
0029
0030 #define ICDC_RGADW_RGDIN_OFFSET 0
0031 #define ICDC_RGADW_RGDIN_MASK GENMASK(7, ICDC_RGADW_RGDIN_OFFSET)
0032
0033
0034 #define ICDC_RGDATA_IRQ BIT(8)
0035
0036 #define ICDC_RGDATA_RGDOUT_OFFSET 0
0037 #define ICDC_RGDATA_RGDOUT_MASK GENMASK(7, ICDC_RGDATA_RGDOUT_OFFSET)
0038
0039
0040 enum {
0041 JZ4770_CODEC_REG_SR,
0042 JZ4770_CODEC_REG_AICR_DAC,
0043 JZ4770_CODEC_REG_AICR_ADC,
0044 JZ4770_CODEC_REG_CR_LO,
0045 JZ4770_CODEC_REG_CR_HP,
0046
0047 JZ4770_CODEC_REG_MISSING_REG1,
0048
0049 JZ4770_CODEC_REG_CR_DAC,
0050 JZ4770_CODEC_REG_CR_MIC,
0051 JZ4770_CODEC_REG_CR_LI,
0052 JZ4770_CODEC_REG_CR_ADC,
0053 JZ4770_CODEC_REG_CR_MIX,
0054 JZ4770_CODEC_REG_CR_VIC,
0055 JZ4770_CODEC_REG_CCR,
0056 JZ4770_CODEC_REG_FCR_DAC,
0057 JZ4770_CODEC_REG_FCR_ADC,
0058 JZ4770_CODEC_REG_ICR,
0059 JZ4770_CODEC_REG_IMR,
0060 JZ4770_CODEC_REG_IFR,
0061 JZ4770_CODEC_REG_GCR_HPL,
0062 JZ4770_CODEC_REG_GCR_HPR,
0063 JZ4770_CODEC_REG_GCR_LIBYL,
0064 JZ4770_CODEC_REG_GCR_LIBYR,
0065 JZ4770_CODEC_REG_GCR_DACL,
0066 JZ4770_CODEC_REG_GCR_DACR,
0067 JZ4770_CODEC_REG_GCR_MIC1,
0068 JZ4770_CODEC_REG_GCR_MIC2,
0069 JZ4770_CODEC_REG_GCR_ADCL,
0070 JZ4770_CODEC_REG_GCR_ADCR,
0071
0072 JZ4770_CODEC_REG_MISSING_REG2,
0073
0074 JZ4770_CODEC_REG_GCR_MIXADC,
0075 JZ4770_CODEC_REG_GCR_MIXDAC,
0076 JZ4770_CODEC_REG_AGC1,
0077 JZ4770_CODEC_REG_AGC2,
0078 JZ4770_CODEC_REG_AGC3,
0079 JZ4770_CODEC_REG_AGC4,
0080 JZ4770_CODEC_REG_AGC5,
0081 };
0082
0083 #define REG_AICR_DAC_ADWL_OFFSET 6
0084 #define REG_AICR_DAC_ADWL_MASK (0x3 << REG_AICR_DAC_ADWL_OFFSET)
0085 #define REG_AICR_DAC_SERIAL BIT(1)
0086 #define REG_AICR_DAC_I2S BIT(0)
0087
0088 #define REG_AICR_ADC_ADWL_OFFSET 6
0089 #define REG_AICR_ADC_ADWL_MASK (0x3 << REG_AICR_ADC_ADWL_OFFSET)
0090 #define REG_AICR_ADC_SERIAL BIT(1)
0091 #define REG_AICR_ADC_I2S BIT(0)
0092
0093 #define REG_CR_LO_MUTE_OFFSET 7
0094 #define REG_CR_LO_SB_OFFSET 4
0095 #define REG_CR_LO_SEL_OFFSET 0
0096 #define REG_CR_LO_SEL_MASK (0x3 << REG_CR_LO_SEL_OFFSET)
0097
0098 #define REG_CR_HP_MUTE BIT(7)
0099 #define REG_CR_HP_LOAD BIT(6)
0100 #define REG_CR_HP_SB_OFFSET 4
0101 #define REG_CR_HP_SB_HPCM_OFFSET 3
0102 #define REG_CR_HP_SEL_OFFSET 0
0103 #define REG_CR_HP_SEL_MASK (0x3 << REG_CR_HP_SEL_OFFSET)
0104
0105 #define REG_CR_DAC_MUTE BIT(7)
0106 #define REG_CR_DAC_MONO BIT(6)
0107 #define REG_CR_DAC_LEFT_ONLY BIT(5)
0108 #define REG_CR_DAC_SB_OFFSET 4
0109 #define REG_CR_DAC_LRSWAP BIT(3)
0110
0111 #define REG_CR_MIC_STEREO_OFFSET 7
0112 #define REG_CR_MIC_IDIFF_OFFSET 6
0113 #define REG_CR_MIC_SB_MIC2_OFFSET 5
0114 #define REG_CR_MIC_SB_MIC1_OFFSET 4
0115 #define REG_CR_MIC_BIAS_V0_OFFSET 1
0116 #define REG_CR_MIC_BIAS_SB_OFFSET 0
0117
0118 #define REG_CR_LI_LIBY_OFFSET 4
0119 #define REG_CR_LI_SB_OFFSET 0
0120
0121 #define REG_CR_ADC_DMIC_SEL BIT(7)
0122 #define REG_CR_ADC_MONO BIT(6)
0123 #define REG_CR_ADC_LEFT_ONLY BIT(5)
0124 #define REG_CR_ADC_SB_OFFSET 4
0125 #define REG_CR_ADC_LRSWAP BIT(3)
0126 #define REG_CR_ADC_IN_SEL_OFFSET 0
0127 #define REG_CR_ADC_IN_SEL_MASK (0x3 << REG_CR_ADC_IN_SEL_OFFSET)
0128
0129 #define REG_CR_VIC_SB_SLEEP BIT(1)
0130 #define REG_CR_VIC_SB BIT(0)
0131
0132 #define REG_CCR_CRYSTAL_OFFSET 0
0133 #define REG_CCR_CRYSTAL_MASK (0xf << REG_CCR_CRYSTAL_OFFSET)
0134
0135 #define REG_FCR_DAC_FREQ_OFFSET 0
0136 #define REG_FCR_DAC_FREQ_MASK (0xf << REG_FCR_DAC_FREQ_OFFSET)
0137
0138 #define REG_FCR_ADC_FREQ_OFFSET 0
0139 #define REG_FCR_ADC_FREQ_MASK (0xf << REG_FCR_ADC_FREQ_OFFSET)
0140
0141 #define REG_ICR_INT_FORM_OFFSET 6
0142 #define REG_ICR_INT_FORM_MASK (0x3 << REG_ICR_INT_FORM_OFFSET)
0143
0144 #define REG_IMR_ALL_MASK (0x7f)
0145 #define REG_IMR_SCLR_MASK BIT(6)
0146 #define REG_IMR_JACK_MASK BIT(5)
0147 #define REG_IMR_SCMC_MASK BIT(4)
0148 #define REG_IMR_RUP_MASK BIT(3)
0149 #define REG_IMR_RDO_MASK BIT(2)
0150 #define REG_IMR_GUP_MASK BIT(1)
0151 #define REG_IMR_GDO_MASK BIT(0)
0152
0153 #define REG_IFR_ALL_MASK (0x7f)
0154 #define REG_IFR_SCLR BIT(6)
0155 #define REG_IFR_JACK BIT(5)
0156 #define REG_IFR_SCMC BIT(4)
0157 #define REG_IFR_RUP BIT(3)
0158 #define REG_IFR_RDO BIT(2)
0159 #define REG_IFR_GUP BIT(1)
0160 #define REG_IFR_GDO BIT(0)
0161
0162 #define REG_GCR_HPL_LRGO BIT(7)
0163
0164 #define REG_GCR_DACL_RLGOD BIT(7)
0165
0166 #define REG_GCR_GAIN_OFFSET 0
0167 #define REG_GCR_GAIN_MAX 0x1f
0168
0169 #define REG_GCR_MIC_GAIN_OFFSET 0
0170 #define REG_GCR_MIC_GAIN_MAX 5
0171
0172 #define REG_GCR_ADC_GAIN_OFFSET 0
0173 #define REG_GCR_ADC_GAIN_MAX 23
0174
0175 #define REG_AGC1_EN BIT(7)
0176
0177
0178 struct jz_codec {
0179 struct device *dev;
0180 struct regmap *regmap;
0181 void __iomem *base;
0182 struct clk *clk;
0183 };
0184
0185 static int jz4770_codec_set_bias_level(struct snd_soc_component *codec,
0186 enum snd_soc_bias_level level)
0187 {
0188 struct jz_codec *jz_codec = snd_soc_component_get_drvdata(codec);
0189 struct regmap *regmap = jz_codec->regmap;
0190
0191 switch (level) {
0192 case SND_SOC_BIAS_PREPARE:
0193
0194 regmap_write(regmap, JZ4770_CODEC_REG_IFR, REG_IFR_ALL_MASK);
0195
0196 regmap_clear_bits(regmap, JZ4770_CODEC_REG_CR_VIC,
0197 REG_CR_VIC_SB);
0198 msleep(250);
0199 regmap_clear_bits(regmap, JZ4770_CODEC_REG_CR_VIC,
0200 REG_CR_VIC_SB_SLEEP);
0201 msleep(400);
0202 break;
0203 case SND_SOC_BIAS_STANDBY:
0204 regmap_set_bits(regmap, JZ4770_CODEC_REG_CR_VIC,
0205 REG_CR_VIC_SB_SLEEP);
0206 regmap_set_bits(regmap, JZ4770_CODEC_REG_CR_VIC,
0207 REG_CR_VIC_SB);
0208 fallthrough;
0209 default:
0210 break;
0211 }
0212
0213 return 0;
0214 }
0215
0216 static int jz4770_codec_startup(struct snd_pcm_substream *substream,
0217 struct snd_soc_dai *dai)
0218 {
0219 struct snd_soc_component *codec = dai->component;
0220 struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(codec);
0221
0222
0223
0224
0225
0226
0227 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
0228 snd_soc_dapm_force_enable_pin(dapm, "SYSCLK");
0229
0230 return 0;
0231 }
0232
0233 static void jz4770_codec_shutdown(struct snd_pcm_substream *substream,
0234 struct snd_soc_dai *dai)
0235 {
0236 struct snd_soc_component *codec = dai->component;
0237 struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(codec);
0238
0239 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
0240 snd_soc_dapm_disable_pin(dapm, "SYSCLK");
0241 }
0242
0243
0244 static int jz4770_codec_pcm_trigger(struct snd_pcm_substream *substream,
0245 int cmd, struct snd_soc_dai *dai)
0246 {
0247 struct snd_soc_component *codec = dai->component;
0248 int ret = 0;
0249
0250 switch (cmd) {
0251 case SNDRV_PCM_TRIGGER_START:
0252 case SNDRV_PCM_TRIGGER_RESUME:
0253 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
0254 if (substream->stream != SNDRV_PCM_STREAM_PLAYBACK)
0255 snd_soc_component_force_bias_level(codec,
0256 SND_SOC_BIAS_ON);
0257 break;
0258 case SNDRV_PCM_TRIGGER_STOP:
0259 case SNDRV_PCM_TRIGGER_SUSPEND:
0260 case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
0261
0262 break;
0263 default:
0264 ret = -EINVAL;
0265 }
0266
0267 return ret;
0268 }
0269
0270 static int jz4770_codec_mute_stream(struct snd_soc_dai *dai, int mute, int direction)
0271 {
0272 struct snd_soc_component *codec = dai->component;
0273 struct jz_codec *jz_codec = snd_soc_component_get_drvdata(codec);
0274 unsigned int gain_bit = mute ? REG_IFR_GDO : REG_IFR_GUP;
0275 unsigned int val;
0276 int change, err;
0277
0278 change = snd_soc_component_update_bits(codec, JZ4770_CODEC_REG_CR_DAC,
0279 REG_CR_DAC_MUTE,
0280 mute ? REG_CR_DAC_MUTE : 0);
0281 if (change == 1) {
0282 regmap_read(jz_codec->regmap, JZ4770_CODEC_REG_CR_DAC, &val);
0283
0284 if (val & BIT(REG_CR_DAC_SB_OFFSET))
0285 return 1;
0286
0287 err = regmap_read_poll_timeout(jz_codec->regmap,
0288 JZ4770_CODEC_REG_IFR,
0289 val, val & gain_bit,
0290 1000, 1 * USEC_PER_SEC);
0291 if (err) {
0292 dev_err(jz_codec->dev,
0293 "Timeout while setting digital mute: %d", err);
0294 return err;
0295 }
0296
0297
0298 regmap_set_bits(jz_codec->regmap, JZ4770_CODEC_REG_IFR,
0299 gain_bit);
0300 }
0301
0302 return 0;
0303 }
0304
0305
0306 static const DECLARE_TLV_DB_MINMAX_MUTE(dac_tlv, -3100, 0);
0307 static const DECLARE_TLV_DB_SCALE(adc_tlv, 0, 100, 0);
0308 static const DECLARE_TLV_DB_MINMAX(out_tlv, -2500, 600);
0309 static const DECLARE_TLV_DB_SCALE(linein_tlv, -2500, 100, 0);
0310 static const DECLARE_TLV_DB_MINMAX(mixer_tlv, -3100, 0);
0311
0312
0313 static const struct snd_kcontrol_new jz4770_codec_snd_controls[] = {
0314
0315 SOC_DOUBLE_R_TLV("PCM Capture Volume",
0316 JZ4770_CODEC_REG_GCR_ADCL, JZ4770_CODEC_REG_GCR_ADCR,
0317 REG_GCR_ADC_GAIN_OFFSET, REG_GCR_ADC_GAIN_MAX,
0318 0, adc_tlv),
0319
0320 SOC_DOUBLE_R_TLV("Line In Bypass Playback Volume",
0321 JZ4770_CODEC_REG_GCR_LIBYL, JZ4770_CODEC_REG_GCR_LIBYR,
0322 REG_GCR_GAIN_OFFSET, REG_GCR_GAIN_MAX, 1, linein_tlv),
0323
0324 SOC_SINGLE_TLV("Mixer Capture Volume",
0325 JZ4770_CODEC_REG_GCR_MIXADC,
0326 REG_GCR_GAIN_OFFSET, REG_GCR_GAIN_MAX, 1, mixer_tlv),
0327
0328 SOC_SINGLE_TLV("Mixer Playback Volume",
0329 JZ4770_CODEC_REG_GCR_MIXDAC,
0330 REG_GCR_GAIN_OFFSET, REG_GCR_GAIN_MAX, 1, mixer_tlv),
0331 };
0332
0333 static const struct snd_kcontrol_new jz4770_codec_pcm_playback_controls[] = {
0334 {
0335 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
0336 .name = "Volume",
0337 .info = snd_soc_info_volsw,
0338 .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ
0339 | SNDRV_CTL_ELEM_ACCESS_READWRITE,
0340 .tlv.p = dac_tlv,
0341 .get = snd_soc_dapm_get_volsw,
0342 .put = snd_soc_dapm_put_volsw,
0343
0344
0345
0346
0347
0348 .private_value = SOC_DOUBLE_R_VALUE(JZ4770_CODEC_REG_GCR_DACR,
0349 JZ4770_CODEC_REG_GCR_DACL,
0350 REG_GCR_GAIN_OFFSET,
0351 REG_GCR_GAIN_MAX, 1),
0352 },
0353 };
0354
0355 static const struct snd_kcontrol_new jz4770_codec_hp_playback_controls[] = {
0356 {
0357 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
0358 .name = "Volume",
0359 .info = snd_soc_info_volsw,
0360 .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ
0361 | SNDRV_CTL_ELEM_ACCESS_READWRITE,
0362 .tlv.p = out_tlv,
0363 .get = snd_soc_dapm_get_volsw,
0364 .put = snd_soc_dapm_put_volsw,
0365
0366 .private_value = SOC_DOUBLE_R_VALUE(JZ4770_CODEC_REG_GCR_HPR,
0367 JZ4770_CODEC_REG_GCR_HPL,
0368 REG_GCR_GAIN_OFFSET,
0369 REG_GCR_GAIN_MAX, 1),
0370 },
0371 };
0372
0373 static int hpout_event(struct snd_soc_dapm_widget *w,
0374 struct snd_kcontrol *kcontrol, int event)
0375 {
0376 struct snd_soc_component *codec = snd_soc_dapm_to_component(w->dapm);
0377 struct jz_codec *jz_codec = snd_soc_component_get_drvdata(codec);
0378 unsigned int val;
0379 int err;
0380
0381 switch (event) {
0382 case SND_SOC_DAPM_PRE_PMU:
0383
0384 regmap_clear_bits(jz_codec->regmap, JZ4770_CODEC_REG_CR_HP,
0385 REG_CR_HP_MUTE);
0386 break;
0387
0388 case SND_SOC_DAPM_POST_PMU:
0389
0390 err = regmap_read_poll_timeout(jz_codec->regmap,
0391 JZ4770_CODEC_REG_IFR,
0392 val, val & REG_IFR_RUP,
0393 1000, 1 * USEC_PER_SEC);
0394 if (err) {
0395 dev_err(jz_codec->dev, "RUP timeout: %d", err);
0396 return err;
0397 }
0398
0399
0400 regmap_set_bits(jz_codec->regmap, JZ4770_CODEC_REG_IFR,
0401 REG_IFR_RUP);
0402
0403 break;
0404
0405 case SND_SOC_DAPM_POST_PMD:
0406
0407 regmap_set_bits(jz_codec->regmap, JZ4770_CODEC_REG_CR_HP,
0408 REG_CR_HP_MUTE);
0409
0410 err = regmap_read_poll_timeout(jz_codec->regmap,
0411 JZ4770_CODEC_REG_IFR,
0412 val, val & REG_IFR_RDO,
0413 1000, 1 * USEC_PER_SEC);
0414 if (err) {
0415 dev_err(jz_codec->dev, "RDO timeout: %d", err);
0416 return err;
0417 }
0418
0419
0420 regmap_set_bits(jz_codec->regmap, JZ4770_CODEC_REG_IFR,
0421 REG_IFR_RDO);
0422
0423 break;
0424 }
0425
0426 return 0;
0427 }
0428
0429 static int adc_poweron_event(struct snd_soc_dapm_widget *w,
0430 struct snd_kcontrol *kcontrol, int event)
0431 {
0432 if (event == SND_SOC_DAPM_POST_PMU)
0433 msleep(1000);
0434
0435 return 0;
0436 }
0437
0438 static const char * const jz4770_codec_hp_texts[] = {
0439 "PCM", "Line In", "Mic 1", "Mic 2"
0440 };
0441 static const unsigned int jz4770_codec_hp_values[] = { 3, 2, 0, 1 };
0442 static SOC_VALUE_ENUM_SINGLE_DECL(jz4770_codec_hp_enum,
0443 JZ4770_CODEC_REG_CR_HP,
0444 REG_CR_HP_SEL_OFFSET,
0445 REG_CR_HP_SEL_MASK,
0446 jz4770_codec_hp_texts,
0447 jz4770_codec_hp_values);
0448 static const struct snd_kcontrol_new jz4770_codec_hp_source =
0449 SOC_DAPM_ENUM("Route", jz4770_codec_hp_enum);
0450
0451 static SOC_VALUE_ENUM_SINGLE_DECL(jz4770_codec_lo_enum,
0452 JZ4770_CODEC_REG_CR_LO,
0453 REG_CR_LO_SEL_OFFSET,
0454 REG_CR_LO_SEL_MASK,
0455 jz4770_codec_hp_texts,
0456 jz4770_codec_hp_values);
0457 static const struct snd_kcontrol_new jz4770_codec_lo_source =
0458 SOC_DAPM_ENUM("Route", jz4770_codec_lo_enum);
0459
0460 static const char * const jz4770_codec_cap_texts[] = {
0461 "Line In", "Mic 1", "Mic 2"
0462 };
0463 static const unsigned int jz4770_codec_cap_values[] = { 2, 0, 1 };
0464 static SOC_VALUE_ENUM_SINGLE_DECL(jz4770_codec_cap_enum,
0465 JZ4770_CODEC_REG_CR_ADC,
0466 REG_CR_ADC_IN_SEL_OFFSET,
0467 REG_CR_ADC_IN_SEL_MASK,
0468 jz4770_codec_cap_texts,
0469 jz4770_codec_cap_values);
0470 static const struct snd_kcontrol_new jz4770_codec_cap_source =
0471 SOC_DAPM_ENUM("Route", jz4770_codec_cap_enum);
0472
0473 static const struct snd_kcontrol_new jz4770_codec_mic_controls[] = {
0474 SOC_DAPM_SINGLE("Stereo Capture Switch", JZ4770_CODEC_REG_CR_MIC,
0475 REG_CR_MIC_STEREO_OFFSET, 1, 0),
0476 };
0477
0478 static const struct snd_soc_dapm_widget jz4770_codec_dapm_widgets[] = {
0479 SND_SOC_DAPM_PGA_E("HP Out", JZ4770_CODEC_REG_CR_HP,
0480 REG_CR_HP_SB_OFFSET, 1, NULL, 0, hpout_event,
0481 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
0482 SND_SOC_DAPM_POST_PMD),
0483
0484 SND_SOC_DAPM_PGA("Line Out", JZ4770_CODEC_REG_CR_LO,
0485 REG_CR_LO_SB_OFFSET, 1, NULL, 0),
0486
0487 SND_SOC_DAPM_PGA("Line Out Switch 2", JZ4770_CODEC_REG_CR_LO,
0488 REG_CR_LO_MUTE_OFFSET, 1, NULL, 0),
0489
0490 SND_SOC_DAPM_PGA("Line In", JZ4770_CODEC_REG_CR_LI,
0491 REG_CR_LI_SB_OFFSET, 1, NULL, 0),
0492
0493 SND_SOC_DAPM_MUX("Headphones Source", SND_SOC_NOPM, 0, 0,
0494 &jz4770_codec_hp_source),
0495 SND_SOC_DAPM_MUX("Capture Source", SND_SOC_NOPM, 0, 0,
0496 &jz4770_codec_cap_source),
0497 SND_SOC_DAPM_MUX("Line Out Source", SND_SOC_NOPM, 0, 0,
0498 &jz4770_codec_lo_source),
0499
0500 SND_SOC_DAPM_PGA("Mic 1", JZ4770_CODEC_REG_CR_MIC,
0501 REG_CR_MIC_SB_MIC1_OFFSET, 1, NULL, 0),
0502 SND_SOC_DAPM_PGA("Mic 2", JZ4770_CODEC_REG_CR_MIC,
0503 REG_CR_MIC_SB_MIC2_OFFSET, 1, NULL, 0),
0504
0505 SND_SOC_DAPM_PGA("Mic Diff", JZ4770_CODEC_REG_CR_MIC,
0506 REG_CR_MIC_IDIFF_OFFSET, 0, NULL, 0),
0507
0508 SND_SOC_DAPM_MIXER("Mic", SND_SOC_NOPM, 0, 0,
0509 jz4770_codec_mic_controls,
0510 ARRAY_SIZE(jz4770_codec_mic_controls)),
0511
0512 SND_SOC_DAPM_PGA("Line In Bypass", JZ4770_CODEC_REG_CR_LI,
0513 REG_CR_LI_LIBY_OFFSET, 1, NULL, 0),
0514
0515 SND_SOC_DAPM_ADC_E("ADC", "HiFi Capture", JZ4770_CODEC_REG_CR_ADC,
0516 REG_CR_ADC_SB_OFFSET, 1, adc_poweron_event,
0517 SND_SOC_DAPM_POST_PMU),
0518 SND_SOC_DAPM_DAC("DAC", "HiFi Playback", JZ4770_CODEC_REG_CR_DAC,
0519 REG_CR_DAC_SB_OFFSET, 1),
0520
0521 SND_SOC_DAPM_MIXER("PCM Playback", SND_SOC_NOPM, 0, 0,
0522 jz4770_codec_pcm_playback_controls,
0523 ARRAY_SIZE(jz4770_codec_pcm_playback_controls)),
0524 SND_SOC_DAPM_MIXER("Headphones Playback", SND_SOC_NOPM, 0, 0,
0525 jz4770_codec_hp_playback_controls,
0526 ARRAY_SIZE(jz4770_codec_hp_playback_controls)),
0527
0528 SND_SOC_DAPM_SUPPLY("MICBIAS", JZ4770_CODEC_REG_CR_MIC,
0529 REG_CR_MIC_BIAS_SB_OFFSET, 1, NULL, 0),
0530
0531 SND_SOC_DAPM_SUPPLY("Cap-less", JZ4770_CODEC_REG_CR_HP,
0532 REG_CR_HP_SB_HPCM_OFFSET, 1, NULL, 0),
0533
0534 SND_SOC_DAPM_INPUT("MIC1P"),
0535 SND_SOC_DAPM_INPUT("MIC1N"),
0536 SND_SOC_DAPM_INPUT("MIC2P"),
0537 SND_SOC_DAPM_INPUT("MIC2N"),
0538
0539 SND_SOC_DAPM_OUTPUT("LOUT"),
0540 SND_SOC_DAPM_OUTPUT("ROUT"),
0541
0542 SND_SOC_DAPM_OUTPUT("LHPOUT"),
0543 SND_SOC_DAPM_OUTPUT("RHPOUT"),
0544
0545 SND_SOC_DAPM_INPUT("LLINEIN"),
0546 SND_SOC_DAPM_INPUT("RLINEIN"),
0547
0548 SND_SOC_DAPM_OUTPUT("SYSCLK"),
0549 };
0550
0551
0552 static const struct snd_soc_dapm_route jz4770_codec_dapm_routes[] = {
0553 { "Mic 1", NULL, "MIC1P" },
0554 { "Mic Diff", NULL, "MIC1N" },
0555 { "Mic 1", NULL, "Mic Diff" },
0556 { "Mic 2", NULL, "MIC2P" },
0557 { "Mic Diff", NULL, "MIC2N" },
0558 { "Mic 2", NULL, "Mic Diff" },
0559
0560 { "Line In", NULL, "LLINEIN" },
0561 { "Line In", NULL, "RLINEIN" },
0562
0563 { "Mic", "Stereo Capture Switch", "Mic 1" },
0564 { "Mic", "Stereo Capture Switch", "Mic 2" },
0565 { "Headphones Source", "Mic 1", "Mic" },
0566 { "Headphones Source", "Mic 2", "Mic" },
0567 { "Capture Source", "Mic 1", "Mic" },
0568 { "Capture Source", "Mic 2", "Mic" },
0569
0570 { "Headphones Source", "Mic 1", "Mic 1" },
0571 { "Headphones Source", "Mic 2", "Mic 2" },
0572 { "Headphones Source", "Line In", "Line In Bypass" },
0573 { "Headphones Source", "PCM", "Headphones Playback" },
0574 { "HP Out", NULL, "Headphones Source" },
0575
0576 { "Capture Source", "Line In", "Line In" },
0577 { "Capture Source", "Mic 1", "Mic 1" },
0578 { "Capture Source", "Mic 2", "Mic 2" },
0579 { "ADC", NULL, "Capture Source" },
0580
0581 { "Line In Bypass", NULL, "Line In" },
0582 { "Line Out Source", "Line In", "Line In Bypass" },
0583 { "Line Out Source", "PCM", "PCM Playback" },
0584
0585 { "LHPOUT", NULL, "HP Out"},
0586 { "RHPOUT", NULL, "HP Out"},
0587
0588 { "Line Out", NULL, "Line Out Source" },
0589 { "Line Out Switch 2", NULL, "Line Out" },
0590
0591 { "LOUT", NULL, "Line Out Switch 2"},
0592 { "ROUT", NULL, "Line Out Switch 2"},
0593
0594 { "PCM Playback", "Volume", "DAC" },
0595 { "Headphones Playback", "Volume", "PCM Playback" },
0596
0597 { "SYSCLK", NULL, "DAC" },
0598 };
0599
0600 static void jz4770_codec_codec_init_regs(struct snd_soc_component *codec)
0601 {
0602 struct jz_codec *jz_codec = snd_soc_component_get_drvdata(codec);
0603 struct regmap *regmap = jz_codec->regmap;
0604
0605
0606 regcache_cache_only(regmap, true);
0607
0608
0609 regmap_set_bits(regmap, JZ4770_CODEC_REG_CR_HP, REG_CR_HP_SEL_MASK);
0610
0611
0612 regmap_set_bits(regmap, JZ4770_CODEC_REG_CR_LO, REG_CR_LO_SEL_MASK);
0613
0614
0615 regmap_clear_bits(regmap, JZ4770_CODEC_REG_CR_MIC,
0616 BIT(REG_CR_MIC_STEREO_OFFSET));
0617
0618
0619 regmap_clear_bits(regmap, JZ4770_CODEC_REG_CR_ADC,
0620 REG_CR_ADC_IN_SEL_MASK);
0621
0622
0623 regmap_set_bits(regmap, JZ4770_CODEC_REG_AICR_ADC,
0624 REG_AICR_ADC_SERIAL | REG_AICR_ADC_I2S);
0625 regmap_set_bits(regmap, JZ4770_CODEC_REG_AICR_DAC,
0626 REG_AICR_DAC_SERIAL | REG_AICR_DAC_I2S);
0627
0628
0629 regmap_clear_bits(regmap, JZ4770_CODEC_REG_ICR, REG_ICR_INT_FORM_MASK);
0630 regmap_update_bits(regmap, JZ4770_CODEC_REG_IMR, REG_IMR_ALL_MASK,
0631 REG_IMR_JACK_MASK | REG_IMR_RUP_MASK |
0632 REG_IMR_RDO_MASK | REG_IMR_GUP_MASK |
0633 REG_IMR_GDO_MASK);
0634
0635
0636 regmap_clear_bits(regmap, JZ4770_CODEC_REG_CCR, REG_CCR_CRYSTAL_MASK);
0637
0638
0639 regmap_clear_bits(regmap, JZ4770_CODEC_REG_CR_HP, REG_CR_HP_LOAD);
0640
0641
0642 regmap_clear_bits(regmap, JZ4770_CODEC_REG_AGC1, REG_AGC1_EN);
0643
0644
0645 regmap_set_bits(regmap, JZ4770_CODEC_REG_CR_DAC, REG_CR_DAC_LRSWAP);
0646
0647
0648 regmap_clear_bits(regmap, JZ4770_CODEC_REG_GCR_DACL,
0649 REG_GCR_DACL_RLGOD);
0650
0651
0652 regmap_set_bits(regmap, JZ4770_CODEC_REG_CR_ADC, REG_CR_ADC_LRSWAP);
0653
0654
0655 regmap_clear_bits(regmap, JZ4770_CODEC_REG_CR_HP,
0656 BIT(REG_CR_HP_SB_HPCM_OFFSET));
0657
0658
0659 regcache_cache_only(regmap, false);
0660 regcache_sync(regmap);
0661 }
0662
0663 static int jz4770_codec_codec_probe(struct snd_soc_component *codec)
0664 {
0665 struct jz_codec *jz_codec = snd_soc_component_get_drvdata(codec);
0666
0667 clk_prepare_enable(jz_codec->clk);
0668
0669 jz4770_codec_codec_init_regs(codec);
0670
0671 return 0;
0672 }
0673
0674 static void jz4770_codec_codec_remove(struct snd_soc_component *codec)
0675 {
0676 struct jz_codec *jz_codec = snd_soc_component_get_drvdata(codec);
0677
0678 clk_disable_unprepare(jz_codec->clk);
0679 }
0680
0681 static const struct snd_soc_component_driver jz4770_codec_soc_codec_dev = {
0682 .probe = jz4770_codec_codec_probe,
0683 .remove = jz4770_codec_codec_remove,
0684 .set_bias_level = jz4770_codec_set_bias_level,
0685 .controls = jz4770_codec_snd_controls,
0686 .num_controls = ARRAY_SIZE(jz4770_codec_snd_controls),
0687 .dapm_widgets = jz4770_codec_dapm_widgets,
0688 .num_dapm_widgets = ARRAY_SIZE(jz4770_codec_dapm_widgets),
0689 .dapm_routes = jz4770_codec_dapm_routes,
0690 .num_dapm_routes = ARRAY_SIZE(jz4770_codec_dapm_routes),
0691 .suspend_bias_off = 1,
0692 .use_pmdown_time = 1,
0693 };
0694
0695 static const unsigned int jz4770_codec_sample_rates[] = {
0696 96000, 48000, 44100, 32000,
0697 24000, 22050, 16000, 12000,
0698 11025, 9600, 8000,
0699 };
0700
0701 static int jz4770_codec_hw_params(struct snd_pcm_substream *substream,
0702 struct snd_pcm_hw_params *params,
0703 struct snd_soc_dai *dai)
0704 {
0705 struct jz_codec *codec = snd_soc_component_get_drvdata(dai->component);
0706 unsigned int rate, bit_width;
0707
0708 switch (params_format(params)) {
0709 case SNDRV_PCM_FORMAT_S16_LE:
0710 bit_width = 0;
0711 break;
0712 case SNDRV_PCM_FORMAT_S18_3LE:
0713 bit_width = 1;
0714 break;
0715 case SNDRV_PCM_FORMAT_S20_3LE:
0716 bit_width = 2;
0717 break;
0718 case SNDRV_PCM_FORMAT_S24_3LE:
0719 bit_width = 3;
0720 break;
0721 default:
0722 return -EINVAL;
0723 }
0724
0725 for (rate = 0; rate < ARRAY_SIZE(jz4770_codec_sample_rates); rate++) {
0726 if (jz4770_codec_sample_rates[rate] == params_rate(params))
0727 break;
0728 }
0729
0730 if (rate == ARRAY_SIZE(jz4770_codec_sample_rates))
0731 return -EINVAL;
0732
0733 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
0734 regmap_update_bits(codec->regmap, JZ4770_CODEC_REG_AICR_DAC,
0735 REG_AICR_DAC_ADWL_MASK,
0736 bit_width << REG_AICR_DAC_ADWL_OFFSET);
0737 regmap_update_bits(codec->regmap, JZ4770_CODEC_REG_FCR_DAC,
0738 REG_FCR_DAC_FREQ_MASK,
0739 rate << REG_FCR_DAC_FREQ_OFFSET);
0740 } else {
0741 regmap_update_bits(codec->regmap, JZ4770_CODEC_REG_AICR_ADC,
0742 REG_AICR_ADC_ADWL_MASK,
0743 bit_width << REG_AICR_ADC_ADWL_OFFSET);
0744 regmap_update_bits(codec->regmap, JZ4770_CODEC_REG_FCR_ADC,
0745 REG_FCR_ADC_FREQ_MASK,
0746 rate << REG_FCR_ADC_FREQ_OFFSET);
0747 }
0748
0749 return 0;
0750 }
0751
0752 static const struct snd_soc_dai_ops jz4770_codec_dai_ops = {
0753 .startup = jz4770_codec_startup,
0754 .shutdown = jz4770_codec_shutdown,
0755 .hw_params = jz4770_codec_hw_params,
0756 .trigger = jz4770_codec_pcm_trigger,
0757 .mute_stream = jz4770_codec_mute_stream,
0758 .no_capture_mute = 1,
0759 };
0760
0761 #define JZ_CODEC_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | \
0762 SNDRV_PCM_FMTBIT_S18_3LE | \
0763 SNDRV_PCM_FMTBIT_S20_3LE | \
0764 SNDRV_PCM_FMTBIT_S24_3LE)
0765
0766 static struct snd_soc_dai_driver jz4770_codec_dai = {
0767 .name = "jz4770-hifi",
0768 .playback = {
0769 .stream_name = "Playback",
0770 .channels_min = 2,
0771 .channels_max = 2,
0772 .rates = SNDRV_PCM_RATE_8000_96000,
0773 .formats = JZ_CODEC_FORMATS,
0774 },
0775 .capture = {
0776 .stream_name = "Capture",
0777 .channels_min = 2,
0778 .channels_max = 2,
0779 .rates = SNDRV_PCM_RATE_8000_96000,
0780 .formats = JZ_CODEC_FORMATS,
0781 },
0782 .ops = &jz4770_codec_dai_ops,
0783 };
0784
0785 static bool jz4770_codec_volatile(struct device *dev, unsigned int reg)
0786 {
0787 return reg == JZ4770_CODEC_REG_SR || reg == JZ4770_CODEC_REG_IFR;
0788 }
0789
0790 static bool jz4770_codec_readable(struct device *dev, unsigned int reg)
0791 {
0792 switch (reg) {
0793 case JZ4770_CODEC_REG_MISSING_REG1:
0794 case JZ4770_CODEC_REG_MISSING_REG2:
0795 return false;
0796 default:
0797 return true;
0798 }
0799 }
0800
0801 static bool jz4770_codec_writeable(struct device *dev, unsigned int reg)
0802 {
0803 switch (reg) {
0804 case JZ4770_CODEC_REG_SR:
0805 case JZ4770_CODEC_REG_MISSING_REG1:
0806 case JZ4770_CODEC_REG_MISSING_REG2:
0807 return false;
0808 default:
0809 return true;
0810 }
0811 }
0812
0813 static int jz4770_codec_io_wait(struct jz_codec *codec)
0814 {
0815 u32 reg;
0816
0817 return readl_poll_timeout(codec->base + ICDC_RGADW_OFFSET, reg,
0818 !(reg & ICDC_RGADW_RGWR),
0819 1000, 1 * USEC_PER_SEC);
0820 }
0821
0822 static int jz4770_codec_reg_read(void *context, unsigned int reg,
0823 unsigned int *val)
0824 {
0825 struct jz_codec *codec = context;
0826 unsigned int i;
0827 u32 tmp;
0828 int ret;
0829
0830 ret = jz4770_codec_io_wait(codec);
0831 if (ret)
0832 return ret;
0833
0834 tmp = readl(codec->base + ICDC_RGADW_OFFSET);
0835 tmp = (tmp & ~ICDC_RGADW_RGADDR_MASK)
0836 | (reg << ICDC_RGADW_RGADDR_OFFSET);
0837 writel(tmp, codec->base + ICDC_RGADW_OFFSET);
0838
0839
0840 for (i = 0; i < 6; i++)
0841 *val = readl(codec->base + ICDC_RGDATA_OFFSET) &
0842 ICDC_RGDATA_RGDOUT_MASK;
0843
0844 return 0;
0845 }
0846
0847 static int jz4770_codec_reg_write(void *context, unsigned int reg,
0848 unsigned int val)
0849 {
0850 struct jz_codec *codec = context;
0851 int ret;
0852
0853 ret = jz4770_codec_io_wait(codec);
0854 if (ret)
0855 return ret;
0856
0857 writel(ICDC_RGADW_RGWR | (reg << ICDC_RGADW_RGADDR_OFFSET) | val,
0858 codec->base + ICDC_RGADW_OFFSET);
0859
0860 ret = jz4770_codec_io_wait(codec);
0861 if (ret)
0862 return ret;
0863
0864 return 0;
0865 }
0866
0867 static const u8 jz4770_codec_reg_defaults[] = {
0868 0x00, 0xC3, 0xC3, 0x90, 0x98, 0xFF, 0x90, 0xB1,
0869 0x11, 0x10, 0x00, 0x03, 0x00, 0x00, 0x40, 0x00,
0870 0xFF, 0x00, 0x06, 0x06, 0x06, 0x06, 0x00, 0x00,
0871 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x34,
0872 0x07, 0x44, 0x1F, 0x00
0873 };
0874
0875 static struct regmap_config jz4770_codec_regmap_config = {
0876 .reg_bits = 7,
0877 .val_bits = 8,
0878
0879 .max_register = JZ4770_CODEC_REG_AGC5,
0880 .volatile_reg = jz4770_codec_volatile,
0881 .readable_reg = jz4770_codec_readable,
0882 .writeable_reg = jz4770_codec_writeable,
0883
0884 .reg_read = jz4770_codec_reg_read,
0885 .reg_write = jz4770_codec_reg_write,
0886
0887 .reg_defaults_raw = jz4770_codec_reg_defaults,
0888 .num_reg_defaults_raw = ARRAY_SIZE(jz4770_codec_reg_defaults),
0889 .cache_type = REGCACHE_FLAT,
0890 };
0891
0892 static int jz4770_codec_probe(struct platform_device *pdev)
0893 {
0894 struct device *dev = &pdev->dev;
0895 struct jz_codec *codec;
0896 int ret;
0897
0898 codec = devm_kzalloc(dev, sizeof(*codec), GFP_KERNEL);
0899 if (!codec)
0900 return -ENOMEM;
0901
0902 codec->dev = dev;
0903
0904 codec->base = devm_platform_ioremap_resource(pdev, 0);
0905 if (IS_ERR(codec->base))
0906 return PTR_ERR(codec->base);
0907
0908 codec->regmap = devm_regmap_init(dev, NULL, codec,
0909 &jz4770_codec_regmap_config);
0910 if (IS_ERR(codec->regmap))
0911 return PTR_ERR(codec->regmap);
0912
0913 codec->clk = devm_clk_get(dev, "aic");
0914 if (IS_ERR(codec->clk))
0915 return PTR_ERR(codec->clk);
0916
0917 platform_set_drvdata(pdev, codec);
0918
0919 ret = devm_snd_soc_register_component(dev, &jz4770_codec_soc_codec_dev,
0920 &jz4770_codec_dai, 1);
0921 if (ret) {
0922 dev_err(dev, "Failed to register codec: %d\n", ret);
0923 return ret;
0924 }
0925
0926 return 0;
0927 }
0928
0929 static const struct of_device_id jz4770_codec_of_matches[] = {
0930 { .compatible = "ingenic,jz4770-codec", },
0931 { }
0932 };
0933 MODULE_DEVICE_TABLE(of, jz4770_codec_of_matches);
0934
0935 static struct platform_driver jz4770_codec_driver = {
0936 .probe = jz4770_codec_probe,
0937 .driver = {
0938 .name = "jz4770-codec",
0939 .of_match_table = jz4770_codec_of_matches,
0940 },
0941 };
0942 module_platform_driver(jz4770_codec_driver);
0943
0944 MODULE_DESCRIPTION("JZ4770 SoC internal codec driver");
0945 MODULE_AUTHOR("Maarten ter Huurne <maarten@treewalker.org>");
0946 MODULE_AUTHOR("Paul Cercueil <paul@crapouillou.net>");
0947 MODULE_LICENSE("GPL v2");