[alsa-devel] [PATCH] ASoC: rt5640: add ASRC support
From: Bard Liao bardliao@realtek.com
This patch add ASRC support for rt5640 series codecs.
Signed-off-by: Bard Liao bardliao@realtek.com --- sound/soc/codecs/rt5640.c | 79 ++++++++++++++++++++++++++++++++++++++++++++++- sound/soc/codecs/rt5640.h | 2 ++ 2 files changed, 80 insertions(+), 1 deletion(-)
diff --git a/sound/soc/codecs/rt5640.c b/sound/soc/codecs/rt5640.c index 6bc6efd..3245ec4 100644 --- a/sound/soc/codecs/rt5640.c +++ b/sound/soc/codecs/rt5640.c @@ -341,6 +341,43 @@ static bool rt5640_readable_register(struct device *dev, unsigned int reg) } }
+static const char * const rt5640_asrc_mode[] = { + "disable", "enable" +}; + +static const SOC_ENUM_SINGLE_DECL(rt5640_asrc_enum, SND_SOC_NOPM, + 0, rt5640_asrc_mode); + +static int rt5640_asrc_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol); + struct rt5640_priv *rt5640 = snd_soc_codec_get_drvdata(codec); + + rt5640->asrc_en = ucontrol->value.integer.value[0]; + + if (rt5640->asrc_en) { + snd_soc_update_bits(codec, RT5640_DUMMY1, 0x70, 0x70); + snd_soc_update_bits(codec, RT5640_JD_CTRL, 0x3, 0x3); + } else { + snd_soc_update_bits(codec, RT5640_DUMMY1, 0x70, 0x0); + snd_soc_update_bits(codec, RT5640_JD_CTRL, 0x3, 0x0); + } + + return 0; +} + +static int rt5640_asrc_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol); + struct rt5640_priv *rt5640 = snd_soc_codec_get_drvdata(codec); + + ucontrol->value.enumerated.item[0] = rt5640->asrc_en; + + return 0; +} + static const DECLARE_TLV_DB_SCALE(out_vol_tlv, -4650, 150, 0); static const DECLARE_TLV_DB_SCALE(dac_vol_tlv, -65625, 375, 0); static const DECLARE_TLV_DB_SCALE(in_vol_tlv, -3450, 150, 0); @@ -436,6 +473,10 @@ static const struct snd_kcontrol_new rt5640_snd_controls[] = { SOC_ENUM("DAC IF1 Data Switch", rt5640_if1_dac_enum), SOC_ENUM("ADC IF2 Data Switch", rt5640_if2_adc_enum), SOC_ENUM("DAC IF2 Data Switch", rt5640_if2_dac_enum), + + /* ASRC */ + SOC_ENUM_EXT("ASRC Switch", rt5640_asrc_enum, + rt5640_asrc_get, rt5640_asrc_put), };
static const struct snd_kcontrol_new rt5640_specific_snd_controls[] = { @@ -1020,9 +1061,37 @@ static int rt5640_hp_post_event(struct snd_soc_dapm_widget *w, return 0; }
+static int rt5640_asrc_event(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, int event) +{ + struct rt5640_priv *rt5640 = snd_soc_codec_get_drvdata(w->codec); + + if (!rt5640->asrc_en) + return 0; + + switch (event) { + case SND_SOC_DAPM_PRE_PMU: + snd_soc_write(w->codec, RT5640_ASRC_1, 0x9b00); + snd_soc_write(w->codec, RT5640_ASRC_2, 0xf800); + break; + case SND_SOC_DAPM_POST_PMD: + snd_soc_write(w->codec, RT5640_ASRC_1, 0x0); + snd_soc_write(w->codec, RT5640_ASRC_2, 0x0); + break; + default: + return 0; + } + + return 0; +} + static const struct snd_soc_dapm_widget rt5640_dapm_widgets[] = { SND_SOC_DAPM_SUPPLY("PLL1", RT5640_PWR_ANLG2, RT5640_PWR_PLL_BIT, 0, NULL, 0), + + SND_SOC_DAPM_SUPPLY_S("ASRC Function", 1, SND_SOC_NOPM, + 0, 0, rt5640_asrc_event, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), /* Input Side */ /* micbias */ SND_SOC_DAPM_SUPPLY("LDO2", RT5640_PWR_ANLG1, @@ -1276,6 +1345,9 @@ static const struct snd_soc_dapm_widget rt5639_specific_dapm_widgets[] = { };
static const struct snd_soc_dapm_route rt5640_dapm_routes[] = { + {"I2S1", NULL, "ASRC Function"}, + {"I2S2", NULL, "ASRC Function"}, + {"IN1P", NULL, "LDO2"}, {"IN2P", NULL, "LDO2"},
@@ -1635,7 +1707,12 @@ static int rt5640_hw_params(struct snd_pcm_substream *substream, int dai_sel, pre_div, bclk_ms, frame_size;
rt5640->lrck[dai->id] = params_rate(params); - pre_div = rl6231_get_clk_info(rt5640->sysclk, rt5640->lrck[dai->id]); + if (rt5640->asrc_en) + pre_div = 0; + else + pre_div = rl6231_get_clk_info(rt5640->sysclk, + rt5640->lrck[dai->id]); + if (pre_div < 0) { dev_err(codec->dev, "Unsupported clock setting %d for DAI %d\n", rt5640->lrck[dai->id], dai->id); diff --git a/sound/soc/codecs/rt5640.h b/sound/soc/codecs/rt5640.h index 58ebe96..0b39178 100644 --- a/sound/soc/codecs/rt5640.h +++ b/sound/soc/codecs/rt5640.h @@ -2095,6 +2095,8 @@ struct rt5640_priv { int pll_out;
bool hp_mute; + + int asrc_en; };
#endif
On 06/27/2014 12:58 PM, bardliao@realtek.com wrote:
From: Bard Liao bardliao@realtek.com
This patch add ASRC support for rt5640 series codecs.
Signed-off-by: Bard Liao bardliao@realtek.com
sound/soc/codecs/rt5640.c | 79 ++++++++++++++++++++++++++++++++++++++++++++++- sound/soc/codecs/rt5640.h | 2 ++ 2 files changed, 80 insertions(+), 1 deletion(-)
diff --git a/sound/soc/codecs/rt5640.c b/sound/soc/codecs/rt5640.c index 6bc6efd..3245ec4 100644 --- a/sound/soc/codecs/rt5640.c +++ b/sound/soc/codecs/rt5640.c @@ -341,6 +341,43 @@ static bool rt5640_readable_register(struct device *dev, unsigned int reg) } }
+static const char * const rt5640_asrc_mode[] = {
- "disable", "enable"
+};
+static const SOC_ENUM_SINGLE_DECL(rt5640_asrc_enum, SND_SOC_NOPM,
0, rt5640_asrc_mode);
I wonder if that shouldn't be something that is automatically enabled/disabled based on the samplerates involved. Also for enable/disable controls use a switch control rather than a enum.
- Lars
-----Original Message----- From: Lars-Peter Clausen [mailto:lars@metafoo.de] Sent: Friday, June 27, 2014 10:05 PM To: Bard Liao; broonie@kernel.org; lgirdwood@gmail.com Cc: Oder Chiou; alsa-devel@alsa-project.org; Flove Subject: Re: [alsa-devel] [PATCH] ASoC: rt5640: add ASRC support
I wonder if that shouldn't be something that is automatically enabled/disabled based on the samplerates involved. Also for enable/disable controls use a switch control rather than a enum.
To turn on/off rt5640's ASRC function is not decided by only one condition. To make it flexible, I prefer to use a control to enable/ disable ASRC function. Do you mean SOC_SINGLE_EXT? I didn't find a _SWITCH control in soc.h
- Lars
------Please consider the environment before printing this e-mail.
On 06/30/2014 08:09 AM, Bard Liao wrote:
-----Original Message----- From: Lars-Peter Clausen [mailto:lars@metafoo.de] Sent: Friday, June 27, 2014 10:05 PM To: Bard Liao; broonie@kernel.org; lgirdwood@gmail.com Cc: Oder Chiou; alsa-devel@alsa-project.org; Flove Subject: Re: [alsa-devel] [PATCH] ASoC: rt5640: add ASRC support
I wonder if that shouldn't be something that is automatically enabled/disabled based on the samplerates involved. Also for enable/disable controls use a switch control rather than a enum.
To turn on/off rt5640's ASRC function is not decided by only one condition. To make it flexible, I prefer to use a control to enable/ disable ASRC function.
But the driver should be able to autodetect those conditions, shouldn't it?
Do you mean SOC_SINGLE_EXT? I didn't find a _SWITCH control in soc.h
Yes SOC_SINGLE_EXT() will create a boolean switch if xmax == 1 (otherwise it will create a integer control).
- Lars
On Mon, Jun 30, 2014 at 12:45:06PM +0200, Lars-Peter Clausen wrote:
On 06/30/2014 08:09 AM, Bard Liao wrote:
To turn on/off rt5640's ASRC function is not decided by only one condition. To make it flexible, I prefer to use a control to enable/ disable ASRC function.
But the driver should be able to autodetect those conditions, shouldn't it?
That depends; we're back to issues with the clock API again. If the device is slave on an interface which is ultimately clocked from a clock which is also fed directly to the device it's not going to be able to tell that the two are synchronous even if we have the common clock API.
However this still shouldn't be exposed directly to userspace since the clocking is generally handled entirely in the kernel.
participants (4)
-
Bard Liao
-
bardliao@realtek.com
-
Lars-Peter Clausen
-
Mark Brown