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

Commit f2d4c127 authored by Mark Brown's avatar Mark Brown
Browse files

Merge remote-tracking branches 'asoc/topic/pxa' and 'asoc/topic/qcom' into asoc-next

Loading
Loading
Loading
Loading
+0 −2
Original line number Diff line number Diff line
@@ -52,7 +52,6 @@ static int brownstone_wm8994_hw_params(struct snd_pcm_substream *substream,
	struct snd_soc_dai *codec_dai = rtd->codec_dai;
	struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
	int freq_out, sspa_mclk, sysclk;
	int sspa_div;

	if (params_rate(params) > 11025) {
		freq_out  = params_rate(params) * 512;
@@ -63,7 +62,6 @@ static int brownstone_wm8994_hw_params(struct snd_pcm_substream *substream,
		sysclk    = params_rate(params) * 512;
		sspa_mclk = params_rate(params) * 64;
	}
	sspa_div = freq_out / sspa_mclk;

	snd_soc_dai_set_sysclk(cpu_dai, MMP_SSPA_CLK_AUDIO, freq_out, 0);
	snd_soc_dai_set_pll(cpu_dai, MMP_SYSCLK, 0, freq_out, sysclk);
+5 −2
Original line number Diff line number Diff line
@@ -11,21 +11,24 @@ config SND_SOC_LPASS_CPU

config SND_SOC_LPASS_PLATFORM
	tristate
	depends on HAS_DMA
	select REGMAP_MMIO

config SND_SOC_LPASS_IPQ806X
	tristate
	depends on HAS_DMA
	select SND_SOC_LPASS_CPU
	select SND_SOC_LPASS_PLATFORM

config SND_SOC_LPASS_APQ8016
	tristate
	depends on HAS_DMA
	select SND_SOC_LPASS_CPU
	select SND_SOC_LPASS_PLATFORM

config SND_SOC_STORM
	tristate "ASoC I2S support for Storm boards"
	depends on SND_SOC_QCOM
	depends on SND_SOC_QCOM && HAS_DMA
	select SND_SOC_LPASS_IPQ806X
	select SND_SOC_MAX98357A
	help
@@ -34,7 +37,7 @@ config SND_SOC_STORM

config SND_SOC_APQ8016_SBC
	tristate "SoC Audio support for APQ8016 SBC platforms"
	depends on SND_SOC_QCOM
	depends on SND_SOC_QCOM && HAS_DMA
	select SND_SOC_LPASS_APQ8016
	help
          Support for Qualcomm Technologies LPASS audio block in
+7 −3
Original line number Diff line number Diff line
@@ -30,6 +30,7 @@ struct apq8016_sbc_data {
	struct snd_soc_dai_link dai_link[];	/* dynamically allocated */
};

#define MIC_CTRL_TER_WS_SLAVE_SEL	BIT(21)
#define MIC_CTRL_QUA_WS_SLAVE_SEL_10	BIT(17)
#define MIC_CTRL_TLMM_SCLK_EN		BIT(1)
#define	SPKR_CTL_PRI_WS_SLAVE_SEL_11	(BIT(17) | BIT(16))
@@ -53,6 +54,12 @@ static int apq8016_sbc_dai_init(struct snd_soc_pcm_runtime *rtd)
			MIC_CTRL_TLMM_SCLK_EN,
			pdata->mic_iomux);
		break;
	case MI2S_TERTIARY:
		writel(readl(pdata->mic_iomux) | MIC_CTRL_TER_WS_SLAVE_SEL |
			MIC_CTRL_TLMM_SCLK_EN,
			pdata->mic_iomux);

		break;

	default:
		dev_err(card->dev, "unsupported cpu dai configuration\n");
@@ -126,9 +133,6 @@ static struct apq8016_sbc_data *apq8016_sbc_parse_of(struct snd_soc_card *card)
		}

		link->platform_of_node = link->cpu_of_node;
		/* For now we only support playback */
		link->playback_only = true;

		ret = of_property_read_string(np, "link-name", &link->name);
		if (ret) {
			dev_err(card->dev, "error getting codec dai_link name\n");
+24 −7
Original line number Diff line number Diff line
@@ -133,23 +133,36 @@ static struct snd_soc_dai_driver apq8016_lpass_cpu_dai_driver[] = {
	},
};

