Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 4f1eacf5 authored by Mark Brown's avatar Mark Brown
Browse files

Merge remote-tracking branches 'asoc/topic/fsl-spdif', 'asoc/topic/imx',...

Merge remote-tracking branches 'asoc/topic/fsl-spdif', 'asoc/topic/imx', 'asoc/topic/intel', 'asoc/topic/mxs-saif' and 'asoc/topic/nuc900' into asoc-next
Loading
Loading
Loading
Loading
+121 −0
Original line number Diff line number Diff line
@@ -14,10 +14,12 @@
#include <linux/init.h>
#include <linux/delay.h>
#include <linux/pm.h>
#include <linux/pm_runtime.h>
#include <linux/i2c.h>
#include <linux/platform_device.h>
#include <linux/acpi.h>
#include <linux/spi/spi.h>
#include <linux/dmi.h>
#include <sound/core.h>
#include <sound/pcm.h>
#include <sound/pcm_params.h>
@@ -590,6 +592,89 @@ static int can_use_asrc(struct snd_soc_dapm_widget *source,
	return 0;
}


/**
 * rt5670_sel_asrc_clk_src - select ASRC clock source for a set of filters
 * @codec: SoC audio codec device.
 * @filter_mask: mask of filters.
 * @clk_src: clock source
 *
 * The ASRC function is for asynchronous MCLK and LRCK. Also, since RT5670 can
 * only support standard 32fs or 64fs i2s format, ASRC should be enabled to
 * support special i2s clock format such as Intel's 100fs(100 * sampling rate).
 * ASRC function will track i2s clock and generate a corresponding system clock
 * for codec. This function provides an API to select the clock source for a
 * set of filters specified by the mask. And the codec driver will turn on ASRC
 * for these filters if ASRC is selected as their clock source.
 */
int rt5670_sel_asrc_clk_src(struct snd_soc_codec *codec,
			    unsigned int filter_mask, unsigned int clk_src)
{
	unsigned int asrc2_mask = 0, asrc2_value = 0;
	unsigned int asrc3_mask = 0, asrc3_value = 0;

	if (clk_src > RT5670_CLK_SEL_SYS3)
		return -EINVAL;

	if (filter_mask & RT5670_DA_STEREO_FILTER) {
		asrc2_mask |= RT5670_DA_STO_CLK_SEL_MASK;
		asrc2_value = (asrc2_value & ~RT5670_DA_STO_CLK_SEL_MASK)
				| (clk_src <<  RT5670_DA_STO_CLK_SEL_SFT);
	}

	if (filter_mask & RT5670_DA_MONO_L_FILTER) {
		asrc2_mask |= RT5670_DA_MONOL_CLK_SEL_MASK;
		asrc2_value = (asrc2_value & ~RT5670_DA_MONOL_CLK_SEL_MASK)
				| (clk_src <<  RT5670_DA_MONOL_CLK_SEL_SFT);
	}

	if (filter_mask & RT5670_DA_MONO_R_FILTER) {
		asrc2_mask |= RT5670_DA_MONOR_CLK_SEL_MASK;
		asrc2_value = (asrc2_value & ~RT5670_DA_MONOR_CLK_SEL_MASK)
				| (clk_src <<  RT5670_DA_MONOR_CLK_SEL_SFT);
	}

	if (filter_mask & RT5670_AD_STEREO_FILTER) {
		asrc2_mask |= RT5670_AD_STO1_CLK_SEL_MASK;
		asrc2_value = (asrc2_value & ~RT5670_AD_STO1_CLK_SEL_MASK)
				| (clk_src <<  RT5670_AD_STO1_CLK_SEL_SFT);
	}

	if (filter_mask & RT5670_AD_MONO_L_FILTER) {
		asrc3_mask |= RT5670_AD_MONOL_CLK_SEL_MASK;
		asrc3_value = (asrc3_value & ~RT5670_AD_MONOL_CLK_SEL_MASK)
				| (clk_src <<  RT5670_AD_MONOL_CLK_SEL_SFT);
	}

	if (filter_mask & RT5670_AD_MONO_R_FILTER)  {
		asrc3_mask |= RT5670_AD_MONOR_CLK_SEL_MASK;
		asrc3_value = (asrc3_value & ~RT5670_AD_MONOR_CLK_SEL_MASK)
				| (clk_src <<  RT5670_AD_MONOR_CLK_SEL_SFT);
	}

	if (filter_mask & RT5670_UP_RATE_FILTER) {
		asrc3_mask |= RT5670_UP_CLK_SEL_MASK;
		asrc3_value = (asrc3_value & ~RT5670_UP_CLK_SEL_MASK)
				| (clk_src <<  RT5670_UP_CLK_SEL_SFT);
	}

	if (filter_mask & RT5670_DOWN_RATE_FILTER) {
		asrc3_mask |= RT5670_DOWN_CLK_SEL_MASK;
		asrc3_value = (asrc3_value & ~RT5670_DOWN_CLK_SEL_MASK)
				| (clk_src <<  RT5670_DOWN_CLK_SEL_SFT);
	}

	if (asrc2_mask)
		snd_soc_update_bits(codec, RT5670_ASRC_2,
				    asrc2_mask, asrc2_value);

	if (asrc3_mask)
		snd_soc_update_bits(codec, RT5670_ASRC_3,
				    asrc3_mask, asrc3_value);
	return 0;
}
EXPORT_SYMBOL_GPL(rt5670_sel_asrc_clk_src);

