diff options
-rw-r--r-- | include/sound/rt5670.h | 1 | ||||
-rw-r--r-- | sound/soc/codecs/rt5670.c | 213 | ||||
-rw-r--r-- | sound/soc/codecs/rt5670.h | 10 |
3 files changed, 207 insertions, 17 deletions
diff --git a/include/sound/rt5670.h b/include/sound/rt5670.h index bd311197a3b5..b7d60510819b 100644 --- a/include/sound/rt5670.h +++ b/include/sound/rt5670.h | |||
@@ -14,6 +14,7 @@ | |||
14 | struct rt5670_platform_data { | 14 | struct rt5670_platform_data { |
15 | int jd_mode; | 15 | int jd_mode; |
16 | bool in2_diff; | 16 | bool in2_diff; |
17 | bool dev_gpio; | ||
17 | 18 | ||
18 | bool dmic_en; | 19 | bool dmic_en; |
19 | unsigned int dmic1_data_pin; | 20 | unsigned int dmic1_data_pin; |
diff --git a/sound/soc/codecs/rt5670.c b/sound/soc/codecs/rt5670.c index fd102613d20d..cc7f84a150a7 100644 --- a/sound/soc/codecs/rt5670.c +++ b/sound/soc/codecs/rt5670.c | |||
@@ -403,6 +403,189 @@ static bool rt5670_readable_register(struct device *dev, unsigned int reg) | |||
403 | } | 403 | } |
404 | } | 404 | } |
405 | 405 | ||
406 | /** | ||
407 | * rt5670_headset_detect - Detect headset. | ||
408 | * @codec: SoC audio codec device. | ||
409 | * @jack_insert: Jack insert or not. | ||
410 | * | ||
411 | * Detect whether is headset or not when jack inserted. | ||
412 | * | ||
413 | * Returns detect status. | ||
414 | */ | ||
415 | |||
416 | static int rt5670_headset_detect(struct snd_soc_codec *codec, int jack_insert) | ||
417 | { | ||
418 | int val; | ||
419 | struct rt5670_priv *rt5670 = snd_soc_codec_get_drvdata(codec); | ||
420 | |||
421 | if (jack_insert) { | ||
422 | snd_soc_dapm_force_enable_pin(&codec->dapm, | ||
423 | "Mic Det Power"); | ||
424 | snd_soc_dapm_sync(&codec->dapm); | ||
425 | snd_soc_update_bits(codec, RT5670_GEN_CTRL3, 0x4, 0x0); | ||
426 | snd_soc_update_bits(codec, RT5670_CJ_CTRL2, | ||
427 | RT5670_CBJ_DET_MODE | RT5670_CBJ_MN_JD, | ||
428 | RT5670_CBJ_MN_JD); | ||
429 | snd_soc_write(codec, RT5670_GPIO_CTRL2, 0x0004); | ||
430 | snd_soc_update_bits(codec, RT5670_GPIO_CTRL1, | ||
431 | RT5670_GP1_PIN_MASK, RT5670_GP1_PIN_IRQ); | ||
432 | snd_soc_update_bits(codec, RT5670_CJ_CTRL1, | ||
433 | RT5670_CBJ_BST1_EN, RT5670_CBJ_BST1_EN); | ||
434 | snd_soc_write(codec, RT5670_JD_CTRL3, 0x00f0); | ||
435 | snd_soc_update_bits(codec, RT5670_CJ_CTRL2, | ||
436 | RT5670_CBJ_MN_JD, RT5670_CBJ_MN_JD); | ||
437 | snd_soc_update_bits(codec, RT5670_CJ_CTRL2, | ||
438 | RT5670_CBJ_MN_JD, 0); | ||
439 | msleep(300); | ||
440 | val = snd_soc_read(codec, RT5670_CJ_CTRL3) & 0x7; | ||
441 | if (val == 0x1 || val == 0x2) { | ||
442 | rt5670->jack_type = SND_JACK_HEADSET; | ||
443 | /* for push button */ | ||
444 | snd_soc_update_bits(codec, RT5670_INT_IRQ_ST, 0x8, 0x8); | ||
445 | snd_soc_update_bits(codec, RT5670_IL_CMD, 0x40, 0x40); | ||
446 | snd_soc_read(codec, RT5670_IL_CMD); | ||
447 | } else { | ||
448 | snd_soc_update_bits(codec, RT5670_GEN_CTRL3, 0x4, 0x4); | ||
449 | rt5670->jack_type = SND_JACK_HEADPHONE; | ||
450 | snd_soc_dapm_disable_pin(&codec->dapm, "Mic Det Power"); | ||
451 | snd_soc_dapm_sync(&codec->dapm); | ||
452 | } | ||
453 | } else { | ||
454 | snd_soc_update_bits(codec, RT5670_INT_IRQ_ST, 0x8, 0x0); | ||
455 | snd_soc_update_bits(codec, RT5670_GEN_CTRL3, 0x4, 0x4); | ||
456 | rt5670->jack_type = 0; | ||
457 | snd_soc_dapm_disable_pin(&codec->dapm, "Mic Det Power"); | ||
458 | snd_soc_dapm_sync(&codec->dapm); | ||
459 | } | ||
460 | |||
461 | return rt5670->jack_type; | ||
462 | } | ||
463 | |||
464 | void rt5670_jack_suspend(struct snd_soc_codec *codec) | ||
465 | { | ||
466 | struct rt5670_priv *rt5670 = snd_soc_codec_get_drvdata(codec); | ||
467 | |||
468 | rt5670->jack_type_saved = rt5670->jack_type; | ||
469 | rt5670_headset_detect(codec, 0); | ||
470 | } | ||
471 | EXPORT_SYMBOL_GPL(rt5670_jack_suspend); | ||
472 | |||
473 | void rt5670_jack_resume(struct snd_soc_codec *codec) | ||
474 | { | ||
475 | struct rt5670_priv *rt5670 = snd_soc_codec_get_drvdata(codec); | ||
476 | |||
477 | if (rt5670->jack_type_saved) | ||
478 | rt5670_headset_detect(codec, 1); | ||
479 | } | ||
480 | EXPORT_SYMBOL_GPL(rt5670_jack_resume); | ||
481 | |||
482 | static int rt5670_button_detect(struct snd_soc_codec *codec) | ||
483 | { | ||
484 | int btn_type, val; | ||
485 | |||
486 | val = snd_soc_read(codec, RT5670_IL_CMD); | ||
487 | btn_type = val & 0xff80; | ||
488 | snd_soc_write(codec, RT5670_IL_CMD, val); | ||
489 | if (btn_type != 0) { | ||
490 | msleep(20); | ||
491 | val = snd_soc_read(codec, RT5670_IL_CMD); | ||
492 | snd_soc_write(codec, RT5670_IL_CMD, val); | ||
493 | } | ||
494 | |||
495 | return btn_type; | ||
496 | } | ||
497 | |||
498 | static int rt5670_irq_detection(void *data) | ||
499 | { | ||
500 | struct rt5670_priv *rt5670 = (struct rt5670_priv *)data; | ||
501 | struct snd_soc_jack_gpio *gpio = &rt5670->hp_gpio; | ||
502 | struct snd_soc_jack *jack = rt5670->jack; | ||
503 | int val, btn_type, report = jack->status; | ||
504 | |||
505 | if (rt5670->pdata.jd_mode == 1) /* 2 port */ | ||
506 | val = snd_soc_read(rt5670->codec, RT5670_A_JD_CTRL1) & 0x0070; | ||
507 | else | ||
508 | val = snd_soc_read(rt5670->codec, RT5670_A_JD_CTRL1) & 0x0020; | ||
509 | |||
510 | switch (val) { | ||
511 | /* jack in */ | ||
512 | case 0x30: /* 2 port */ | ||
513 | case 0x0: /* 1 port or 2 port */ | ||
514 | if (rt5670->jack_type == 0) { | ||
515 | report = rt5670_headset_detect(rt5670->codec, 1); | ||
516 | /* for push button and jack out */ | ||
517 | gpio->debounce_time = 25; | ||
518 | break; | ||
519 | } | ||
520 | btn_type = 0; | ||
521 | if (snd_soc_read(rt5670->codec, RT5670_INT_IRQ_ST) & 0x4) { | ||
522 | /* button pressed */ | ||
523 | report = SND_JACK_HEADSET; | ||
524 | btn_type = rt5670_button_detect(rt5670->codec); | ||
525 | switch (btn_type) { | ||
526 | case 0x2000: /* up */ | ||
527 | report |= SND_JACK_BTN_1; | ||
528 | break; | ||
529 | case 0x0400: /* center */ | ||
530 | report |= SND_JACK_BTN_0; | ||
531 | break; | ||
532 | case 0x0080: /* down */ | ||
533 | report |= SND_JACK_BTN_2; | ||
534 | break; | ||
535 | default: | ||
536 | dev_err(rt5670->codec->dev, | ||
537 | "Unexpected button code 0x%04x\n", | ||
538 | btn_type); | ||
539 | break; | ||
540 | } | ||
541 | } | ||
542 | if (btn_type == 0)/* button release */ | ||
543 | report = rt5670->jack_type; | ||
544 | |||
545 | break; | ||
546 | /* jack out */ | ||
547 | case 0x70: /* 2 port */ | ||
548 | case 0x10: /* 2 port */ | ||
549 | case 0x20: /* 1 port */ | ||
550 | report = 0; | ||
551 | snd_soc_update_bits(rt5670->codec, RT5670_INT_IRQ_ST, 0x1, 0x0); | ||
552 | rt5670_headset_detect(rt5670->codec, 0); | ||
553 | gpio->debounce_time = 150; /* for jack in */ | ||
554 | break; | ||
555 | default: | ||
556 | break; | ||
557 | } | ||
558 | |||
559 | return report; | ||
560 | } | ||
561 | |||
562 | int rt5670_set_jack_detect(struct snd_soc_codec *codec, | ||
563 | struct snd_soc_jack *jack) | ||
564 | { | ||
565 | struct rt5670_priv *rt5670 = snd_soc_codec_get_drvdata(codec); | ||
566 | int ret; | ||
567 | |||
568 | rt5670->jack = jack; | ||
569 | rt5670->hp_gpio.gpiod_dev = codec->dev; | ||
570 | rt5670->hp_gpio.name = "headphone detect"; | ||
571 | rt5670->hp_gpio.report = SND_JACK_HEADSET | | ||
572 | SND_JACK_BTN_0 | SND_JACK_BTN_1 | SND_JACK_BTN_2; | ||
573 | rt5670->hp_gpio.debounce_time = 150; | ||
574 | rt5670->hp_gpio.wake = true; | ||
575 | rt5670->hp_gpio.data = (struct rt5670_priv *)rt5670; | ||
576 | rt5670->hp_gpio.jack_status_check = rt5670_irq_detection; | ||
577 | |||
578 | ret = snd_soc_jack_add_gpios(rt5670->jack, 1, | ||
579 | &rt5670->hp_gpio); | ||
580 | if (ret) { | ||
581 | dev_err(codec->dev, "Adding jack GPIO failed\n"); | ||
582 | return ret; | ||
583 | } | ||
584 | |||
585 | return 0; | ||
586 | } | ||
587 | EXPORT_SYMBOL_GPL(rt5670_set_jack_detect); | ||
588 | |||
406 | static const DECLARE_TLV_DB_SCALE(out_vol_tlv, -4650, 150, 0); | 589 | static const DECLARE_TLV_DB_SCALE(out_vol_tlv, -4650, 150, 0); |
407 | static const DECLARE_TLV_DB_SCALE(dac_vol_tlv, -65625, 375, 0); | 590 | static const DECLARE_TLV_DB_SCALE(dac_vol_tlv, -65625, 375, 0); |
408 | static const DECLARE_TLV_DB_SCALE(in_vol_tlv, -3450, 150, 0); | 591 | static const DECLARE_TLV_DB_SCALE(in_vol_tlv, -3450, 150, 0); |
@@ -517,11 +700,9 @@ static int is_sys_clk_from_pll(struct snd_soc_dapm_widget *source, | |||
517 | struct snd_soc_dapm_widget *sink) | 700 | struct snd_soc_dapm_widget *sink) |
518 | { | 701 | { |
519 | struct snd_soc_codec *codec = snd_soc_dapm_to_codec(source->dapm); | 702 | struct snd_soc_codec *codec = snd_soc_dapm_to_codec(source->dapm); |
520 | unsigned int val; | 703 | struct rt5670_priv *rt5670 = snd_soc_codec_get_drvdata(codec); |
521 | 704 | ||
522 | val = snd_soc_read(codec, RT5670_GLB_CLK); | 705 | if (rt5670->sysclk_src == RT5670_SCLK_S_PLL1) |
523 | val &= RT5670_SCLK_SRC_MASK; | ||
524 | if (val == RT5670_SCLK_SRC_PLL1) | ||
525 | return 1; | 706 | return 1; |
526 | else | 707 | else |
527 | return 0; | 708 | return 0; |
@@ -2271,16 +2452,6 @@ static int rt5670_set_dai_sysclk(struct snd_soc_dai *dai, | |||
2271 | struct rt5670_priv *rt5670 = snd_soc_codec_get_drvdata(codec); | 2452 | struct rt5670_priv *rt5670 = snd_soc_codec_get_drvdata(codec); |
2272 | unsigned int reg_val = 0; | 2453 | unsigned int reg_val = 0; |
2273 | 2454 | ||
2274 | if (freq == rt5670->sysclk && clk_id == rt5670->sysclk_src) | ||
2275 | return 0; | ||
2276 | |||
2277 | if (rt5670->pdata.jd_mode) { | ||
2278 | if (clk_id == RT5670_SCLK_S_PLL1) | ||
2279 | snd_soc_dapm_force_enable_pin(&codec->dapm, "PLL1"); | ||
2280 | else | ||
2281 | snd_soc_dapm_disable_pin(&codec->dapm, "PLL1"); | ||
2282 | snd_soc_dapm_sync(&codec->dapm); | ||
2283 | } | ||
2284 | switch (clk_id) { | 2455 | switch (clk_id) { |
2285 | case RT5670_SCLK_S_MCLK: | 2456 | case RT5670_SCLK_S_MCLK: |
2286 | reg_val |= RT5670_SCLK_SRC_MCLK; | 2457 | reg_val |= RT5670_SCLK_SRC_MCLK; |
@@ -2298,7 +2469,8 @@ static int rt5670_set_dai_sysclk(struct snd_soc_dai *dai, | |||
2298 | snd_soc_update_bits(codec, RT5670_GLB_CLK, | 2469 | snd_soc_update_bits(codec, RT5670_GLB_CLK, |
2299 | RT5670_SCLK_SRC_MASK, reg_val); | 2470 | RT5670_SCLK_SRC_MASK, reg_val); |
2300 | rt5670->sysclk = freq; | 2471 | rt5670->sysclk = freq; |
2301 | rt5670->sysclk_src = clk_id; | 2472 | if (clk_id != RT5670_SCLK_S_RCCLK) |
2473 | rt5670->sysclk_src = clk_id; | ||
2302 | 2474 | ||
2303 | dev_dbg(dai->dev, "Sysclk is %dHz and clock id is %d\n", freq, clk_id); | 2475 | dev_dbg(dai->dev, "Sysclk is %dHz and clock id is %d\n", freq, clk_id); |
2304 | 2476 | ||
@@ -2517,6 +2689,7 @@ static int rt5670_remove(struct snd_soc_codec *codec) | |||
2517 | struct rt5670_priv *rt5670 = snd_soc_codec_get_drvdata(codec); | 2689 | struct rt5670_priv *rt5670 = snd_soc_codec_get_drvdata(codec); |
2518 | 2690 | ||
2519 | regmap_write(rt5670->regmap, RT5670_RESET, 0); | 2691 | regmap_write(rt5670->regmap, RT5670_RESET, 0); |
2692 | snd_soc_jack_free_gpios(rt5670->jack, 1, &rt5670->hp_gpio); | ||
2520 | return 0; | 2693 | return 0; |
2521 | } | 2694 | } |
2522 | 2695 | ||
@@ -2676,6 +2849,7 @@ static int rt5670_i2c_probe(struct i2c_client *i2c, | |||
2676 | if (dmi_check_system(dmi_platform_intel_braswell)) { | 2849 | if (dmi_check_system(dmi_platform_intel_braswell)) { |
2677 | rt5670->pdata.dmic_en = true; | 2850 | rt5670->pdata.dmic_en = true; |
2678 | rt5670->pdata.dmic1_data_pin = RT5670_DMIC_DATA_IN2P; | 2851 | rt5670->pdata.dmic1_data_pin = RT5670_DMIC_DATA_IN2P; |
2852 | rt5670->pdata.dev_gpio = true; | ||
2679 | rt5670->pdata.jd_mode = 1; | 2853 | rt5670->pdata.jd_mode = 1; |
2680 | } | 2854 | } |
2681 | 2855 | ||
@@ -2717,12 +2891,17 @@ static int rt5670_i2c_probe(struct i2c_client *i2c, | |||
2717 | regmap_update_bits(rt5670->regmap, RT5670_IN2, | 2891 | regmap_update_bits(rt5670->regmap, RT5670_IN2, |
2718 | RT5670_IN_DF2, RT5670_IN_DF2); | 2892 | RT5670_IN_DF2, RT5670_IN_DF2); |
2719 | 2893 | ||
2720 | if (i2c->irq) { | 2894 | if (rt5670->pdata.dev_gpio) { |
2895 | /* for push button */ | ||
2896 | regmap_write(rt5670->regmap, RT5670_IL_CMD, 0x0000); | ||
2897 | regmap_write(rt5670->regmap, RT5670_IL_CMD2, 0x0010); | ||
2898 | regmap_write(rt5670->regmap, RT5670_IL_CMD3, 0x0014); | ||
2899 | /* for irq */ | ||
2721 | regmap_update_bits(rt5670->regmap, RT5670_GPIO_CTRL1, | 2900 | regmap_update_bits(rt5670->regmap, RT5670_GPIO_CTRL1, |
2722 | RT5670_GP1_PIN_MASK, RT5670_GP1_PIN_IRQ); | 2901 | RT5670_GP1_PIN_MASK, RT5670_GP1_PIN_IRQ); |
2723 | regmap_update_bits(rt5670->regmap, RT5670_GPIO_CTRL2, | 2902 | regmap_update_bits(rt5670->regmap, RT5670_GPIO_CTRL2, |
2724 | RT5670_GP1_PF_MASK, RT5670_GP1_PF_OUT); | 2903 | RT5670_GP1_PF_MASK, RT5670_GP1_PF_OUT); |
2725 | 2904 | regmap_update_bits(rt5670->regmap, RT5670_DIG_MISC, 0x8, 0x8); | |
2726 | } | 2905 | } |
2727 | 2906 | ||
2728 | if (rt5670->pdata.jd_mode) { | 2907 | if (rt5670->pdata.jd_mode) { |
diff --git a/sound/soc/codecs/rt5670.h b/sound/soc/codecs/rt5670.h index 21f8e18c13c4..dc2b46236c5c 100644 --- a/sound/soc/codecs/rt5670.h +++ b/sound/soc/codecs/rt5670.h | |||
@@ -1950,17 +1950,20 @@ enum { | |||
1950 | }; | 1950 | }; |
1951 | 1951 | ||
1952 | enum { | 1952 | enum { |
1953 | RT5670_DMIC1_DISABLED, | ||
1953 | RT5670_DMIC_DATA_GPIO6, | 1954 | RT5670_DMIC_DATA_GPIO6, |
1954 | RT5670_DMIC_DATA_IN2P, | 1955 | RT5670_DMIC_DATA_IN2P, |
1955 | RT5670_DMIC_DATA_GPIO7, | 1956 | RT5670_DMIC_DATA_GPIO7, |
1956 | }; | 1957 | }; |
1957 | 1958 | ||
1958 | enum { | 1959 | enum { |
1960 | RT5670_DMIC2_DISABLED, | ||
1959 | RT5670_DMIC_DATA_GPIO8, | 1961 | RT5670_DMIC_DATA_GPIO8, |
1960 | RT5670_DMIC_DATA_IN3N, | 1962 | RT5670_DMIC_DATA_IN3N, |
1961 | }; | 1963 | }; |
1962 | 1964 | ||
1963 | enum { | 1965 | enum { |
1966 | RT5670_DMIC3_DISABLED, | ||
1964 | RT5670_DMIC_DATA_GPIO9, | 1967 | RT5670_DMIC_DATA_GPIO9, |
1965 | RT5670_DMIC_DATA_GPIO10, | 1968 | RT5670_DMIC_DATA_GPIO10, |
1966 | RT5670_DMIC_DATA_GPIO5, | 1969 | RT5670_DMIC_DATA_GPIO5, |
@@ -1985,6 +1988,8 @@ struct rt5670_priv { | |||
1985 | struct snd_soc_codec *codec; | 1988 | struct snd_soc_codec *codec; |
1986 | struct rt5670_platform_data pdata; | 1989 | struct rt5670_platform_data pdata; |
1987 | struct regmap *regmap; | 1990 | struct regmap *regmap; |
1991 | struct snd_soc_jack *jack; | ||
1992 | struct snd_soc_jack_gpio hp_gpio; | ||
1988 | 1993 | ||
1989 | int sysclk; | 1994 | int sysclk; |
1990 | int sysclk_src; | 1995 | int sysclk_src; |
@@ -1999,6 +2004,11 @@ struct rt5670_priv { | |||
1999 | int dsp_sw; /* expected parameter setting */ | 2004 | int dsp_sw; /* expected parameter setting */ |
2000 | int dsp_rate; | 2005 | int dsp_rate; |
2001 | int jack_type; | 2006 | int jack_type; |
2007 | int jack_type_saved; | ||
2002 | }; | 2008 | }; |
2003 | 2009 | ||
2010 | void rt5670_jack_suspend(struct snd_soc_codec *codec); | ||
2011 | void rt5670_jack_resume(struct snd_soc_codec *codec); | ||
2012 | int rt5670_set_jack_detect(struct snd_soc_codec *codec, | ||
2013 | struct snd_soc_jack *jack); | ||
2004 | #endif /* __RT5670_H__ */ | 2014 | #endif /* __RT5670_H__ */ |