diff options
Diffstat (limited to 'sound/soc/codecs/rt286.c')
-rw-r--r-- | sound/soc/codecs/rt286.c | 82 |
1 files changed, 42 insertions, 40 deletions
diff --git a/sound/soc/codecs/rt286.c b/sound/soc/codecs/rt286.c index 1d1c7f8a9af2..f374840a5a7c 100644 --- a/sound/soc/codecs/rt286.c +++ b/sound/soc/codecs/rt286.c | |||
@@ -34,6 +34,7 @@ | |||
34 | #include "rt286.h" | 34 | #include "rt286.h" |
35 | 35 | ||
36 | #define RT286_VENDOR_ID 0x10ec0286 | 36 | #define RT286_VENDOR_ID 0x10ec0286 |
37 | #define RT288_VENDOR_ID 0x10ec0288 | ||
37 | 38 | ||
38 | struct rt286_priv { | 39 | struct rt286_priv { |
39 | struct regmap *regmap; | 40 | struct regmap *regmap; |
@@ -305,6 +306,8 @@ static int rt286_jack_detect(struct rt286_priv *rt286, bool *hp, bool *mic) | |||
305 | *hp = false; | 306 | *hp = false; |
306 | *mic = false; | 307 | *mic = false; |
307 | 308 | ||
309 | if (!rt286->codec) | ||
310 | return -EINVAL; | ||
308 | if (rt286->pdata.cbj_en) { | 311 | if (rt286->pdata.cbj_en) { |
309 | regmap_read(rt286->regmap, RT286_GET_HP_SENSE, &buf); | 312 | regmap_read(rt286->regmap, RT286_GET_HP_SENSE, &buf); |
310 | *hp = buf & 0x80000000; | 313 | *hp = buf & 0x80000000; |
@@ -403,7 +406,8 @@ EXPORT_SYMBOL_GPL(rt286_mic_detect); | |||
403 | static int is_mclk_mode(struct snd_soc_dapm_widget *source, | 406 | static int is_mclk_mode(struct snd_soc_dapm_widget *source, |
404 | struct snd_soc_dapm_widget *sink) | 407 | struct snd_soc_dapm_widget *sink) |
405 | { | 408 | { |
406 | struct rt286_priv *rt286 = snd_soc_codec_get_drvdata(source->codec); | 409 | struct snd_soc_codec *codec = snd_soc_dapm_to_codec(source->dapm); |
410 | struct rt286_priv *rt286 = snd_soc_codec_get_drvdata(codec); | ||
407 | 411 | ||
408 | if (rt286->clk_id == RT286_SCLK_S_MCLK) | 412 | if (rt286->clk_id == RT286_SCLK_S_MCLK) |
409 | return 1; | 413 | return 1; |
@@ -417,6 +421,8 @@ static const DECLARE_TLV_DB_SCALE(mic_vol_tlv, 0, 1000, 0); | |||
417 | static const struct snd_kcontrol_new rt286_snd_controls[] = { | 421 | static const struct snd_kcontrol_new rt286_snd_controls[] = { |
418 | SOC_DOUBLE_R_TLV("DAC0 Playback Volume", RT286_DACL_GAIN, | 422 | SOC_DOUBLE_R_TLV("DAC0 Playback Volume", RT286_DACL_GAIN, |
419 | RT286_DACR_GAIN, 0, 0x7f, 0, out_vol_tlv), | 423 | RT286_DACR_GAIN, 0, 0x7f, 0, out_vol_tlv), |
424 | SOC_DOUBLE_R("ADC0 Capture Switch", RT286_ADCL_GAIN, | ||
425 | RT286_ADCR_GAIN, 7, 1, 1), | ||
420 | SOC_DOUBLE_R_TLV("ADC0 Capture Volume", RT286_ADCL_GAIN, | 426 | SOC_DOUBLE_R_TLV("ADC0 Capture Volume", RT286_ADCL_GAIN, |
421 | RT286_ADCR_GAIN, 0, 0x7f, 0, out_vol_tlv), | 427 | RT286_ADCR_GAIN, 0, 0x7f, 0, out_vol_tlv), |
422 | SOC_SINGLE_TLV("AMIC Volume", RT286_MIC_GAIN, | 428 | SOC_SINGLE_TLV("AMIC Volume", RT286_MIC_GAIN, |
@@ -500,7 +506,7 @@ SOC_DAPM_ENUM("SPO source", rt286_spo_enum); | |||
500 | static int rt286_spk_event(struct snd_soc_dapm_widget *w, | 506 | static int rt286_spk_event(struct snd_soc_dapm_widget *w, |
501 | struct snd_kcontrol *kcontrol, int event) | 507 | struct snd_kcontrol *kcontrol, int event) |
502 | { | 508 | { |
503 | struct snd_soc_codec *codec = w->codec; | 509 | struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); |
504 | 510 | ||
505 | switch (event) { | 511 | switch (event) { |
506 | case SND_SOC_DAPM_POST_PMU: | 512 | case SND_SOC_DAPM_POST_PMU: |
@@ -522,7 +528,7 @@ static int rt286_spk_event(struct snd_soc_dapm_widget *w, | |||
522 | static int rt286_set_dmic1_event(struct snd_soc_dapm_widget *w, | 528 | static int rt286_set_dmic1_event(struct snd_soc_dapm_widget *w, |
523 | struct snd_kcontrol *kcontrol, int event) | 529 | struct snd_kcontrol *kcontrol, int event) |
524 | { | 530 | { |
525 | struct snd_soc_codec *codec = w->codec; | 531 | struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); |
526 | 532 | ||
527 | switch (event) { | 533 | switch (event) { |
528 | case SND_SOC_DAPM_POST_PMU: | 534 | case SND_SOC_DAPM_POST_PMU: |
@@ -538,36 +544,10 @@ static int rt286_set_dmic1_event(struct snd_soc_dapm_widget *w, | |||
538 | return 0; | 544 | return 0; |
539 | } | 545 | } |
540 | 546 | ||
541 | static int rt286_adc_event(struct snd_soc_dapm_widget *w, | ||
542 | struct snd_kcontrol *kcontrol, int event) | ||
543 | { | ||
544 | struct snd_soc_codec *codec = w->codec; | ||
545 | unsigned int nid; | ||
546 | |||
547 | nid = (w->reg >> 20) & 0xff; | ||
548 | |||
549 | switch (event) { | ||
550 | case SND_SOC_DAPM_POST_PMU: | ||
551 | snd_soc_update_bits(codec, | ||
552 | VERB_CMD(AC_VERB_SET_AMP_GAIN_MUTE, nid, 0), | ||
553 | 0x7080, 0x7000); | ||
554 | break; | ||
555 | case SND_SOC_DAPM_PRE_PMD: | ||
556 | snd_soc_update_bits(codec, | ||
557 | VERB_CMD(AC_VERB_SET_AMP_GAIN_MUTE, nid, 0), | ||
558 | 0x7080, 0x7080); | ||
559 | break; | ||
560 | default: | ||
561 | return 0; | ||
562 | } | ||
563 | |||
564 | return 0; | ||
565 | } | ||
566 | |||
567 | static int rt286_vref_event(struct snd_soc_dapm_widget *w, | 547 | static int rt286_vref_event(struct snd_soc_dapm_widget *w, |
568 | struct snd_kcontrol *kcontrol, int event) | 548 | struct snd_kcontrol *kcontrol, int event) |
569 | { | 549 | { |
570 | struct snd_soc_codec *codec = w->codec; | 550 | struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); |
571 | 551 | ||
572 | switch (event) { | 552 | switch (event) { |
573 | case SND_SOC_DAPM_PRE_PMU: | 553 | case SND_SOC_DAPM_PRE_PMU: |
@@ -585,7 +565,7 @@ static int rt286_vref_event(struct snd_soc_dapm_widget *w, | |||
585 | static int rt286_ldo2_event(struct snd_soc_dapm_widget *w, | 565 | static int rt286_ldo2_event(struct snd_soc_dapm_widget *w, |
586 | struct snd_kcontrol *kcontrol, int event) | 566 | struct snd_kcontrol *kcontrol, int event) |
587 | { | 567 | { |
588 | struct snd_soc_codec *codec = w->codec; | 568 | struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); |
589 | 569 | ||
590 | switch (event) { | 570 | switch (event) { |
591 | case SND_SOC_DAPM_POST_PMU: | 571 | case SND_SOC_DAPM_POST_PMU: |
@@ -604,7 +584,7 @@ static int rt286_ldo2_event(struct snd_soc_dapm_widget *w, | |||
604 | static int rt286_mic1_event(struct snd_soc_dapm_widget *w, | 584 | static int rt286_mic1_event(struct snd_soc_dapm_widget *w, |
605 | struct snd_kcontrol *kcontrol, int event) | 585 | struct snd_kcontrol *kcontrol, int event) |
606 | { | 586 | { |
607 | struct snd_soc_codec *codec = w->codec; | 587 | struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); |
608 | 588 | ||
609 | switch (event) { | 589 | switch (event) { |
610 | case SND_SOC_DAPM_PRE_PMU: | 590 | case SND_SOC_DAPM_PRE_PMU: |
@@ -667,12 +647,10 @@ static const struct snd_soc_dapm_widget rt286_dapm_widgets[] = { | |||
667 | SND_SOC_DAPM_ADC("ADC 1", NULL, SND_SOC_NOPM, 0, 0), | 647 | SND_SOC_DAPM_ADC("ADC 1", NULL, SND_SOC_NOPM, 0, 0), |
668 | 648 | ||
669 | /* ADC Mux */ | 649 | /* ADC Mux */ |
670 | SND_SOC_DAPM_MUX_E("ADC 0 Mux", RT286_SET_POWER(RT286_ADC_IN1), 0, 1, | 650 | SND_SOC_DAPM_MUX("ADC 0 Mux", RT286_SET_POWER(RT286_ADC_IN1), 0, 1, |
671 | &rt286_adc0_mux, rt286_adc_event, SND_SOC_DAPM_PRE_PMD | | 651 | &rt286_adc0_mux), |
672 | SND_SOC_DAPM_POST_PMU), | 652 | SND_SOC_DAPM_MUX("ADC 1 Mux", RT286_SET_POWER(RT286_ADC_IN2), 0, 1, |
673 | SND_SOC_DAPM_MUX_E("ADC 1 Mux", RT286_SET_POWER(RT286_ADC_IN2), 0, 1, | 653 | &rt286_adc1_mux), |
674 | &rt286_adc1_mux, rt286_adc_event, SND_SOC_DAPM_PRE_PMD | | ||
675 | SND_SOC_DAPM_POST_PMU), | ||
676 | 654 | ||
677 | /* Audio Interface */ | 655 | /* Audio Interface */ |
678 | SND_SOC_DAPM_AIF_IN("AIF1RX", "AIF1 Playback", 0, SND_SOC_NOPM, 0, 0), | 656 | SND_SOC_DAPM_AIF_IN("AIF1RX", "AIF1 Playback", 0, SND_SOC_NOPM, 0, 0), |
@@ -1194,6 +1172,7 @@ static const struct regmap_config rt286_regmap = { | |||
1194 | 1172 | ||
1195 | static const struct i2c_device_id rt286_i2c_id[] = { | 1173 | static const struct i2c_device_id rt286_i2c_id[] = { |
1196 | {"rt286", 0}, | 1174 | {"rt286", 0}, |
1175 | {"rt288", 0}, | ||
1197 | {} | 1176 | {} |
1198 | }; | 1177 | }; |
1199 | MODULE_DEVICE_TABLE(i2c, rt286_i2c_id); | 1178 | MODULE_DEVICE_TABLE(i2c, rt286_i2c_id); |
@@ -1214,6 +1193,17 @@ static struct dmi_system_id force_combo_jack_table[] = { | |||
1214 | { } | 1193 | { } |
1215 | }; | 1194 | }; |
1216 | 1195 | ||
1196 | static struct dmi_system_id dmi_dell_dino[] = { | ||
1197 | { | ||
1198 | .ident = "Dell Dino", | ||
1199 | .matches = { | ||
1200 | DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), | ||
1201 | DMI_MATCH(DMI_BOARD_NAME, "0144P8") | ||
1202 | } | ||
1203 | }, | ||
1204 | { } | ||
1205 | }; | ||
1206 | |||
1217 | static int rt286_i2c_probe(struct i2c_client *i2c, | 1207 | static int rt286_i2c_probe(struct i2c_client *i2c, |
1218 | const struct i2c_device_id *id) | 1208 | const struct i2c_device_id *id) |
1219 | { | 1209 | { |
@@ -1236,7 +1226,7 @@ static int rt286_i2c_probe(struct i2c_client *i2c, | |||
1236 | 1226 | ||
1237 | regmap_read(rt286->regmap, | 1227 | regmap_read(rt286->regmap, |
1238 | RT286_GET_PARAM(AC_NODE_ROOT, AC_PAR_VENDOR_ID), &ret); | 1228 | RT286_GET_PARAM(AC_NODE_ROOT, AC_PAR_VENDOR_ID), &ret); |
1239 | if (ret != RT286_VENDOR_ID) { | 1229 | if (ret != RT286_VENDOR_ID && ret != RT288_VENDOR_ID) { |
1240 | dev_err(&i2c->dev, | 1230 | dev_err(&i2c->dev, |
1241 | "Device with ID register %x is not rt286\n", ret); | 1231 | "Device with ID register %x is not rt286\n", ret); |
1242 | return -ENODEV; | 1232 | return -ENODEV; |
@@ -1249,7 +1239,8 @@ static int rt286_i2c_probe(struct i2c_client *i2c, | |||
1249 | if (pdata) | 1239 | if (pdata) |
1250 | rt286->pdata = *pdata; | 1240 | rt286->pdata = *pdata; |
1251 | 1241 | ||
1252 | if (dmi_check_system(force_combo_jack_table)) | 1242 | if (dmi_check_system(force_combo_jack_table) || |
1243 | dmi_check_system(dmi_dell_dino)) | ||
1253 | rt286->pdata.cbj_en = true; | 1244 | rt286->pdata.cbj_en = true; |
1254 | 1245 | ||
1255 | regmap_write(rt286->regmap, RT286_SET_AUDIO_POWER, AC_PWRST_D3); | 1246 | regmap_write(rt286->regmap, RT286_SET_AUDIO_POWER, AC_PWRST_D3); |
@@ -1288,6 +1279,17 @@ static int rt286_i2c_probe(struct i2c_client *i2c, | |||
1288 | regmap_update_bits(rt286->regmap, RT286_DEPOP_CTRL3, 0xf777, 0x4737); | 1279 | regmap_update_bits(rt286->regmap, RT286_DEPOP_CTRL3, 0xf777, 0x4737); |
1289 | regmap_update_bits(rt286->regmap, RT286_DEPOP_CTRL4, 0x00ff, 0x003f); | 1280 | regmap_update_bits(rt286->regmap, RT286_DEPOP_CTRL4, 0x00ff, 0x003f); |
1290 | 1281 | ||
1282 | if (dmi_check_system(dmi_dell_dino)) { | ||
1283 | regmap_update_bits(rt286->regmap, | ||
1284 | RT286_SET_GPIO_MASK, 0x40, 0x40); | ||
1285 | regmap_update_bits(rt286->regmap, | ||
1286 | RT286_SET_GPIO_DIRECTION, 0x40, 0x40); | ||
1287 | regmap_update_bits(rt286->regmap, | ||
1288 | RT286_SET_GPIO_DATA, 0x40, 0x40); | ||
1289 | regmap_update_bits(rt286->regmap, | ||
1290 | RT286_GPIO_CTRL, 0xc, 0x8); | ||
1291 | } | ||
1292 | |||
1291 | if (rt286->i2c->irq) { | 1293 | if (rt286->i2c->irq) { |
1292 | ret = request_threaded_irq(rt286->i2c->irq, NULL, rt286_irq, | 1294 | ret = request_threaded_irq(rt286->i2c->irq, NULL, rt286_irq, |
1293 | IRQF_TRIGGER_HIGH | IRQF_ONESHOT, "rt286", rt286); | 1295 | IRQF_TRIGGER_HIGH | IRQF_ONESHOT, "rt286", rt286); |