/* Digital Mixer */
static const struct snd_kcontrol_new rt5670_sto1_adc_l_mix[] = {
	SOC_DAPM_SINGLE("ADC1 Switch", RT5670_STO1_ADC_MIXER,
@@ -2190,6 +2275,13 @@ static int rt5670_set_dai_sysclk(struct snd_soc_dai *dai,
	if (freq == rt5670->sysclk && clk_id == rt5670->sysclk_src)
		return 0;

	if (rt5670->pdata.jd_mode) {
		if (clk_id == RT5670_SCLK_S_PLL1)
			snd_soc_dapm_force_enable_pin(&codec->dapm, "PLL1");
		else
			snd_soc_dapm_disable_pin(&codec->dapm, "PLL1");
		snd_soc_dapm_sync(&codec->dapm);
	}
	switch (clk_id) {
	case RT5670_SCLK_S_MCLK:
		reg_val |= RT5670_SCLK_SRC_MCLK;
@@ -2551,6 +2643,17 @@ static struct acpi_device_id rt5670_acpi_match[] = {
MODULE_DEVICE_TABLE(acpi, rt5670_acpi_match);
#endif

static const struct dmi_system_id dmi_platform_intel_braswell[] = {
	{
		.ident = "Intel Braswell",
		.matches = {
			DMI_MATCH(DMI_SYS_VENDOR, "Intel Corporation"),
			DMI_MATCH(DMI_BOARD_NAME, "Braswell CRB"),
		},
	},
	{}
};

static int rt5670_i2c_probe(struct i2c_client *i2c,
		    const struct i2c_device_id *id)
{
@@ -2570,6 +2673,12 @@ static int rt5670_i2c_probe(struct i2c_client *i2c,
	if (pdata)
		rt5670->pdata = *pdata;

	if (dmi_check_system(dmi_platform_intel_braswell)) {
		rt5670->pdata.dmic_en = true;
		rt5670->pdata.dmic1_data_pin = RT5670_DMIC_DATA_IN2P;
		rt5670->pdata.jd_mode = 1;
	}

	rt5670->regmap = devm_regmap_init_i2c(i2c, &rt5670_regmap);
	if (IS_ERR(rt5670->regmap)) {
		ret = PTR_ERR(rt5670->regmap);
@@ -2611,6 +2720,10 @@ static int rt5670_i2c_probe(struct i2c_client *i2c,
	}

	if (rt5670->pdata.jd_mode) {
		regmap_update_bits(rt5670->regmap, RT5670_GLB_CLK,
				   RT5670_SCLK_SRC_MASK, RT5670_SCLK_SRC_RCCLK);
		rt5670->sysclk = 0;
		rt5670->sysclk_src = RT5670_SCLK_S_RCCLK;
		regmap_update_bits(rt5670->regmap, RT5670_PWR_ANLG1,
				   RT5670_PWR_MB, RT5670_PWR_MB);
		regmap_update_bits(rt5670->regmap, RT5670_PWR_ANLG2,
@@ -2718,18 +2831,26 @@ static int rt5670_i2c_probe(struct i2c_client *i2c,

	}

	pm_runtime_enable(&i2c->dev);
	pm_request_idle(&i2c->dev);

	ret = snd_soc_register_codec(&i2c->dev, &soc_codec_dev_rt5670,
			rt5670_dai, ARRAY_SIZE(rt5670_dai));
	if (ret < 0)
		goto err;

	pm_runtime_put(&i2c->dev);

	return 0;
err:
	pm_runtime_disable(&i2c->dev);

	return ret;
}

static int rt5670_i2c_remove(struct i2c_client *i2c)
{
	pm_runtime_disable(&i2c->dev);
	snd_soc_unregister_codec(&i2c->dev);

	return 0;
+39 −41
Original line number Diff line number Diff line
@@ -1023,50 +1023,33 @@
#define RT5670_DMIC_2_M_NOR			(0x0 << 8)
#define RT5670_DMIC_2_M_ASYN			(0x1 << 8)

/* ASRC clock source selection (0x84, 0x85) */
#define RT5670_CLK_SEL_SYS			(0x0)
#define RT5670_CLK_SEL_I2S1_ASRC		(0x1)
#define RT5670_CLK_SEL_I2S2_ASRC		(0x2)
#define RT5670_CLK_SEL_I2S3_ASRC		(0x3)
#define RT5670_CLK_SEL_SYS2			(0x5)
#define RT5670_CLK_SEL_SYS3			(0x6)

/* ASRC Control 2 (0x84) */
#define RT5670_MDA_L_M_MASK			(0x1 << 15)
#define RT5670_MDA_L_M_SFT			15
#define RT5670_MDA_L_M_NOR			(0x0 << 15)
#define RT5670_MDA_L_M_ASYN			(0x1 << 15)
#define RT5670_MDA_R_M_MASK			(0x1 << 14)
#define RT5670_MDA_R_M_SFT			14
#define RT5670_MDA_R_M_NOR			(0x0 << 14)
#define RT5670_MDA_R_M_ASYN			(0x1 << 14)
#define RT5670_MAD_L_M_MASK			(0x1 << 13)
#define RT5670_MAD_L_M_SFT			13
#define RT5670_MAD_L_M_NOR			(0x0 << 13)
#define RT5670_MAD_L_M_ASYN			(0x1 << 13)
#define RT5670_MAD_R_M_MASK			(0x1 << 12)
#define RT5670_MAD_R_M_SFT			12
#define RT5670_MAD_R_M_NOR			(0x0 << 12)
#define RT5670_MAD_R_M_ASYN			(0x1 << 12)
#define RT5670_ADC_M_MASK			(0x1 << 11)
#define RT5670_ADC_M_SFT			11
#define RT5670_ADC_M_NOR			(0x0 << 11)
#define RT5670_ADC_M_ASYN			(0x1 << 11)
#define RT5670_STO_DAC_M_MASK			(0x1 << 5)
#define RT5670_STO_DAC_M_SFT			5
#define RT5670_STO_DAC_M_NOR			(0x0 << 5)
#define RT5670_STO_DAC_M_ASYN			(0x1 << 5)
#define RT5670_I2S1_R_D_MASK			(0x1 << 4)
#define RT5670_I2S1_R_D_SFT			4
#define RT5670_I2S1_R_D_DIS			(0x0 << 4)
#define RT5670_I2S1_R_D_EN			(0x1 << 4)
#define RT5670_I2S2_R_D_MASK			(0x1 << 3)
#define RT5670_I2S2_R_D_SFT			3
#define RT5670_I2S2_R_D_DIS			(0x0 << 3)
#define RT5670_I2S2_R_D_EN			(0x1 << 3)
#define RT5670_PRE_SCLK_MASK			(0x3)
#define RT5670_PRE_SCLK_SFT			0
#define RT5670_PRE_SCLK_512			(0x0)
#define RT5670_PRE_SCLK_1024			(0x1)
#define RT5670_PRE_SCLK_2048			(0x2)
#define RT5670_DA_STO_CLK_SEL_MASK		(0xf << 12)
#define RT5670_DA_STO_CLK_SEL_SFT		12
#define RT5670_DA_MONOL_CLK_SEL_MASK		(0xf << 8)
#define RT5670_DA_MONOL_CLK_SEL_SFT		8
#define RT5670_DA_MONOR_CLK_SEL_MASK		(0xf << 4)
#define RT5670_DA_MONOR_CLK_SEL_SFT		4
#define RT5670_AD_STO1_CLK_SEL_MASK		(0xf << 0)
#define RT5670_AD_STO1_CLK_SEL_SFT		0

/* ASRC Control 3 (0x85) */
#define RT5670_I2S1_RATE_MASK			(0xf << 12)
#define RT5670_I2S1_RATE_SFT			12
#define RT5670_I2S2_RATE_MASK			(0xf << 8)
#define RT5670_I2S2_RATE_SFT			8
#define RT5670_UP_CLK_SEL_MASK			(0xf << 12)
#define RT5670_UP_CLK_SEL_SFT			12
#define RT5670_DOWN_CLK_SEL_MASK		(0xf << 8)
#define RT5670_DOWN_CLK_SEL_SFT			8
#define RT5670_AD_MONOL_CLK_SEL_MASK		(0xf << 4)
#define RT5670_AD_MONOL_CLK_SEL_SFT		4
#define RT5670_AD_MONOR_CLK_SEL_MASK		(0xf << 0)
#define RT5670_AD_MONOR_CLK_SEL_SFT		0

/* ASRC Control 4 (0x89) */
#define RT5670_I2S1_PD_MASK			(0x7 << 12)
@@ -1983,6 +1966,21 @@ enum {
	RT5670_DMIC_DATA_GPIO5,
};

/* filter mask */
enum {
	RT5670_DA_STEREO_FILTER = 0x1,
	RT5670_DA_MONO_L_FILTER = (0x1 << 1),
	RT5670_DA_MONO_R_FILTER = (0x1 << 2),
	RT5670_AD_STEREO_FILTER = (0x1 << 3),
	RT5670_AD_MONO_L_FILTER = (0x1 << 4),
	RT5670_AD_MONO_R_FILTER = (0x1 << 5),
	RT5670_UP_RATE_FILTER   = (0x1 << 6),
	RT5670_DOWN_RATE_FILTER = (0x1 << 7),
};

int rt5670_sel_asrc_clk_src(struct snd_soc_codec *codec,
			    unsigned int filter_mask, unsigned int clk_src);

struct rt5670_priv {
	struct snd_soc_codec *codec;
	struct rt5670_platform_data pdata;
+3 −12
Original line number Diff line number Diff line
@@ -90,7 +90,6 @@ struct spdif_mixer_control {
 * @sysclk: system clock for rx clock rate measurement
 * @dma_params_tx: DMA parameters for transmit channel
 * @dma_params_rx: DMA parameters for receive channel
 * @name: driver name
 */
struct fsl_spdif_priv {
	struct spdif_mixer_control fsl_spdif_control;
@@ -109,12 +108,8 @@ struct fsl_spdif_priv {
	struct clk *sysclk;
	struct snd_dmaengine_dai_dma_data dma_params_tx;
	struct snd_dmaengine_dai_dma_data dma_params_rx;

	/* The name space will be allocated dynamically */
	char name[0];
};


/* DPLL locked and lock loss interrupt handler */
static void spdif_irq_dpll_lock(struct fsl_spdif_priv *spdif_priv)
{
@@ -1169,19 +1164,15 @@ static int fsl_spdif_probe(struct platform_device *pdev)
	if (!np)
		return -ENODEV;

	spdif_priv = devm_kzalloc(&pdev->dev,
			sizeof(struct fsl_spdif_priv) + strlen(np->name) + 1,
			GFP_KERNEL);
	spdif_priv = devm_kzalloc(&pdev->dev, sizeof(*spdif_priv), GFP_KERNEL);
	if (!spdif_priv)
		return -ENOMEM;

	strcpy(spdif_priv->name, np->name);

	spdif_priv->pdev = pdev;

	/* Initialize this copy of the CPU DAI driver structure */
	memcpy(&spdif_priv->cpu_dai_drv, &fsl_spdif_dai, sizeof(fsl_spdif_dai));
	spdif_priv->cpu_dai_drv.name = spdif_priv->name;
	spdif_priv->cpu_dai_drv.name = dev_name(&pdev->dev);

	/* Get the addresses and IRQ */
	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
@@ -1203,7 +1194,7 @@ static int fsl_spdif_probe(struct platform_device *pdev)
	}

	ret = devm_request_irq(&pdev->dev, irq, spdif_isr, 0,
			spdif_priv->name, spdif_priv);
			       dev_name(&pdev->dev), spdif_priv);
	if (ret) {
		dev_err(&pdev->dev, "could not claim irq %u\n", irq);
		return ret;
+1 −1
Original line number Diff line number Diff line
@@ -160,7 +160,7 @@ struct fsl_ssi_soc_data {
 */
struct fsl_ssi_private {
	struct regmap *regs;
	unsigned int irq;
	int irq;
	struct snd_soc_dai_driver cpu_dai_drv;

	unsigned int dai_fmt;
+1 −0
Original line number Diff line number Diff line
@@ -60,6 +60,7 @@ static int imx_spdif_audio_probe(struct platform_device *pdev)
	data->card.dev = &pdev->dev;
	data->card.dai_link = &data->dai;
	data->card.num_links = 1;
	data->card.owner = THIS_MODULE;

	ret = snd_soc_of_parse_card_name(&data->card, "model");
	if (ret)
Loading