static int apq8016_lpass_alloc_dma_channel(struct lpass_data *drvdata)
static int apq8016_lpass_alloc_dma_channel(struct lpass_data *drvdata,
					   int direction)
{
	struct lpass_variant *v = drvdata->variant;
	int chan = find_first_zero_bit(&drvdata->rdma_ch_bit_map,
	int chan = 0;

	if (direction == SNDRV_PCM_STREAM_PLAYBACK) {
		chan = find_first_zero_bit(&drvdata->dma_ch_bit_map,
					v->rdma_channels);

		if (chan >= v->rdma_channels)
			return -EBUSY;
	} else {
		chan = find_next_zero_bit(&drvdata->dma_ch_bit_map,
					v->wrdma_channel_start +
					v->wrdma_channels,
					v->wrdma_channel_start);

		if (chan >=  v->wrdma_channel_start + v->wrdma_channels)
			return -EBUSY;
	}

	set_bit(chan, &drvdata->rdma_ch_bit_map);
	set_bit(chan, &drvdata->dma_ch_bit_map);

	return chan;
}

static int apq8016_lpass_free_dma_channel(struct lpass_data *drvdata, int chan)
{
	clear_bit(chan, &drvdata->rdma_ch_bit_map);
	clear_bit(chan, &drvdata->dma_ch_bit_map);

	return 0;
}
@@ -212,7 +225,11 @@ static struct lpass_variant apq8016_data = {
	.rdma_reg_base		= 0x8400,
	.rdma_reg_stride	= 0x1000,
	.rdma_channels		= 2,
	.rdmactl_audif_start	= 1,
	.dmactl_audif_start	= 1,
	.wrdma_reg_base		= 0xB000,
	.wrdma_reg_stride	= 0x1000,
	.wrdma_channel_start	= 5,
	.wrdma_channels		= 2,
	.dai_driver		= apq8016_lpass_cpu_dai_driver,
	.num_dai		= ARRAY_SIZE(apq8016_lpass_cpu_dai_driver),
	.init			= apq8016_lpass_init,
+114 −32
Original line number Diff line number Diff line
@@ -120,6 +120,7 @@ static int lpass_cpu_daiops_hw_params(struct snd_pcm_substream *substream,
		return -EINVAL;
	}

	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
		switch (channels) {
		case 1:
			regval |= LPAIF_I2SCTL_SPKMODE_SD0;
@@ -146,6 +147,34 @@ static int lpass_cpu_daiops_hw_params(struct snd_pcm_substream *substream,
					__func__, channels);
			return -EINVAL;
		}
	} else {
		switch (channels) {
		case 1:
			regval |= LPAIF_I2SCTL_MICMODE_SD0;
			regval |= LPAIF_I2SCTL_MICMONO_MONO;
			break;
		case 2:
			regval |= LPAIF_I2SCTL_MICMODE_SD0;
			regval |= LPAIF_I2SCTL_MICMONO_STEREO;
			break;
		case 4:
			regval |= LPAIF_I2SCTL_MICMODE_QUAD01;
			regval |= LPAIF_I2SCTL_MICMONO_STEREO;
			break;
		case 6:
			regval |= LPAIF_I2SCTL_MICMODE_6CH;
			regval |= LPAIF_I2SCTL_MICMONO_STEREO;
			break;
		case 8:
			regval |= LPAIF_I2SCTL_MICMODE_8CH;
			regval |= LPAIF_I2SCTL_MICMONO_STEREO;
			break;
		default:
			dev_err(dai->dev, "%s() invalid channels given: %u\n",
					__func__, channels);
			return -EINVAL;
		}
	}

	ret = regmap_write(drvdata->lpaif_map,
			   LPAIF_I2SCTL_REG(drvdata->variant, dai->driver->id),
@@ -188,10 +217,19 @@ static int lpass_cpu_daiops_prepare(struct snd_pcm_substream *substream,
{
	struct lpass_data *drvdata = snd_soc_dai_get_drvdata(dai);
	int ret;
	unsigned int val, mask;

	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
		val = LPAIF_I2SCTL_SPKEN_ENABLE;
		mask = LPAIF_I2SCTL_SPKEN_MASK;
	} else  {
		val = LPAIF_I2SCTL_MICEN_ENABLE;
		mask = LPAIF_I2SCTL_MICEN_MASK;
	}

	ret = regmap_update_bits(drvdata->lpaif_map,
			LPAIF_I2SCTL_REG(drvdata->variant, dai->driver->id),
			LPAIF_I2SCTL_SPKEN_MASK, LPAIF_I2SCTL_SPKEN_ENABLE);
			mask, val);
	if (ret)
		dev_err(dai->dev, "%s() error writing to i2sctl reg: %d\n",
				__func__, ret);
@@ -204,16 +242,24 @@ static int lpass_cpu_daiops_trigger(struct snd_pcm_substream *substream,
{
	struct lpass_data *drvdata = snd_soc_dai_get_drvdata(dai);
	int ret = -EINVAL;
	unsigned int val, mask;

	switch (cmd) {
	case SNDRV_PCM_TRIGGER_START:
	case SNDRV_PCM_TRIGGER_RESUME:
	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
		if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
			val = LPAIF_I2SCTL_SPKEN_ENABLE;
			mask = LPAIF_I2SCTL_SPKEN_MASK;
		} else  {
			val = LPAIF_I2SCTL_MICEN_ENABLE;
			mask = LPAIF_I2SCTL_MICEN_MASK;
		}

		ret = regmap_update_bits(drvdata->lpaif_map,
				LPAIF_I2SCTL_REG(drvdata->variant,
						dai->driver->id),
				LPAIF_I2SCTL_SPKEN_MASK,
				LPAIF_I2SCTL_SPKEN_ENABLE);
				mask, val);
		if (ret)
			dev_err(dai->dev, "%s() error writing to i2sctl reg: %d\n",
					__func__, ret);
@@ -221,11 +267,18 @@ static int lpass_cpu_daiops_trigger(struct snd_pcm_substream *substream,
	case SNDRV_PCM_TRIGGER_STOP:
	case SNDRV_PCM_TRIGGER_SUSPEND:
	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
		if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
			val = LPAIF_I2SCTL_SPKEN_DISABLE;
			mask = LPAIF_I2SCTL_SPKEN_MASK;
		} else  {
			val = LPAIF_I2SCTL_MICEN_DISABLE;
			mask = LPAIF_I2SCTL_MICEN_MASK;
		}

		ret = regmap_update_bits(drvdata->lpaif_map,
				LPAIF_I2SCTL_REG(drvdata->variant,
						dai->driver->id),
				LPAIF_I2SCTL_SPKEN_MASK,
				LPAIF_I2SCTL_SPKEN_DISABLE);
				mask, val);
		if (ret)
			dev_err(dai->dev, "%s() error writing to i2sctl reg: %d\n",
					__func__, ret);
@@ -294,6 +347,17 @@ static bool lpass_cpu_regmap_writeable(struct device *dev, unsigned int reg)
			return true;
	}

	for (i = 0; i < v->wrdma_channels; ++i) {
		if (reg == LPAIF_WRDMACTL_REG(v, i + v->wrdma_channel_start))
			return true;
		if (reg == LPAIF_WRDMABASE_REG(v, i + v->wrdma_channel_start))
			return true;
		if (reg == LPAIF_WRDMABUFF_REG(v, i + v->wrdma_channel_start))
			return true;
		if (reg == LPAIF_WRDMAPER_REG(v, i + v->wrdma_channel_start))
			return true;
	}

	return false;
}

