diff options
-rw-r--r-- | sound/soc/codecs/rt286.c | 211 |
1 files changed, 155 insertions, 56 deletions
diff --git a/sound/soc/codecs/rt286.c b/sound/soc/codecs/rt286.c index 4aa555cbcca8..97daa80e9104 100644 --- a/sound/soc/codecs/rt286.c +++ b/sound/soc/codecs/rt286.c | |||
@@ -36,11 +36,13 @@ | |||
36 | 36 | ||
37 | struct rt286_priv { | 37 | struct rt286_priv { |
38 | struct regmap *regmap; | 38 | struct regmap *regmap; |
39 | struct snd_soc_codec *codec; | ||
39 | struct rt286_platform_data pdata; | 40 | struct rt286_platform_data pdata; |
40 | struct i2c_client *i2c; | 41 | struct i2c_client *i2c; |
41 | struct snd_soc_jack *jack; | 42 | struct snd_soc_jack *jack; |
42 | struct delayed_work jack_detect_work; | 43 | struct delayed_work jack_detect_work; |
43 | int sys_clk; | 44 | int sys_clk; |
45 | int clk_id; | ||
44 | struct reg_default *index_cache; | 46 | struct reg_default *index_cache; |
45 | }; | 47 | }; |
46 | 48 | ||
@@ -298,7 +300,6 @@ static int rt286_support_power_controls[] = { | |||
298 | static int rt286_jack_detect(struct rt286_priv *rt286, bool *hp, bool *mic) | 300 | static int rt286_jack_detect(struct rt286_priv *rt286, bool *hp, bool *mic) |
299 | { | 301 | { |
300 | unsigned int val, buf; | 302 | unsigned int val, buf; |
301 | int i; | ||
302 | 303 | ||
303 | *hp = false; | 304 | *hp = false; |
304 | *mic = false; | 305 | *mic = false; |
@@ -309,67 +310,44 @@ static int rt286_jack_detect(struct rt286_priv *rt286, bool *hp, bool *mic) | |||
309 | if (*hp) { | 310 | if (*hp) { |
310 | /* power on HV,VERF */ | 311 | /* power on HV,VERF */ |
311 | regmap_update_bits(rt286->regmap, | 312 | regmap_update_bits(rt286->regmap, |
312 | RT286_POWER_CTRL1, 0x1001, 0x0); | 313 | RT286_DC_GAIN, 0x200, 0x200); |
314 | |||
315 | snd_soc_dapm_force_enable_pin(&rt286->codec->dapm, | ||
316 | "HV"); | ||
317 | snd_soc_dapm_force_enable_pin(&rt286->codec->dapm, | ||
318 | "VREF"); | ||
313 | /* power LDO1 */ | 319 | /* power LDO1 */ |
314 | regmap_update_bits(rt286->regmap, | 320 | snd_soc_dapm_force_enable_pin(&rt286->codec->dapm, |
315 | RT286_POWER_CTRL2, 0x4, 0x4); | 321 | "LDO1"); |
316 | regmap_write(rt286->regmap, RT286_SET_MIC1, 0x24); | 322 | snd_soc_dapm_sync(&rt286->codec->dapm); |
317 | regmap_read(rt286->regmap, RT286_CBJ_CTRL2, &val); | ||
318 | 323 | ||
319 | msleep(200); | 324 | regmap_write(rt286->regmap, RT286_SET_MIC1, 0x24); |
320 | i = 40; | 325 | msleep(50); |
321 | while (((val & 0x0800) == 0) && (i > 0)) { | ||
322 | regmap_read(rt286->regmap, | ||
323 | RT286_CBJ_CTRL2, &val); | ||
324 | i--; | ||
325 | msleep(20); | ||
326 | } | ||
327 | 326 | ||
328 | if (0x0400 == (val & 0x0700)) { | 327 | regmap_update_bits(rt286->regmap, |
329 | *mic = false; | 328 | RT286_CBJ_CTRL1, 0xfcc0, 0xd400); |
329 | msleep(300); | ||
330 | regmap_read(rt286->regmap, RT286_CBJ_CTRL2, &val); | ||
330 | 331 | ||
331 | regmap_write(rt286->regmap, | 332 | if (0x0070 == (val & 0x0070)) { |
332 | RT286_SET_MIC1, 0x20); | ||
333 | /* power off HV,VERF */ | ||
334 | regmap_update_bits(rt286->regmap, | ||
335 | RT286_POWER_CTRL1, 0x1001, 0x1001); | ||
336 | regmap_update_bits(rt286->regmap, | ||
337 | RT286_A_BIAS_CTRL3, 0xc000, 0x0000); | ||
338 | regmap_update_bits(rt286->regmap, | ||
339 | RT286_CBJ_CTRL1, 0x0030, 0x0000); | ||
340 | regmap_update_bits(rt286->regmap, | ||
341 | RT286_A_BIAS_CTRL2, 0xc000, 0x0000); | ||
342 | } else if ((0x0200 == (val & 0x0700)) || | ||
343 | (0x0100 == (val & 0x0700))) { | ||
344 | *mic = true; | 333 | *mic = true; |
345 | regmap_update_bits(rt286->regmap, | ||
346 | RT286_A_BIAS_CTRL3, 0xc000, 0x8000); | ||
347 | regmap_update_bits(rt286->regmap, | ||
348 | RT286_CBJ_CTRL1, 0x0030, 0x0020); | ||
349 | regmap_update_bits(rt286->regmap, | ||
350 | RT286_A_BIAS_CTRL2, 0xc000, 0x8000); | ||
351 | } else { | 334 | } else { |
352 | *mic = false; | 335 | regmap_update_bits(rt286->regmap, |
336 | RT286_CBJ_CTRL1, 0xfcc0, 0xe400); | ||
337 | msleep(300); | ||
338 | regmap_read(rt286->regmap, | ||
339 | RT286_CBJ_CTRL2, &val); | ||
340 | if (0x0070 == (val & 0x0070)) | ||
341 | *mic = true; | ||
342 | else | ||
343 | *mic = false; | ||
353 | } | 344 | } |
354 | |||
355 | regmap_update_bits(rt286->regmap, | ||
356 | RT286_MISC_CTRL1, | ||
357 | 0x0060, 0x0000); | ||
358 | } else { | ||
359 | regmap_update_bits(rt286->regmap, | ||
360 | RT286_MISC_CTRL1, | ||
361 | 0x0060, 0x0020); | ||
362 | regmap_update_bits(rt286->regmap, | ||
363 | RT286_A_BIAS_CTRL3, | ||
364 | 0xc000, 0x8000); | ||
365 | regmap_update_bits(rt286->regmap, | 345 | regmap_update_bits(rt286->regmap, |
366 | RT286_CBJ_CTRL1, | 346 | RT286_DC_GAIN, 0x200, 0x0); |
367 | 0x0030, 0x0020); | ||
368 | regmap_update_bits(rt286->regmap, | ||
369 | RT286_A_BIAS_CTRL2, | ||
370 | 0xc000, 0x8000); | ||
371 | 347 | ||
348 | } else { | ||
372 | *mic = false; | 349 | *mic = false; |
350 | regmap_write(rt286->regmap, RT286_SET_MIC1, 0x20); | ||
373 | } | 351 | } |
374 | } else { | 352 | } else { |
375 | regmap_read(rt286->regmap, RT286_GET_HP_SENSE, &buf); | 353 | regmap_read(rt286->regmap, RT286_GET_HP_SENSE, &buf); |
@@ -378,6 +356,12 @@ static int rt286_jack_detect(struct rt286_priv *rt286, bool *hp, bool *mic) | |||
378 | *mic = buf & 0x80000000; | 356 | *mic = buf & 0x80000000; |
379 | } | 357 | } |
380 | 358 | ||
359 | snd_soc_dapm_disable_pin(&rt286->codec->dapm, "HV"); | ||
360 | snd_soc_dapm_disable_pin(&rt286->codec->dapm, "VREF"); | ||
361 | if (!*hp) | ||
362 | snd_soc_dapm_disable_pin(&rt286->codec->dapm, "LDO1"); | ||
363 | snd_soc_dapm_sync(&rt286->codec->dapm); | ||
364 | |||
381 | return 0; | 365 | return 0; |
382 | } | 366 | } |
383 | 367 | ||
@@ -415,6 +399,17 @@ int rt286_mic_detect(struct snd_soc_codec *codec, struct snd_soc_jack *jack) | |||
415 | } | 399 | } |
416 | EXPORT_SYMBOL_GPL(rt286_mic_detect); | 400 | EXPORT_SYMBOL_GPL(rt286_mic_detect); |
417 | 401 | ||
402 | static int is_mclk_mode(struct snd_soc_dapm_widget *source, | ||
403 | struct snd_soc_dapm_widget *sink) | ||
404 | { | ||
405 | struct rt286_priv *rt286 = snd_soc_codec_get_drvdata(source->codec); | ||
406 | |||
407 | if (rt286->clk_id == RT286_SCLK_S_MCLK) | ||
408 | return 1; | ||
409 | else | ||
410 | return 0; | ||
411 | } | ||
412 | |||
418 | static const DECLARE_TLV_DB_SCALE(out_vol_tlv, -6350, 50, 0); | 413 | static const DECLARE_TLV_DB_SCALE(out_vol_tlv, -6350, 50, 0); |
419 | static const DECLARE_TLV_DB_SCALE(mic_vol_tlv, 0, 1000, 0); | 414 | static const DECLARE_TLV_DB_SCALE(mic_vol_tlv, 0, 1000, 0); |
420 | 415 | ||
@@ -568,7 +563,84 @@ static int rt286_adc_event(struct snd_soc_dapm_widget *w, | |||
568 | return 0; | 563 | return 0; |
569 | } | 564 | } |
570 | 565 | ||
566 | static int rt286_vref_event(struct snd_soc_dapm_widget *w, | ||
567 | struct snd_kcontrol *kcontrol, int event) | ||
568 | { | ||
569 | struct snd_soc_codec *codec = w->codec; | ||
570 | |||
571 | switch (event) { | ||
572 | case SND_SOC_DAPM_PRE_PMU: | ||
573 | snd_soc_update_bits(codec, | ||
574 | RT286_CBJ_CTRL1, 0x0400, 0x0000); | ||
575 | mdelay(50); | ||
576 | break; | ||
577 | default: | ||
578 | return 0; | ||
579 | } | ||
580 | |||
581 | return 0; | ||
582 | } | ||
583 | |||
584 | static int rt286_ldo2_event(struct snd_soc_dapm_widget *w, | ||
585 | struct snd_kcontrol *kcontrol, int event) | ||
586 | { | ||
587 | struct snd_soc_codec *codec = w->codec; | ||
588 | |||
589 | switch (event) { | ||
590 | case SND_SOC_DAPM_POST_PMU: | ||
591 | snd_soc_update_bits(codec, RT286_POWER_CTRL2, 0x38, 0x08); | ||
592 | break; | ||
593 | case SND_SOC_DAPM_PRE_PMD: | ||
594 | snd_soc_update_bits(codec, RT286_POWER_CTRL2, 0x38, 0x30); | ||
595 | break; | ||
596 | default: | ||
597 | return 0; | ||
598 | } | ||
599 | |||
600 | return 0; | ||
601 | } | ||
602 | |||
603 | static int rt286_mic1_event(struct snd_soc_dapm_widget *w, | ||
604 | struct snd_kcontrol *kcontrol, int event) | ||
605 | { | ||
606 | struct snd_soc_codec *codec = w->codec; | ||
607 | |||
608 | switch (event) { | ||
609 | case SND_SOC_DAPM_PRE_PMU: | ||
610 | snd_soc_update_bits(codec, | ||
611 | RT286_A_BIAS_CTRL3, 0xc000, 0x8000); | ||
612 | snd_soc_update_bits(codec, | ||
613 | RT286_A_BIAS_CTRL2, 0xc000, 0x8000); | ||
614 | break; | ||
615 | case SND_SOC_DAPM_POST_PMD: | ||
616 | snd_soc_update_bits(codec, | ||
617 | RT286_A_BIAS_CTRL3, 0xc000, 0x0000); | ||
618 | snd_soc_update_bits(codec, | ||
619 | RT286_A_BIAS_CTRL2, 0xc000, 0x0000); | ||
620 | break; | ||
621 | default: | ||
622 | return 0; | ||
623 | } | ||
624 | |||
625 | return 0; | ||
626 | } | ||
627 | |||
571 | static const struct snd_soc_dapm_widget rt286_dapm_widgets[] = { | 628 | static const struct snd_soc_dapm_widget rt286_dapm_widgets[] = { |
629 | SND_SOC_DAPM_SUPPLY_S("HV", 1, RT286_POWER_CTRL1, | ||
630 | 12, 1, NULL, 0), | ||
631 | SND_SOC_DAPM_SUPPLY("VREF", RT286_POWER_CTRL1, | ||
632 | 0, 1, rt286_vref_event, SND_SOC_DAPM_PRE_PMU), | ||
633 | SND_SOC_DAPM_SUPPLY_S("LDO1", 1, RT286_POWER_CTRL2, | ||
634 | 2, 0, NULL, 0), | ||
635 | SND_SOC_DAPM_SUPPLY_S("LDO2", 2, RT286_POWER_CTRL1, | ||
636 | 13, 1, rt286_ldo2_event, SND_SOC_DAPM_PRE_PMD | | ||
637 | SND_SOC_DAPM_POST_PMU), | ||
638 | SND_SOC_DAPM_SUPPLY("MCLK MODE", RT286_PLL_CTRL1, | ||
639 | 5, 0, NULL, 0), | ||
640 | SND_SOC_DAPM_SUPPLY("MIC1 Input Buffer", SND_SOC_NOPM, | ||
641 | 0, 0, rt286_mic1_event, SND_SOC_DAPM_PRE_PMU | | ||
642 | SND_SOC_DAPM_POST_PMD), | ||
643 | |||
572 | /* Input Lines */ | 644 | /* Input Lines */ |
573 | SND_SOC_DAPM_INPUT("DMIC1 Pin"), | 645 | SND_SOC_DAPM_INPUT("DMIC1 Pin"), |
574 | SND_SOC_DAPM_INPUT("DMIC2 Pin"), | 646 | SND_SOC_DAPM_INPUT("DMIC2 Pin"), |
@@ -642,6 +714,25 @@ static const struct snd_soc_dapm_widget rt286_dapm_widgets[] = { | |||
642 | }; | 714 | }; |
643 | 715 | ||
644 | static const struct snd_soc_dapm_route rt286_dapm_routes[] = { | 716 | static const struct snd_soc_dapm_route rt286_dapm_routes[] = { |
717 | {"ADC 0", NULL, "MCLK MODE", is_mclk_mode}, | ||
718 | {"ADC 1", NULL, "MCLK MODE", is_mclk_mode}, | ||
719 | {"Front", NULL, "MCLK MODE", is_mclk_mode}, | ||
720 | {"Surround", NULL, "MCLK MODE", is_mclk_mode}, | ||
721 | |||
722 | {"HP Power", NULL, "LDO1"}, | ||
723 | {"HP Power", NULL, "LDO2"}, | ||
724 | |||
725 | {"MIC1", NULL, "LDO1"}, | ||
726 | {"MIC1", NULL, "LDO2"}, | ||
727 | {"MIC1", NULL, "HV"}, | ||
728 | {"MIC1", NULL, "VREF"}, | ||
729 | {"MIC1", NULL, "MIC1 Input Buffer"}, | ||
730 | |||
731 | {"SPO", NULL, "LDO1"}, | ||
732 | {"SPO", NULL, "LDO2"}, | ||
733 | {"SPO", NULL, "HV"}, | ||
734 | {"SPO", NULL, "VREF"}, | ||
735 | |||
645 | {"DMIC1", NULL, "DMIC1 Pin"}, | 736 | {"DMIC1", NULL, "DMIC1 Pin"}, |
646 | {"DMIC2", NULL, "DMIC2 Pin"}, | 737 | {"DMIC2", NULL, "DMIC2 Pin"}, |
647 | {"DMIC1", NULL, "DMIC Receiver"}, | 738 | {"DMIC1", NULL, "DMIC Receiver"}, |
@@ -880,6 +971,7 @@ static int rt286_set_dai_sysclk(struct snd_soc_dai *dai, | |||
880 | } | 971 | } |
881 | 972 | ||
882 | rt286->sys_clk = freq; | 973 | rt286->sys_clk = freq; |
974 | rt286->clk_id = clk_id; | ||
883 | 975 | ||
884 | return 0; | 976 | return 0; |
885 | } | 977 | } |
@@ -915,13 +1007,18 @@ static int rt286_set_bias_level(struct snd_soc_codec *codec, | |||
915 | 1007 | ||
916 | case SND_SOC_BIAS_ON: | 1008 | case SND_SOC_BIAS_ON: |
917 | mdelay(10); | 1009 | mdelay(10); |
1010 | snd_soc_update_bits(codec, | ||
1011 | RT286_CBJ_CTRL1, 0x0400, 0x0400); | ||
1012 | snd_soc_update_bits(codec, | ||
1013 | RT286_DC_GAIN, 0x200, 0x0); | ||
1014 | |||
918 | break; | 1015 | break; |
919 | 1016 | ||
920 | case SND_SOC_BIAS_STANDBY: | 1017 | case SND_SOC_BIAS_STANDBY: |
921 | snd_soc_write(codec, | 1018 | snd_soc_write(codec, |
922 | RT286_SET_AUDIO_POWER, AC_PWRST_D3); | 1019 | RT286_SET_AUDIO_POWER, AC_PWRST_D3); |
923 | snd_soc_update_bits(codec, | 1020 | snd_soc_update_bits(codec, |
924 | RT286_DC_GAIN, 0x200, 0x0); | 1021 | RT286_CBJ_CTRL1, 0x0400, 0x0000); |
925 | break; | 1022 | break; |
926 | 1023 | ||
927 | default: | 1024 | default: |
@@ -962,6 +1059,7 @@ static int rt286_probe(struct snd_soc_codec *codec) | |||
962 | { | 1059 | { |
963 | struct rt286_priv *rt286 = snd_soc_codec_get_drvdata(codec); | 1060 | struct rt286_priv *rt286 = snd_soc_codec_get_drvdata(codec); |
964 | 1061 | ||
1062 | rt286->codec = codec; | ||
965 | codec->dapm.bias_level = SND_SOC_BIAS_OFF; | 1063 | codec->dapm.bias_level = SND_SOC_BIAS_OFF; |
966 | 1064 | ||
967 | if (rt286->i2c->irq) { | 1065 | if (rt286->i2c->irq) { |
@@ -1152,7 +1250,6 @@ static int rt286_i2c_probe(struct i2c_client *i2c, | |||
1152 | if (!rt286->pdata.cbj_en) { | 1250 | if (!rt286->pdata.cbj_en) { |
1153 | regmap_write(rt286->regmap, RT286_CBJ_CTRL2, 0x0000); | 1251 | regmap_write(rt286->regmap, RT286_CBJ_CTRL2, 0x0000); |
1154 | regmap_write(rt286->regmap, RT286_MIC1_DET_CTRL, 0x0816); | 1252 | regmap_write(rt286->regmap, RT286_MIC1_DET_CTRL, 0x0816); |
1155 | regmap_write(rt286->regmap, RT286_MISC_CTRL1, 0x0000); | ||
1156 | regmap_update_bits(rt286->regmap, | 1253 | regmap_update_bits(rt286->regmap, |
1157 | RT286_CBJ_CTRL1, 0xf000, 0xb000); | 1254 | RT286_CBJ_CTRL1, 0xf000, 0xb000); |
1158 | } else { | 1255 | } else { |
@@ -1169,8 +1266,10 @@ static int rt286_i2c_probe(struct i2c_client *i2c, | |||
1169 | 1266 | ||
1170 | mdelay(10); | 1267 | mdelay(10); |
1171 | 1268 | ||
1172 | /*Power down LDO2*/ | 1269 | regmap_write(rt286->regmap, RT286_MISC_CTRL1, 0x0000); |
1173 | regmap_update_bits(rt286->regmap, RT286_POWER_CTRL2, 0x8, 0x0); | 1270 | /*Power down LDO, VREF*/ |
1271 | regmap_update_bits(rt286->regmap, RT286_POWER_CTRL2, 0xc, 0x0); | ||
1272 | regmap_update_bits(rt286->regmap, RT286_POWER_CTRL1, 0x1001, 0x1001); | ||
1174 | 1273 | ||
1175 | /*Set depop parameter*/ | 1274 | /*Set depop parameter*/ |
1176 | regmap_update_bits(rt286->regmap, RT286_DEPOP_CTRL2, 0x403a, 0x401a); | 1275 | regmap_update_bits(rt286->regmap, RT286_DEPOP_CTRL2, 0x403a, 0x401a); |