[alsa-devel] [PATCH v2 3/4] ASoC: Intel: Support rt5660 codec for Baytrail

Shrirang Bagul shrirang.bagul at canonical.com
Mon Jan 16 08:45:22 CET 2017


On Thu, 2017-01-12 at 08:40 -0600, Pierre-Louis Bossart wrote:
> On 1/12/17 6:01 AM, Shrirang Bagul wrote:
> > rt5660 and rt5640 are similar codecs so reuse the bytcr_rt5640 driver.
> > RT5660 codec is used on Dell Edge IoT Gateways with ACPI ID 10EC3277.
> > These devices sport only Line-In and Line-Out jacks.
> 
> While it would be nice to avoid copy/pasting everytime we add a new 
> codec and refactor the code, I am not comfortable with a series of 
> changes below.
> Also if we do this refactoring then we might as well do it for rt5651 
> which is similar and only relies on I2S. other machine drivers enable 
> TDM mode when possible.
> And last this change has a lot of impact on how we deal with UCM files. 
> The name of the card should reflect which codec is used, and the quirks 
> be added to the long name. If you lump everything with a single name 
> then you will make it really hard for userspace to figure out which 
> controls need to be set.
> 
> So nice idea but too early to merge. NAK.
Thank you for the review, will address these comments in the next version. When
you it be appropriate to re-submit? Are we waiting for any patches which are
queued to be merged soon?
> 
> > 
> > Signed-off-by: Shrirang Bagul <shrirang.bagul at canonical.com>
> > ---
> >  sound/soc/intel/Kconfig               |  11 +--
> >  sound/soc/intel/atom/sst/sst_acpi.c   |   2 +
> >  sound/soc/intel/boards/bytcr_rt5640.c | 156 ++++++++++++++++++++++++++++++-
> > ---
> >  3 files changed, 147 insertions(+), 22 deletions(-)
> > 
> > diff --git a/sound/soc/intel/Kconfig b/sound/soc/intel/Kconfig
> > index fd5d1e0..0b43b6a 100644
> > --- a/sound/soc/intel/Kconfig
> > +++ b/sound/soc/intel/Kconfig
> > @@ -147,17 +147,18 @@ config SND_SOC_INTEL_BROADWELL_MACH
> >  	  If unsure select "N".
> > 
> >  config SND_SOC_INTEL_BYTCR_RT5640_MACH
> > -        tristate "ASoC Audio driver for Intel Baytrail and Baytrail-CR with
> > RT5640 codec"
> > +	tristate "ASoC Audio driver for Intel Baytrail and Baytrail-CR with
> > RT5640/5660 codec"
> >  	depends on X86 && I2C && ACPI
> >  	select SND_SOC_RT5640
> > +	select SND_SOC_RT5660
> >  	select SND_SST_MFLD_PLATFORM
> >  	select SND_SST_IPC_ACPI
> >  	select SND_SOC_INTEL_SST_MATCH if ACPI
> >  	help
> > -          This adds support for ASoC machine driver for Intel(R) Baytrail
> > and Baytrail-CR
> > -          platforms with RT5640 audio codec.
> > -          Say Y if you have such a device.
> > -          If unsure select "N".
> > +	  This adds support for ASoC machine driver for Intel(R) Baytrail
> > and Baytrail-CR
> > +	  platforms with RT5640, RT5460 audio codec.
> > +	  Say Y if you have such a device.
> > +	  If unsure select "N".
> > 
> >  config SND_SOC_INTEL_BYTCR_RT5651_MACH
> >          tristate "ASoC Audio driver for Intel Baytrail and Baytrail-CR with
> > RT5651 codec"
> > diff --git a/sound/soc/intel/atom/sst/sst_acpi.c
> > b/sound/soc/intel/atom/sst/sst_acpi.c
> > index f4d92bb..d401457f 100644
> > --- a/sound/soc/intel/atom/sst/sst_acpi.c
> > +++ b/sound/soc/intel/atom/sst/sst_acpi.c
> > @@ -441,6 +441,8 @@ static struct sst_acpi_mach sst_acpi_bytcr[] = {
> >  						&byt_rvp_platform_data },
> >  	{"10EC5642", "bytcr_rt5640", "intel/fw_sst_0f28.bin",
> > "bytcr_rt5640", NULL,
> >  						&byt_rvp_platform_data },
> > +	{"10EC3277", "bytcr_rt5640", "intel/fw_sst_0f28.bin",
> > "bytcr_rt5640", NULL,
> > +						&byt_rvp_platform_data },
> 
> so right there you add an HID in the platform driver and you need the 
> same in the platform driver to determine which codec type this is...
> 
> >  	{"INTCCFFD", "bytcr_rt5640", "intel/fw_sst_0f28.bin",
> > "bytcr_rt5640", NULL,
> >  						&byt_rvp_platform_data },
> >  	{"10EC5651", "bytcr_rt5651", "intel/fw_sst_0f28.bin",
> > "bytcr_rt5651", NULL,
> > diff --git a/sound/soc/intel/boards/bytcr_rt5640.c
> > b/sound/soc/intel/boards/bytcr_rt5640.c
> > index f6fd397..e8c9a01 100644
> > --- a/sound/soc/intel/boards/bytcr_rt5640.c
> > +++ b/sound/soc/intel/boards/bytcr_rt5640.c
> > @@ -32,11 +32,17 @@
> >  #include <sound/soc.h>
> >  #include <sound/jack.h>
> >  #include "../../codecs/rt5640.h"
> > +#include "../../codecs/rt5660.h"
> >  #include "../atom/sst-atom-controls.h"
> >  #include "../common/sst-acpi.h"
> >  #include "../common/sst-dsp.h"
> > 
> >  enum {
> > +	CODEC_TYPE_RT5640,
> > +	CODEC_TYPE_RT5660,
> > +};
> > +
> > +enum {
> >  	BYT_RT5640_DMIC1_MAP,
> >  	BYT_RT5640_DMIC2_MAP,
> >  	BYT_RT5640_IN1_MAP,
> > @@ -60,8 +66,16 @@ enum {
> >  	PLL1_MCLK,
> >  };
> > 
> > +struct byt_acpi_card {
> > +	char *codec_id;
> > +	int codec_type;
> > +	struct snd_soc_card *soc_card;
> > +};
> > +
> >  struct byt_rt5640_private {
> > +	struct byt_acpi_card *acpi_card;
> >  	struct clk *mclk;
> > +	char codec_name[16];
> >  	int *clks;
> >  };
> > 
> > @@ -72,6 +86,13 @@ static int byt_rt5640_clks[] = {
> >  	RT5640_PLL1_S_MCLK
> >  };
> > 
> > +static int byt_rt5660_clks[] = {
> > +	RT5660_SCLK_S_PLL1,
> > +	RT5660_SCLK_S_RCCLK,
> > +	RT5660_PLL1_S_BCLK,
> > +	RT5660_PLL1_S_MCLK
> > +};
> > +
> >  static unsigned long byt_rt5640_quirk = BYT_RT5640_MCLK_EN;
> 
> the quirks would need to be isolated and made dependent on codec type
Will fix in next version of the patch.
> 
> > 
> >  static void log_quirks(struct device *dev)
> > @@ -105,6 +126,7 @@ static void log_quirks(struct device *dev)
> > 
> >  #define BYT_CODEC_DAI1	"rt5640-aif1"
> >  #define BYT_CODEC_DAI2	"rt5640-aif2"
> > +#define BYT_CODEC_DAI3	"rt5660-aif1"
> > 
> >  static inline struct snd_soc_dai *byt_get_codec_dai(struct snd_soc_card
> > *card)
> >  {
> > @@ -117,6 +139,9 @@ static inline struct snd_soc_dai
> > *byt_get_codec_dai(struct snd_soc_card *card)
> >  		if (!strncmp(rtd->codec_dai->name, BYT_CODEC_DAI2,
> >  				strlen(BYT_CODEC_DAI2)))
> >  			return rtd->codec_dai;
> > +		if (!strncmp(rtd->codec_dai->name, BYT_CODEC_DAI3,
> > +				strlen(BYT_CODEC_DAI3)))
> > +			return rtd->codec_dai;
> 
> not very good to go look for a DAI that doesn't exist for a specific 
> codec. this would need to be dependent on codec type.
Understood, will fix this in next version.
> 
> > 
> >  	}
> >  	return NULL;
> > @@ -269,6 +294,29 @@ static const struct snd_kcontrol_new
> > byt_rt5640_controls[] = {
> >  	SOC_DAPM_PIN_SWITCH("Speaker"),
> >  };
> > 
> > +static const struct snd_soc_dapm_widget byt_rt5660_widgets[] = {
> > +	SND_SOC_DAPM_MIC("Line In", NULL),
> > +	SND_SOC_DAPM_LINE("Line Out", NULL),
> > +	SND_SOC_DAPM_SUPPLY("Platform Clock", SND_SOC_NOPM, 0, 0,
> > +			platform_clock_control, SND_SOC_DAPM_PRE_PMU |
> > +			SND_SOC_DAPM_POST_PMD),
> > +};
> > +
> > +static const struct snd_soc_dapm_route byt_rt5660_audio_map[] = {
> > +	{"IN1P", NULL, "Line In"},
> > +	{"IN2P", NULL, "Line In"},
> > +	{"Line Out", NULL, "LOUTR"},
> > +	{"Line Out", NULL, "LOUTL"},
> > +
> > +	{"Line In", NULL, "Platform Clock"},
> > +	{"Line Out", NULL, "Platform Clock"},
> > +};
> > +
> > +static const struct snd_kcontrol_new byt_rt5660_controls[] = {
> > +	SOC_DAPM_PIN_SWITCH("Line In"),
> > +	SOC_DAPM_PIN_SWITCH("Line Out"),
> > +};
> > +
> >  static int byt_rt5640_aif1_hw_params(struct snd_pcm_substream *substream,
> >  					struct snd_pcm_hw_params *params)
> >  {
> > @@ -422,11 +470,8 @@ static int byt_rt5640_init(struct snd_soc_pcm_runtime
> > *runtime)
> >  	struct snd_soc_codec *codec = runtime->codec;
> >  	struct snd_soc_card *card = runtime->card;
> >  	const struct snd_soc_dapm_route *custom_map;
> > -	struct byt_rt5640_private *priv = snd_soc_card_get_drvdata(card);
> >  	int num_routes;
> > 
> > -	card->dapm.idle_bias_off = true;
> > -
> >  	rt5640_sel_asrc_clk_src(codec,
> >  				RT5640_DA_STEREO_FILTER |
> >  				RT5640_DA_MONO_L_FILTER	|
> > @@ -511,6 +556,39 @@ static int byt_rt5640_init(struct snd_soc_pcm_runtime
> > *runtime)
> >  	snd_soc_dapm_ignore_suspend(&card->dapm, "Headphone");
> >  	snd_soc_dapm_ignore_suspend(&card->dapm, "Speaker");
> > 
> > +	return ret;
> > +}
> > +
> > +static int byt_rt5660_init(struct snd_soc_pcm_runtime *runtime)
> > +{
> > +	int ret;
> > +	struct snd_soc_card *card = runtime->card;
> > +
> > +	ret = snd_soc_dapm_add_routes(&card->dapm,
> > +			byt_rt5640_ssp2_aif1_map,
> > +			ARRAY_SIZE(byt_rt5640_ssp2_aif1_map));
> > +	if (ret)
> > +		return ret;
> > +
> > +	snd_soc_dapm_enable_pin(&card->dapm, "Line In");
> > +	snd_soc_dapm_enable_pin(&card->dapm, "Line Out");
> > +
> > +	return ret;
> > +}
> > +
> > +static int byt_rt56x0_init(struct snd_soc_pcm_runtime *runtime)
> > +{
> > +	int ret;
> > +	struct snd_soc_card *card = runtime->card;
> > +	struct byt_rt5640_private *priv = snd_soc_card_get_drvdata(card);
> > +
> > +	card->dapm.idle_bias_off = true;
> > +
> > +	if (priv->acpi_card->codec_type == CODEC_TYPE_RT5640)
> > +		ret = byt_rt5640_init(runtime);
> > +	else
> > +		ret = byt_rt5660_init(runtime);
> > +
> >  	if ((byt_rt5640_quirk & BYT_RT5640_MCLK_EN) && priv->mclk) {
> >  		/*
> >  		 * The firmware might enable the clock at
> > @@ -679,7 +757,7 @@ static struct snd_soc_dai_link byt_rt5640_dais[] = {
> >  		.ignore_suspend = 1,
> >  		.dpcm_playback = 1,
> >  		.dpcm_capture = 1,
> > -		.init = byt_rt5640_init,
> > +		.init = byt_rt56x0_init,
> >  		.ops = &byt_rt5640_be_ssp2_ops,
> >  	},
> >  };
> > @@ -697,6 +775,25 @@ static struct snd_soc_card byt_rt5640_card = {
> >  	.fully_routed = true,
> >  };
> > 
> > +static struct snd_soc_card byt_rt5660_card = {
> > +	.name = "bytcr-rt5660",
> > +	.owner = THIS_MODULE,
> > +	.dai_link = byt_rt5640_dais,
> > +	.num_links = ARRAY_SIZE(byt_rt5640_dais),
> > +	.controls = byt_rt5660_controls,
> > +	.num_controls = ARRAY_SIZE(byt_rt5660_controls),
> > +	.dapm_widgets = byt_rt5660_widgets,
> > +	.num_dapm_widgets = ARRAY_SIZE(byt_rt5660_widgets),
> > +	.dapm_routes = byt_rt5660_audio_map,
> > +	.num_dapm_routes = ARRAY_SIZE(byt_rt5660_audio_map),
> > +	.fully_routed = true,
> > +};
> > +
> > +static struct byt_acpi_card snd_soc_cards[] = {
> > +	{"10EC5640", CODEC_TYPE_RT5640, &byt_rt5640_card},
> > +	{"10EC3277", CODEC_TYPE_RT5660, &byt_rt5660_card},
> > +};
> 
> I know this is what's used for rt5645/50 but I don't like it and don't 
> think it should be the baseline for how we deal with codecs. This forces 
> the addition of additional quirks.
Is there a better baseline to start from or none exists and we ought to come-up
with one?
> 
> > +
> >  static char byt_rt5640_codec_name[16]; /* i2c-<HID>:00 with HID being 8
> > chars */
> >  static char byt_rt5640_codec_aif_name[12]; /*  = "rt5640-aif[1|2]" */
> >  static char byt_rt5640_cpu_dai_name[10]; /*  = "ssp[0|2]-port" */
> > @@ -721,41 +818,51 @@ struct acpi_chan_package {   /* ACPICA seems to
> > require 64 bit integers */
> >  static int snd_byt_rt5640_mc_probe(struct platform_device *pdev)
> >  {
> >  	int ret_val = 0;
> > -	struct sst_acpi_mach *mach;
> > -	const char *i2c_name = NULL;
> >  	int i;
> > -	int dai_index;
> >  	struct byt_rt5640_private *priv;
> > +	struct snd_soc_card *card = snd_soc_cards[0].soc_card;
> > +	struct sst_acpi_mach *mach;
> > +	const char *i2c_name = NULL;
> > +	int dai_index = 0;
> >  	bool is_bytcr = false;
> > 
> >  	priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_ATOMIC);
> >  	if (!priv)
> >  		return -ENOMEM;
> > 
> > +	for (i = 0; i < ARRAY_SIZE(snd_soc_cards); i++) {
> > +		if (acpi_dev_found(snd_soc_cards[i].codec_id)) {
> > +			dev_dbg(&pdev->dev,
> > +				"found codec %s\n",
> > snd_soc_cards[i].codec_id);
> > +			card = snd_soc_cards[i].soc_card;
> > +			priv->acpi_card = &snd_soc_cards[i];
> > +			break;
> > +		}
> > +	}
> > +
> >  	/* register the soc card */
> >  	priv->clks = byt_rt5640_clks;
> > -	byt_rt5640_card.dev = &pdev->dev;
> > -	mach = byt_rt5640_card.dev->platform_data;
> > -	snd_soc_card_set_drvdata(&byt_rt5640_card, priv);
> > +	card->dev = &pdev->dev;
> > +	mach = card->dev->platform_data;
> > +	sprintf(priv->codec_name, "i2c-%s:00", priv->acpi_card->codec_id);
> > 
> >  	/* fix index of codec dai */
> > -	dai_index = MERR_DPCM_COMPR + 1;
> > -	for (i = 0; i < ARRAY_SIZE(byt_rt5640_dais); i++) {
> > +	for (i = 0; i < ARRAY_SIZE(byt_rt5640_dais); i++)
> >  		if (!strcmp(byt_rt5640_dais[i].codec_name, "i2c-
> > 10EC5640:00")) {
> > +			card->dai_link[i].codec_name = priv->codec_name;
> >  			dai_index = i;
> > -			break;
> >  		}
> > -	}
> > 
> >  	/* fixup codec name based on HID */
> >  	i2c_name = sst_acpi_find_name_from_hid(mach->id);
> >  	if (i2c_name != NULL) {
> >  		snprintf(byt_rt5640_codec_name,
> > sizeof(byt_rt5640_codec_name),
> >  			"%s%s", "i2c-", i2c_name);
> > -
> >  		byt_rt5640_dais[dai_index].codec_name =
> > byt_rt5640_codec_name;
> >  	}
> > 
> > +	snd_soc_card_set_drvdata(card, priv);
> > +
> >  	/*
> >  	 * swap SSP0 if bytcr is detected
> >  	 * (will be overridden if DMI quirk is detected)
> > @@ -821,6 +928,21 @@ static int snd_byt_rt5640_mc_probe(struct
> > platform_device *pdev)
> >  				BYT_RT5640_DMIC_EN);
> >  	}
> > 
> > +	if (priv->acpi_card->codec_type == CODEC_TYPE_RT5660) {
> > +		priv->clks = byt_rt5660_clks;
> > +
> > +		/* fixup codec aif name for rt5660 */
> > +		snprintf(byt_rt5640_codec_aif_name,
> > +			sizeof(byt_rt5640_codec_aif_name),
> > +			"%s", "rt5660-aif1");
> > +
> > +		byt_rt5640_dais[dai_index].codec_dai_name =
> > +			byt_rt5640_codec_aif_name;
> > +
> > +		/* setup codec quirks for rt5660 */
> > +		byt_rt5640_quirk = BYT_RT5640_MCLK_EN;
> > +	}
> > +
> >  	/* check quirks before creating card */
> >  	dmi_check_system(byt_rt5640_quirk_table);
> 
> the quirks have to be separate.
> 
> >  	log_quirks(&pdev->dev);
> > @@ -869,14 +991,14 @@ static int snd_byt_rt5640_mc_probe(struct
> > platform_device *pdev)
> >  		}
> >  	}
> > 
> > -	ret_val = devm_snd_soc_register_card(&pdev->dev, &byt_rt5640_card);
> > +	ret_val = devm_snd_soc_register_card(&pdev->dev, card);
> > 
> >  	if (ret_val) {
> >  		dev_err(&pdev->dev, "devm_snd_soc_register_card failed
> > %d\n",
> >  			ret_val);
> >  		return ret_val;
> >  	}
> > -	platform_set_drvdata(pdev, &byt_rt5640_card);
> > +	platform_set_drvdata(pdev, card);
> >  	return ret_val;
> >  }
> > 
> > 
> 
> 


More information about the Alsa-devel mailing list