@@ -327,6 +391,19 @@ static bool lpass_cpu_regmap_readable(struct device *dev, unsigned int reg)
			return true;
	}

	for (i = 0; i < v->wrdma_channels; ++i) {
		if (reg == LPAIF_WRDMACTL_REG(v, i + v->wrdma_channel_start))
			return true;
		if (reg == LPAIF_WRDMABASE_REG(v, i + v->wrdma_channel_start))
			return true;
		if (reg == LPAIF_WRDMABUFF_REG(v, i + v->wrdma_channel_start))
			return true;
		if (reg == LPAIF_WRDMACURR_REG(v, i + v->wrdma_channel_start))
			return true;
		if (reg == LPAIF_WRDMAPER_REG(v, i + v->wrdma_channel_start))
			return true;
	}

	return false;
}

@@ -344,6 +421,10 @@ static bool lpass_cpu_regmap_volatile(struct device *dev, unsigned int reg)
		if (reg == LPAIF_RDMACURR_REG(v, i))
			return true;

	for (i = 0; i < v->wrdma_channels; ++i)
		if (reg == LPAIF_WRDMACURR_REG(v, i + v->wrdma_channel_start))
			return true;

	return false;
}

@@ -398,8 +479,9 @@ int asoc_qcom_lpass_cpu_platform_probe(struct platform_device *pdev)
		return PTR_ERR((void const __force *)drvdata->lpaif);
	}

	lpass_cpu_regmap_config.max_register = LPAIF_RDMAPER_REG(variant,
						variant->rdma_channels);
	lpass_cpu_regmap_config.max_register = LPAIF_WRDMAPER_REG(variant,
						variant->wrdma_channels +
						variant->wrdma_channel_start);

	drvdata->lpaif_map = devm_regmap_init_mmio(&pdev->dev, drvdata->lpaif,
			&lpass_cpu_regmap_config);
Loading