diff options
Diffstat (limited to 'sound/soc/codecs/mt6358.c')
| -rw-r--r-- | sound/soc/codecs/mt6358.c | 212 |
1 files changed, 83 insertions, 129 deletions
diff --git a/sound/soc/codecs/mt6358.c b/sound/soc/codecs/mt6358.c index 1b830ea4f6ed..a787accb88e8 100644 --- a/sound/soc/codecs/mt6358.c +++ b/sound/soc/codecs/mt6358.c @@ -6,8 +6,8 @@ // Author: KaiChieh Chuang <kaichieh.chuang@mediatek.com> #include <linux/platform_device.h> +#include <linux/mod_devicetable.h> #include <linux/module.h> -#include <linux/of_device.h> #include <linux/delay.h> #include <linux/kthread.h> #include <linux/sched.h> @@ -95,6 +95,8 @@ struct mt6358_priv { struct regulator *avdd_reg; int wov_enabled; + + int dmic_one_wire_mode; }; int mt6358_set_mtkaif_protocol(struct snd_soc_component *cmpnt, @@ -105,6 +107,7 @@ int mt6358_set_mtkaif_protocol(struct snd_soc_component *cmpnt, priv->mtkaif_protocol = mtkaif_protocol; return 0; } +EXPORT_SYMBOL_GPL(mt6358_set_mtkaif_protocol); static void playback_gpio_set(struct mt6358_priv *priv) { @@ -159,47 +162,6 @@ static void capture_gpio_reset(struct mt6358_priv *priv) 0xf << 12, 0x0); } -/* use only when not govern by DAPM */ -static int mt6358_set_dcxo(struct mt6358_priv *priv, bool enable) -{ - regmap_update_bits(priv->regmap, MT6358_DCXO_CW14, - 0x1 << RG_XO_AUDIO_EN_M_SFT, - (enable ? 1 : 0) << RG_XO_AUDIO_EN_M_SFT); - return 0; -} - -/* use only when not govern by DAPM */ -static int mt6358_set_clksq(struct mt6358_priv *priv, bool enable) -{ - /* audio clk source from internal dcxo */ - regmap_update_bits(priv->regmap, MT6358_AUDENC_ANA_CON6, - RG_CLKSQ_IN_SEL_TEST_MASK_SFT, - 0x0); - - /* Enable/disable CLKSQ 26MHz */ - regmap_update_bits(priv->regmap, MT6358_AUDENC_ANA_CON6, - RG_CLKSQ_EN_MASK_SFT, - (enable ? 1 : 0) << RG_CLKSQ_EN_SFT); - return 0; -} - -/* use only when not govern by DAPM */ -static int mt6358_set_aud_global_bias(struct mt6358_priv *priv, bool enable) -{ - regmap_update_bits(priv->regmap, MT6358_AUDDEC_ANA_CON13, - RG_AUDGLB_PWRDN_VA28_MASK_SFT, - (enable ? 0 : 1) << RG_AUDGLB_PWRDN_VA28_SFT); - return 0; -} - -/* use only when not govern by DAPM */ -static int mt6358_set_topck(struct mt6358_priv *priv, bool enable) -{ - regmap_update_bits(priv->regmap, MT6358_AUD_TOP_CKPDN_CON0, - 0x0066, enable ? 0x0 : 0x66); - return 0; -} - static int mt6358_mtkaif_tx_enable(struct mt6358_priv *priv) { switch (priv->mtkaif_protocol) { @@ -249,66 +211,6 @@ static int mt6358_mtkaif_tx_disable(struct mt6358_priv *priv) return 0; } -int mt6358_mtkaif_calibration_enable(struct snd_soc_component *cmpnt) -{ - struct mt6358_priv *priv = snd_soc_component_get_drvdata(cmpnt); - - playback_gpio_set(priv); - capture_gpio_set(priv); - mt6358_mtkaif_tx_enable(priv); - - mt6358_set_dcxo(priv, true); - mt6358_set_aud_global_bias(priv, true); - mt6358_set_clksq(priv, true); - mt6358_set_topck(priv, true); - - /* set dat_miso_loopback on */ - regmap_update_bits(priv->regmap, MT6358_AUDIO_DIG_CFG, - RG_AUD_PAD_TOP_DAT_MISO2_LOOPBACK_MASK_SFT, - 1 << RG_AUD_PAD_TOP_DAT_MISO2_LOOPBACK_SFT); - regmap_update_bits(priv->regmap, MT6358_AUDIO_DIG_CFG, - RG_AUD_PAD_TOP_DAT_MISO_LOOPBACK_MASK_SFT, - 1 << RG_AUD_PAD_TOP_DAT_MISO_LOOPBACK_SFT); - return 0; -} - -int mt6358_mtkaif_calibration_disable(struct snd_soc_component *cmpnt) -{ - struct mt6358_priv *priv = snd_soc_component_get_drvdata(cmpnt); - - /* set dat_miso_loopback off */ - regmap_update_bits(priv->regmap, MT6358_AUDIO_DIG_CFG, - RG_AUD_PAD_TOP_DAT_MISO2_LOOPBACK_MASK_SFT, - 0 << RG_AUD_PAD_TOP_DAT_MISO2_LOOPBACK_SFT); - regmap_update_bits(priv->regmap, MT6358_AUDIO_DIG_CFG, - RG_AUD_PAD_TOP_DAT_MISO_LOOPBACK_MASK_SFT, - 0 << RG_AUD_PAD_TOP_DAT_MISO_LOOPBACK_SFT); - - mt6358_set_topck(priv, false); - mt6358_set_clksq(priv, false); - mt6358_set_aud_global_bias(priv, false); - mt6358_set_dcxo(priv, false); - - mt6358_mtkaif_tx_disable(priv); - playback_gpio_reset(priv); - capture_gpio_reset(priv); - return 0; -} - -int mt6358_set_mtkaif_calibration_phase(struct snd_soc_component *cmpnt, - int phase_1, int phase_2) -{ - struct mt6358_priv *priv = snd_soc_component_get_drvdata(cmpnt); - - regmap_update_bits(priv->regmap, MT6358_AUDIO_DIG_CFG, - RG_AUD_PAD_TOP_PHASE_MODE_MASK_SFT, - phase_1 << RG_AUD_PAD_TOP_PHASE_MODE_SFT); - regmap_update_bits(priv->regmap, MT6358_AUDIO_DIG_CFG, - RG_AUD_PAD_TOP_PHASE_MODE2_MASK_SFT, - phase_2 << RG_AUD_PAD_TOP_PHASE_MODE2_SFT); - return 0; -} - /* dl pga gain */ enum { DL_GAIN_8DB = 0, @@ -329,7 +231,7 @@ static void hp_zcd_disable(struct mt6358_priv *priv) static void hp_main_output_ramp(struct mt6358_priv *priv, bool up) { - int i = 0, stage = 0; + int i, stage; int target = 7; /* Enable/Reduce HPL/R main output stage step by step */ @@ -345,7 +247,7 @@ static void hp_main_output_ramp(struct mt6358_priv *priv, bool up) static void hp_aux_feedback_loop_gain_ramp(struct mt6358_priv *priv, bool up) { - int i = 0, stage = 0; + int i, stage; /* Reduce HP aux feedback loop gain step by step */ for (i = 0; i <= 0xf; i++) { @@ -418,12 +320,11 @@ static void headset_volume_ramp(struct mt6358_priv *priv, int from, int to) static int mt6358_put_volsw(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { - struct snd_soc_component *component = - snd_soc_kcontrol_component(kcontrol); + struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); struct mt6358_priv *priv = snd_soc_component_get_drvdata(component); struct soc_mixer_control *mc = (struct soc_mixer_control *)kcontrol->private_value; - unsigned int reg; + unsigned int reg = 0; int ret; ret = snd_soc_put_volsw(kcontrol, ucontrol); @@ -540,7 +441,7 @@ static int mt6358_disable_wov_phase2(struct mt6358_priv *priv) static int mt6358_get_wov(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { - struct snd_soc_component *c = snd_soc_kcontrol_component(kcontrol); + struct snd_soc_component *c = snd_kcontrol_chip(kcontrol); struct mt6358_priv *priv = snd_soc_component_get_drvdata(c); ucontrol->value.integer.value[0] = priv->wov_enabled; @@ -550,10 +451,13 @@ static int mt6358_get_wov(struct snd_kcontrol *kcontrol, static int mt6358_put_wov(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { - struct snd_soc_component *c = snd_soc_kcontrol_component(kcontrol); + struct snd_soc_component *c = snd_kcontrol_chip(kcontrol); struct mt6358_priv *priv = snd_soc_component_get_drvdata(c); int enabled = ucontrol->value.integer.value[0]; + if (enabled < 0 || enabled > 1) + return -EINVAL; + if (priv->wov_enabled != enabled) { if (enabled) mt6358_enable_wov_phase2(priv); @@ -561,11 +465,46 @@ static int mt6358_put_wov(struct snd_kcontrol *kcontrol, mt6358_disable_wov_phase2(priv); priv->wov_enabled = enabled; + + return 1; } return 0; } +static int mt6358_dmic_mode_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *c = snd_kcontrol_chip(kcontrol); + struct mt6358_priv *priv = snd_soc_component_get_drvdata(c); + + ucontrol->value.integer.value[0] = priv->dmic_one_wire_mode; + dev_dbg(priv->dev, "%s() dmic_mode = %d", __func__, priv->dmic_one_wire_mode); + + return 0; +} + +static int mt6358_dmic_mode_set(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *c = snd_kcontrol_chip(kcontrol); + struct mt6358_priv *priv = snd_soc_component_get_drvdata(c); + int enabled = ucontrol->value.integer.value[0]; + + if (enabled < 0 || enabled > 1) + return -EINVAL; + + if (priv->dmic_one_wire_mode != enabled) { + priv->dmic_one_wire_mode = enabled; + dev_dbg(priv->dev, "%s() dmic_mode = %d", __func__, priv->dmic_one_wire_mode); + + return 1; + } + dev_dbg(priv->dev, "%s() dmic_mode = %d", __func__, priv->dmic_one_wire_mode); + + return 0; +} + static const DECLARE_TLV_DB_SCALE(playback_tlv, -1000, 100, 0); static const DECLARE_TLV_DB_SCALE(pga_tlv, 0, 600, 0); @@ -588,6 +527,9 @@ static const struct snd_kcontrol_new mt6358_snd_controls[] = { SOC_SINGLE_BOOL_EXT("Wake-on-Voice Phase2 Switch", 0, mt6358_get_wov, mt6358_put_wov), + + SOC_SINGLE_BOOL_EXT("Dmic Mode Switch", 0, + mt6358_dmic_mode_get, mt6358_dmic_mode_set), }; /* MUX */ @@ -626,9 +568,6 @@ static const char * const hp_in_mux_map[] = { "Audio Playback", "Test Mode", "HP Impedance", - "undefined1", - "undefined2", - "undefined3", }; static int hp_in_mux_map_value[] = { @@ -637,9 +576,6 @@ static int hp_in_mux_map_value[] = { HP_MUX_HP, HP_MUX_TEST_MODE, HP_MUX_HP_IMPEDANCE, - HP_MUX_OPEN, - HP_MUX_OPEN, - HP_MUX_OPEN, }; static SOC_VALUE_ENUM_SINGLE_DECL(hpl_in_mux_map_enum, @@ -1351,7 +1287,7 @@ static int mt_hp_event(struct snd_soc_dapm_widget *w, { struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm); struct mt6358_priv *priv = snd_soc_component_get_drvdata(cmpnt); - unsigned int mux = dapm_kcontrol_get_value(w->kcontrols[0]); + unsigned int mux = snd_soc_dapm_kcontrol_get_value(w->kcontrols[0]); int device = DEVICE_HP; dev_info(priv->dev, "%s(), event 0x%x, dev_counter[DEV_HP] %d, mux %u\n", @@ -1413,7 +1349,7 @@ static int mt_rcv_event(struct snd_soc_dapm_widget *w, dev_info(priv->dev, "%s(), event 0x%x, mux %u\n", __func__, event, - dapm_kcontrol_get_value(w->kcontrols[0])); + snd_soc_dapm_kcontrol_get_value(w->kcontrols[0])); switch (event) { case SND_SOC_DAPM_PRE_PMU: @@ -1831,7 +1767,10 @@ static int mt6358_dmic_enable(struct mt6358_priv *priv) mt6358_mtkaif_tx_enable(priv); /* UL dmic setting */ - regmap_write(priv->regmap, MT6358_AFE_UL_SRC_CON0_H, 0x0080); + if (priv->dmic_one_wire_mode) + regmap_write(priv->regmap, MT6358_AFE_UL_SRC_CON0_H, 0x0400); + else + regmap_write(priv->regmap, MT6358_AFE_UL_SRC_CON0_H, 0x0080); /* UL turn on */ regmap_write(priv->regmap, MT6358_AFE_UL_SRC_CON0_L, 0x0003); @@ -1889,7 +1828,7 @@ static int mt_mic_type_event(struct snd_soc_dapm_widget *w, { struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm); struct mt6358_priv *priv = snd_soc_component_get_drvdata(cmpnt); - unsigned int mux = dapm_kcontrol_get_value(w->kcontrols[0]); + unsigned int mux = snd_soc_dapm_kcontrol_get_value(w->kcontrols[0]); dev_dbg(priv->dev, "%s(), event 0x%x, mux %u\n", __func__, event, mux); @@ -1935,7 +1874,7 @@ static int mt_adc_l_event(struct snd_soc_dapm_widget *w, { struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm); struct mt6358_priv *priv = snd_soc_component_get_drvdata(cmpnt); - unsigned int mux = dapm_kcontrol_get_value(w->kcontrols[0]); + unsigned int mux = snd_soc_dapm_kcontrol_get_value(w->kcontrols[0]); dev_dbg(priv->dev, "%s(), event = 0x%x, mux %u\n", __func__, event, mux); @@ -1951,7 +1890,7 @@ static int mt_adc_r_event(struct snd_soc_dapm_widget *w, { struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm); struct mt6358_priv *priv = snd_soc_component_get_drvdata(cmpnt); - unsigned int mux = dapm_kcontrol_get_value(w->kcontrols[0]); + unsigned int mux = snd_soc_dapm_kcontrol_get_value(w->kcontrols[0]); dev_dbg(priv->dev, "%s(), event = 0x%x, mux %u\n", __func__, event, mux); @@ -1967,7 +1906,7 @@ static int mt_pga_left_event(struct snd_soc_dapm_widget *w, { struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm); struct mt6358_priv *priv = snd_soc_component_get_drvdata(cmpnt); - unsigned int mux = dapm_kcontrol_get_value(w->kcontrols[0]); + unsigned int mux = snd_soc_dapm_kcontrol_get_value(w->kcontrols[0]); dev_dbg(priv->dev, "%s(), event = 0x%x, mux %u\n", __func__, event, mux); @@ -1983,7 +1922,7 @@ static int mt_pga_right_event(struct snd_soc_dapm_widget *w, { struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm); struct mt6358_priv *priv = snd_soc_component_get_drvdata(cmpnt); - unsigned int mux = dapm_kcontrol_get_value(w->kcontrols[0]); + unsigned int mux = snd_soc_dapm_kcontrol_get_value(w->kcontrols[0]); dev_dbg(priv->dev, "%s(), event = 0x%x, mux %u\n", __func__, event, mux); @@ -2331,12 +2270,9 @@ static const struct snd_soc_dai_ops mt6358_codec_dai_ops = { .hw_params = mt6358_codec_dai_hw_params, }; -#define MT6358_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S16_BE |\ - SNDRV_PCM_FMTBIT_U16_LE | SNDRV_PCM_FMTBIT_U16_BE |\ - SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S24_BE |\ - SNDRV_PCM_FMTBIT_U24_LE | SNDRV_PCM_FMTBIT_U24_BE |\ - SNDRV_PCM_FMTBIT_S32_LE | SNDRV_PCM_FMTBIT_S32_BE |\ - SNDRV_PCM_FMTBIT_U32_LE | SNDRV_PCM_FMTBIT_U32_BE) +#define MT6358_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_U16_LE |\ + SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_U24_LE |\ + SNDRV_PCM_FMTBIT_S32_LE | SNDRV_PCM_FMTBIT_U32_LE) static struct snd_soc_dai_driver mt6358_dai_driver[] = { { @@ -2424,8 +2360,23 @@ static const struct snd_soc_component_driver mt6358_soc_component_driver = { .num_dapm_widgets = ARRAY_SIZE(mt6358_dapm_widgets), .dapm_routes = mt6358_dapm_routes, .num_dapm_routes = ARRAY_SIZE(mt6358_dapm_routes), + .endianness = 1, }; +static void mt6358_parse_dt(struct mt6358_priv *priv) +{ + int ret; + struct device *dev = priv->dev; + + ret = of_property_read_u32(dev->of_node, "mediatek,dmic-mode", + &priv->dmic_one_wire_mode); + if (ret) { + dev_warn(priv->dev, "%s() failed to read dmic-mode\n", + __func__); + priv->dmic_one_wire_mode = 0; + } +} + static int mt6358_platform_driver_probe(struct platform_device *pdev) { struct mt6358_priv *priv; @@ -2445,6 +2396,8 @@ static int mt6358_platform_driver_probe(struct platform_device *pdev) if (IS_ERR(priv->regmap)) return PTR_ERR(priv->regmap); + mt6358_parse_dt(priv); + dev_info(priv->dev, "%s(), dev name %s\n", __func__, dev_name(&pdev->dev)); @@ -2456,6 +2409,7 @@ static int mt6358_platform_driver_probe(struct platform_device *pdev) static const struct of_device_id mt6358_of_match[] = { {.compatible = "mediatek,mt6358-sound",}, + {.compatible = "mediatek,mt6366-sound",}, {} }; MODULE_DEVICE_TABLE(of, mt6358_of_match); |
