aboutsummaryrefslogtreecommitdiffstats
path: root/sound/soc/codecs/rt5670.c
diff options
context:
space:
mode:
Diffstat (limited to 'sound/soc/codecs/rt5670.c')
-rw-r--r--sound/soc/codecs/rt5670.c138
1 files changed, 131 insertions, 7 deletions
diff --git a/sound/soc/codecs/rt5670.c b/sound/soc/codecs/rt5670.c
index 8a0833de1665..e1a4a45c57e2 100644
--- a/sound/soc/codecs/rt5670.c
+++ b/sound/soc/codecs/rt5670.c
@@ -14,10 +14,12 @@
14#include <linux/init.h> 14#include <linux/init.h>
15#include <linux/delay.h> 15#include <linux/delay.h>
16#include <linux/pm.h> 16#include <linux/pm.h>
17#include <linux/pm_runtime.h>
17#include <linux/i2c.h> 18#include <linux/i2c.h>
18#include <linux/platform_device.h> 19#include <linux/platform_device.h>
19#include <linux/acpi.h> 20#include <linux/acpi.h>
20#include <linux/spi/spi.h> 21#include <linux/spi/spi.h>
22#include <linux/dmi.h>
21#include <sound/core.h> 23#include <sound/core.h>
22#include <sound/pcm.h> 24#include <sound/pcm.h>
23#include <sound/pcm_params.h> 25#include <sound/pcm_params.h>
@@ -498,7 +500,7 @@ static const struct snd_kcontrol_new rt5670_snd_controls[] = {
498static int set_dmic_clk(struct snd_soc_dapm_widget *w, 500static int set_dmic_clk(struct snd_soc_dapm_widget *w,
499 struct snd_kcontrol *kcontrol, int event) 501 struct snd_kcontrol *kcontrol, int event)
500{ 502{
501 struct snd_soc_codec *codec = w->codec; 503 struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
502 struct rt5670_priv *rt5670 = snd_soc_codec_get_drvdata(codec); 504 struct rt5670_priv *rt5670 = snd_soc_codec_get_drvdata(codec);
503 int idx = -EINVAL; 505 int idx = -EINVAL;
504 506
@@ -515,9 +517,10 @@ static int set_dmic_clk(struct snd_soc_dapm_widget *w,
515static int is_sys_clk_from_pll(struct snd_soc_dapm_widget *source, 517static int is_sys_clk_from_pll(struct snd_soc_dapm_widget *source,
516 struct snd_soc_dapm_widget *sink) 518 struct snd_soc_dapm_widget *sink)
517{ 519{
520 struct snd_soc_codec *codec = snd_soc_dapm_to_codec(source->dapm);
518 unsigned int val; 521 unsigned int val;
519 522
520 val = snd_soc_read(source->codec, RT5670_GLB_CLK); 523 val = snd_soc_read(codec, RT5670_GLB_CLK);
521 val &= RT5670_SCLK_SRC_MASK; 524 val &= RT5670_SCLK_SRC_MASK;
522 if (val == RT5670_SCLK_SRC_PLL1) 525 if (val == RT5670_SCLK_SRC_PLL1)
523 return 1; 526 return 1;
@@ -528,6 +531,7 @@ static int is_sys_clk_from_pll(struct snd_soc_dapm_widget *source,
528static int is_using_asrc(struct snd_soc_dapm_widget *source, 531static int is_using_asrc(struct snd_soc_dapm_widget *source,
529 struct snd_soc_dapm_widget *sink) 532 struct snd_soc_dapm_widget *sink)
530{ 533{
534 struct snd_soc_codec *codec = snd_soc_dapm_to_codec(source->dapm);
531 unsigned int reg, shift, val; 535 unsigned int reg, shift, val;
532 536
533 switch (source->shift) { 537 switch (source->shift) {
@@ -563,7 +567,7 @@ static int is_using_asrc(struct snd_soc_dapm_widget *source,
563 return 0; 567 return 0;
564 } 568 }
565 569
566 val = (snd_soc_read(source->codec, reg) >> shift) & 0xf; 570 val = (snd_soc_read(codec, reg) >> shift) & 0xf;
567 switch (val) { 571 switch (val) {
568 case 1: 572 case 1:
569 case 2: 573 case 2:
@@ -588,6 +592,89 @@ static int can_use_asrc(struct snd_soc_dapm_widget *source,
588 return 0; 592 return 0;
589} 593}
590 594
595
596/**
597 * rt5670_sel_asrc_clk_src - select ASRC clock source for a set of filters
598 * @codec: SoC audio codec device.
599 * @filter_mask: mask of filters.
600 * @clk_src: clock source
601 *
602 * The ASRC function is for asynchronous MCLK and LRCK. Also, since RT5670 can
603 * only support standard 32fs or 64fs i2s format, ASRC should be enabled to
604 * support special i2s clock format such as Intel's 100fs(100 * sampling rate).
605 * ASRC function will track i2s clock and generate a corresponding system clock
606 * for codec. This function provides an API to select the clock source for a
607 * set of filters specified by the mask. And the codec driver will turn on ASRC
608 * for these filters if ASRC is selected as their clock source.
609 */
610int rt5670_sel_asrc_clk_src(struct snd_soc_codec *codec,
611 unsigned int filter_mask, unsigned int clk_src)
612{
613 unsigned int asrc2_mask = 0, asrc2_value = 0;
614 unsigned int asrc3_mask = 0, asrc3_value = 0;
615
616 if (clk_src > RT5670_CLK_SEL_SYS3)
617 return -EINVAL;
618
619 if (filter_mask & RT5670_DA_STEREO_FILTER) {
620 asrc2_mask |= RT5670_DA_STO_CLK_SEL_MASK;
621 asrc2_value = (asrc2_value & ~RT5670_DA_STO_CLK_SEL_MASK)
622 | (clk_src << RT5670_DA_STO_CLK_SEL_SFT);
623 }
624
625 if (filter_mask & RT5670_DA_MONO_L_FILTER) {
626 asrc2_mask |= RT5670_DA_MONOL_CLK_SEL_MASK;
627 asrc2_value = (asrc2_value & ~RT5670_DA_MONOL_CLK_SEL_MASK)
628 | (clk_src << RT5670_DA_MONOL_CLK_SEL_SFT);
629 }
630
631 if (filter_mask & RT5670_DA_MONO_R_FILTER) {
632 asrc2_mask |= RT5670_DA_MONOR_CLK_SEL_MASK;
633 asrc2_value = (asrc2_value & ~RT5670_DA_MONOR_CLK_SEL_MASK)
634 | (clk_src << RT5670_DA_MONOR_CLK_SEL_SFT);
635 }
636
637 if (filter_mask & RT5670_AD_STEREO_FILTER) {
638 asrc2_mask |= RT5670_AD_STO1_CLK_SEL_MASK;
639 asrc2_value = (asrc2_value & ~RT5670_AD_STO1_CLK_SEL_MASK)
640 | (clk_src << RT5670_AD_STO1_CLK_SEL_SFT);
641 }
642
643 if (filter_mask & RT5670_AD_MONO_L_FILTER) {
644 asrc3_mask |= RT5670_AD_MONOL_CLK_SEL_MASK;
645 asrc3_value = (asrc3_value & ~RT5670_AD_MONOL_CLK_SEL_MASK)
646 | (clk_src << RT5670_AD_MONOL_CLK_SEL_SFT);
647 }
648
649 if (filter_mask & RT5670_AD_MONO_R_FILTER) {
650 asrc3_mask |= RT5670_AD_MONOR_CLK_SEL_MASK;
651 asrc3_value = (asrc3_value & ~RT5670_AD_MONOR_CLK_SEL_MASK)
652 | (clk_src << RT5670_AD_MONOR_CLK_SEL_SFT);
653 }
654
655 if (filter_mask & RT5670_UP_RATE_FILTER) {
656 asrc3_mask |= RT5670_UP_CLK_SEL_MASK;
657 asrc3_value = (asrc3_value & ~RT5670_UP_CLK_SEL_MASK)
658 | (clk_src << RT5670_UP_CLK_SEL_SFT);
659 }
660
661 if (filter_mask & RT5670_DOWN_RATE_FILTER) {
662 asrc3_mask |= RT5670_DOWN_CLK_SEL_MASK;
663 asrc3_value = (asrc3_value & ~RT5670_DOWN_CLK_SEL_MASK)
664 | (clk_src << RT5670_DOWN_CLK_SEL_SFT);
665 }
666
667 if (asrc2_mask)
668 snd_soc_update_bits(codec, RT5670_ASRC_2,
669 asrc2_mask, asrc2_value);
670
671 if (asrc3_mask)
672 snd_soc_update_bits(codec, RT5670_ASRC_3,
673 asrc3_mask, asrc3_value);
674 return 0;
675}
676EXPORT_SYMBOL_GPL(rt5670_sel_asrc_clk_src);
677
591/* Digital Mixer */ 678/* Digital Mixer */
592static const struct snd_kcontrol_new rt5670_sto1_adc_l_mix[] = { 679static const struct snd_kcontrol_new rt5670_sto1_adc_l_mix[] = {
593 SOC_DAPM_SINGLE("ADC1 Switch", RT5670_STO1_ADC_MIXER, 680 SOC_DAPM_SINGLE("ADC1 Switch", RT5670_STO1_ADC_MIXER,
@@ -1146,7 +1233,7 @@ static const struct snd_kcontrol_new rt5670_vad_adc_mux =
1146static int rt5670_hp_power_event(struct snd_soc_dapm_widget *w, 1233static int rt5670_hp_power_event(struct snd_soc_dapm_widget *w,
1147 struct snd_kcontrol *kcontrol, int event) 1234 struct snd_kcontrol *kcontrol, int event)
1148{ 1235{
1149 struct snd_soc_codec *codec = w->codec; 1236 struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
1150 struct rt5670_priv *rt5670 = snd_soc_codec_get_drvdata(codec); 1237 struct rt5670_priv *rt5670 = snd_soc_codec_get_drvdata(codec);
1151 1238
1152 switch (event) { 1239 switch (event) {
@@ -1182,7 +1269,7 @@ static int rt5670_hp_power_event(struct snd_soc_dapm_widget *w,
1182static int rt5670_hp_event(struct snd_soc_dapm_widget *w, 1269static int rt5670_hp_event(struct snd_soc_dapm_widget *w,
1183 struct snd_kcontrol *kcontrol, int event) 1270 struct snd_kcontrol *kcontrol, int event)
1184{ 1271{
1185 struct snd_soc_codec *codec = w->codec; 1272 struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
1186 struct rt5670_priv *rt5670 = snd_soc_codec_get_drvdata(codec); 1273 struct rt5670_priv *rt5670 = snd_soc_codec_get_drvdata(codec);
1187 1274
1188 switch (event) { 1275 switch (event) {
@@ -1232,7 +1319,7 @@ static int rt5670_hp_event(struct snd_soc_dapm_widget *w,
1232static int rt5670_bst1_event(struct snd_soc_dapm_widget *w, 1319static int rt5670_bst1_event(struct snd_soc_dapm_widget *w,
1233 struct snd_kcontrol *kcontrol, int event) 1320 struct snd_kcontrol *kcontrol, int event)
1234{ 1321{
1235 struct snd_soc_codec *codec = w->codec; 1322 struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
1236 1323
1237 switch (event) { 1324 switch (event) {
1238 case SND_SOC_DAPM_POST_PMU: 1325 case SND_SOC_DAPM_POST_PMU:
@@ -1255,7 +1342,7 @@ static int rt5670_bst1_event(struct snd_soc_dapm_widget *w,
1255static int rt5670_bst2_event(struct snd_soc_dapm_widget *w, 1342static int rt5670_bst2_event(struct snd_soc_dapm_widget *w,
1256 struct snd_kcontrol *kcontrol, int event) 1343 struct snd_kcontrol *kcontrol, int event)
1257{ 1344{
1258 struct snd_soc_codec *codec = w->codec; 1345 struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
1259 1346
1260 switch (event) { 1347 switch (event) {
1261 case SND_SOC_DAPM_POST_PMU: 1348 case SND_SOC_DAPM_POST_PMU:
@@ -2188,6 +2275,13 @@ static int rt5670_set_dai_sysclk(struct snd_soc_dai *dai,
2188 if (freq == rt5670->sysclk && clk_id == rt5670->sysclk_src) 2275 if (freq == rt5670->sysclk && clk_id == rt5670->sysclk_src)
2189 return 0; 2276 return 0;
2190 2277
2278 if (rt5670->pdata.jd_mode) {
2279 if (clk_id == RT5670_SCLK_S_PLL1)
2280 snd_soc_dapm_force_enable_pin(&codec->dapm, "PLL1");
2281 else
2282 snd_soc_dapm_disable_pin(&codec->dapm, "PLL1");
2283 snd_soc_dapm_sync(&codec->dapm);
2284 }
2191 switch (clk_id) { 2285 switch (clk_id) {
2192 case RT5670_SCLK_S_MCLK: 2286 case RT5670_SCLK_S_MCLK:
2193 reg_val |= RT5670_SCLK_SRC_MCLK; 2287 reg_val |= RT5670_SCLK_SRC_MCLK;
@@ -2522,6 +2616,7 @@ static struct snd_soc_codec_driver soc_codec_dev_rt5670 = {
2522static const struct regmap_config rt5670_regmap = { 2616static const struct regmap_config rt5670_regmap = {
2523 .reg_bits = 8, 2617 .reg_bits = 8,
2524 .val_bits = 16, 2618 .val_bits = 16,
2619 .use_single_rw = true,
2525 .max_register = RT5670_VENDOR_ID2 + 1 + (ARRAY_SIZE(rt5670_ranges) * 2620 .max_register = RT5670_VENDOR_ID2 + 1 + (ARRAY_SIZE(rt5670_ranges) *
2526 RT5670_PR_SPACING), 2621 RT5670_PR_SPACING),
2527 .volatile_reg = rt5670_volatile_register, 2622 .volatile_reg = rt5670_volatile_register,
@@ -2549,6 +2644,17 @@ static struct acpi_device_id rt5670_acpi_match[] = {
2549MODULE_DEVICE_TABLE(acpi, rt5670_acpi_match); 2644MODULE_DEVICE_TABLE(acpi, rt5670_acpi_match);
2550#endif 2645#endif
2551 2646
2647static const struct dmi_system_id dmi_platform_intel_braswell[] = {
2648 {
2649 .ident = "Intel Braswell",
2650 .matches = {
2651 DMI_MATCH(DMI_SYS_VENDOR, "Intel Corporation"),
2652 DMI_MATCH(DMI_BOARD_NAME, "Braswell CRB"),
2653 },
2654 },
2655 {}
2656};
2657
2552static int rt5670_i2c_probe(struct i2c_client *i2c, 2658static int rt5670_i2c_probe(struct i2c_client *i2c,
2553 const struct i2c_device_id *id) 2659 const struct i2c_device_id *id)
2554{ 2660{
@@ -2568,6 +2674,12 @@ static int rt5670_i2c_probe(struct i2c_client *i2c,
2568 if (pdata) 2674 if (pdata)
2569 rt5670->pdata = *pdata; 2675 rt5670->pdata = *pdata;
2570 2676
2677 if (dmi_check_system(dmi_platform_intel_braswell)) {
2678 rt5670->pdata.dmic_en = true;
2679 rt5670->pdata.dmic1_data_pin = RT5670_DMIC_DATA_IN2P;
2680 rt5670->pdata.jd_mode = 1;
2681 }
2682
2571 rt5670->regmap = devm_regmap_init_i2c(i2c, &rt5670_regmap); 2683 rt5670->regmap = devm_regmap_init_i2c(i2c, &rt5670_regmap);
2572 if (IS_ERR(rt5670->regmap)) { 2684 if (IS_ERR(rt5670->regmap)) {
2573 ret = PTR_ERR(rt5670->regmap); 2685 ret = PTR_ERR(rt5670->regmap);
@@ -2609,6 +2721,10 @@ static int rt5670_i2c_probe(struct i2c_client *i2c,
2609 } 2721 }
2610 2722
2611 if (rt5670->pdata.jd_mode) { 2723 if (rt5670->pdata.jd_mode) {
2724 regmap_update_bits(rt5670->regmap, RT5670_GLB_CLK,
2725 RT5670_SCLK_SRC_MASK, RT5670_SCLK_SRC_RCCLK);
2726 rt5670->sysclk = 0;
2727 rt5670->sysclk_src = RT5670_SCLK_S_RCCLK;
2612 regmap_update_bits(rt5670->regmap, RT5670_PWR_ANLG1, 2728 regmap_update_bits(rt5670->regmap, RT5670_PWR_ANLG1,
2613 RT5670_PWR_MB, RT5670_PWR_MB); 2729 RT5670_PWR_MB, RT5670_PWR_MB);
2614 regmap_update_bits(rt5670->regmap, RT5670_PWR_ANLG2, 2730 regmap_update_bits(rt5670->regmap, RT5670_PWR_ANLG2,
@@ -2716,18 +2832,26 @@ static int rt5670_i2c_probe(struct i2c_client *i2c,
2716 2832
2717 } 2833 }
2718 2834
2835 pm_runtime_enable(&i2c->dev);
2836 pm_request_idle(&i2c->dev);
2837
2719 ret = snd_soc_register_codec(&i2c->dev, &soc_codec_dev_rt5670, 2838 ret = snd_soc_register_codec(&i2c->dev, &soc_codec_dev_rt5670,
2720 rt5670_dai, ARRAY_SIZE(rt5670_dai)); 2839 rt5670_dai, ARRAY_SIZE(rt5670_dai));
2721 if (ret < 0) 2840 if (ret < 0)
2722 goto err; 2841 goto err;
2723 2842
2843 pm_runtime_put(&i2c->dev);
2844
2724 return 0; 2845 return 0;
2725err: 2846err:
2847 pm_runtime_disable(&i2c->dev);
2848
2726 return ret; 2849 return ret;
2727} 2850}
2728 2851
2729static int rt5670_i2c_remove(struct i2c_client *i2c) 2852static int rt5670_i2c_remove(struct i2c_client *i2c)
2730{ 2853{
2854 pm_runtime_disable(&i2c->dev);
2731 snd_soc_unregister_codec(&i2c->dev); 2855 snd_soc_unregister_codec(&i2c->dev);
2732 2856
2733 return 0; 2857 return 0;