Unverified Commit b5022a36 authored by Rohit kumar's avatar Rohit kumar Committed by Mark Brown
Browse files

ASoC: qcom: lpass: Use regmap_field for i2sctl and dmactl registers



I2SCTL and DMACTL registers has different bits alignment for newer
LPASS variants of SC7180 soc. Use REG_FIELD_ID() to define the
reg_fields in platform specific file and removed shifts and mask
macros for such registers from header file.

Signed-off-by: default avatarRohit kumar <rohitkr@codeaurora.org>
Link: https://lore.kernel.org/r/1597402388-14112-6-git-send-email-rohitkr@codeaurora.org


Signed-off-by: default avatarMark Brown <broonie@kernel.org>
parent 5fd18821
Loading
Loading
Loading
Loading
+24 −0
Original line number Diff line number Diff line
@@ -240,6 +240,30 @@ static struct lpass_variant apq8016_data = {
	.wrdma_reg_stride	= 0x1000,
	.wrdma_channel_start	= 5,
	.wrdma_channels		= 2,
	.loopback		= REG_FIELD_ID(0x1000, 15, 15, 4, 0x1000),
	.spken			= REG_FIELD_ID(0x1000, 14, 14, 4, 0x1000),
	.spkmode		= REG_FIELD_ID(0x1000, 10, 13, 4, 0x1000),
	.spkmono		= REG_FIELD_ID(0x1000, 9, 9, 4, 0x1000),
	.micen			= REG_FIELD_ID(0x1000, 8, 8, 4, 0x1000),
	.micmode		= REG_FIELD_ID(0x1000, 4, 7, 4, 0x1000),
	.micmono		= REG_FIELD_ID(0x1000, 3, 3, 4, 0x1000),
	.wssrc			= REG_FIELD_ID(0x1000, 2, 2, 4, 0x1000),
	.bitwidth		= REG_FIELD_ID(0x1000, 0, 0, 4, 0x1000),

	.rdma_dyncclk		= REG_FIELD_ID(0x8400, 12, 12, 2, 0x1000),
	.rdma_bursten		= REG_FIELD_ID(0x8400, 11, 11, 2, 0x1000),
	.rdma_wpscnt		= REG_FIELD_ID(0x8400, 8, 10, 2, 0x1000),
	.rdma_intf		= REG_FIELD_ID(0x8400, 4, 7, 2, 0x1000),
	.rdma_fifowm		= REG_FIELD_ID(0x8400, 1, 3, 2, 0x1000),
	.rdma_enable		= REG_FIELD_ID(0x8400, 0, 0, 2, 0x1000),

	.wrdma_dyncclk		= REG_FIELD_ID(0xB000, 12, 12, 2, 0x1000),
	.wrdma_bursten		= REG_FIELD_ID(0xB000, 11, 11, 2, 0x1000),
	.wrdma_wpscnt		= REG_FIELD_ID(0xB000, 8, 10, 2, 0x1000),
	.wrdma_intf		= REG_FIELD_ID(0xB000, 4, 7, 2, 0x1000),
	.wrdma_fifowm		= REG_FIELD_ID(0xB000, 1, 3, 2, 0x1000),
	.wrdma_enable		= REG_FIELD_ID(0xB000, 0, 0, 2, 0x1000),

	.clk_name		= (const char*[]) {
				   "pcnoc-mport-clk",
				   "pcnoc-sway-clk",
+107 −49
Original line number Diff line number Diff line
@@ -29,6 +29,32 @@
#define LPASS_CPU_I2S_SD0_1_2_MASK	GENMASK(2, 0)
#define LPASS_CPU_I2S_SD0_1_2_3_MASK	GENMASK(3, 0)

static int lpass_cpu_init_i2sctl_bitfields(struct device *dev,
			struct lpaif_i2sctl *i2sctl, struct regmap *map)
{
	struct lpass_data *drvdata = dev_get_drvdata(dev);
	struct lpass_variant *v = drvdata->variant;

	i2sctl->loopback = devm_regmap_field_alloc(dev, map, v->loopback);
	i2sctl->spken = devm_regmap_field_alloc(dev, map, v->spken);
	i2sctl->spkmode = devm_regmap_field_alloc(dev, map, v->spkmode);
	i2sctl->spkmono = devm_regmap_field_alloc(dev, map, v->spkmono);
	i2sctl->micen = devm_regmap_field_alloc(dev, map, v->micen);
	i2sctl->micmode = devm_regmap_field_alloc(dev, map, v->micmode);
	i2sctl->micmono = devm_regmap_field_alloc(dev, map, v->micmono);
	i2sctl->wssrc = devm_regmap_field_alloc(dev, map, v->wssrc);
	i2sctl->bitwidth = devm_regmap_field_alloc(dev, map, v->bitwidth);

	if (IS_ERR(i2sctl->loopback) || IS_ERR(i2sctl->spken) ||
	    IS_ERR(i2sctl->spkmode) || IS_ERR(i2sctl->spkmono) ||
	    IS_ERR(i2sctl->micen) || IS_ERR(i2sctl->micmode) ||
	    IS_ERR(i2sctl->micmono) || IS_ERR(i2sctl->wssrc) ||
	    IS_ERR(i2sctl->bitwidth))
		return -EINVAL;

	return 0;
}

static int lpass_cpu_daiops_set_sysclk(struct snd_soc_dai *dai, int clk_id,
		unsigned int freq, int dir)
{
@@ -79,6 +105,8 @@ static int lpass_cpu_daiops_hw_params(struct snd_pcm_substream *substream,
		struct snd_pcm_hw_params *params, struct snd_soc_dai *dai)
{
	struct lpass_data *drvdata = snd_soc_dai_get_drvdata(dai);
	struct lpaif_i2sctl *i2sctl = drvdata->i2sctl;
	unsigned int id = dai->driver->id;
	snd_pcm_format_t format = params_format(params);
	unsigned int channels = params_channels(params);
	unsigned int rate = params_rate(params);
@@ -92,28 +120,45 @@ static int lpass_cpu_daiops_hw_params(struct snd_pcm_substream *substream,
		return bitwidth;
	}

	regval = LPAIF_I2SCTL_LOOPBACK_DISABLE |
			LPAIF_I2SCTL_WSSRC_INTERNAL;
	ret = regmap_fields_write(i2sctl->loopback, id,
				 LPAIF_I2SCTL_LOOPBACK_DISABLE);
	if (ret) {
		dev_err(dai->dev, "error updating loopback field: %d\n", ret);
		return ret;
	}

	ret = regmap_fields_write(i2sctl->wssrc, id,
				 LPAIF_I2SCTL_WSSRC_INTERNAL);
	if (ret) {
		dev_err(dai->dev, "error updating wssrc field: %d\n", ret);
		return ret;
	}

	switch (bitwidth) {
	case 16:
		regval |= LPAIF_I2SCTL_BITWIDTH_16;
		regval = LPAIF_I2SCTL_BITWIDTH_16;
		break;
	case 24:
		regval |= LPAIF_I2SCTL_BITWIDTH_24;
		regval = LPAIF_I2SCTL_BITWIDTH_24;
		break;
	case 32:
		regval |= LPAIF_I2SCTL_BITWIDTH_32;
		regval = LPAIF_I2SCTL_BITWIDTH_32;
		break;
	default:
		dev_err(dai->dev, "invalid bitwidth given: %d\n", bitwidth);
		return -EINVAL;
	}

	ret = regmap_fields_write(i2sctl->bitwidth, id, regval);
	if (ret) {
		dev_err(dai->dev, "error updating bitwidth field: %d\n", ret);
		return ret;
	}

	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
		mode = drvdata->mi2s_playback_sd_mode[dai->driver->id];
		mode = drvdata->mi2s_playback_sd_mode[id];
	else
		mode = drvdata->mi2s_capture_sd_mode[dai->driver->id];
		mode = drvdata->mi2s_capture_sd_mode[id];

	if (!mode) {
		dev_err(dai->dev, "no line is assigned\n");
@@ -175,30 +220,42 @@ static int lpass_cpu_daiops_hw_params(struct snd_pcm_substream *substream,
	}

	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
		regval |= LPAIF_I2SCTL_SPKMODE(mode);

		ret = regmap_fields_write(i2sctl->spkmode, id,
					 LPAIF_I2SCTL_SPKMODE(mode));
		if (ret) {
			dev_err(dai->dev, "error writing to i2sctl spkr mode: %d\n",
				ret);
			return ret;
		}
		if (channels >= 2)
			regval |= LPAIF_I2SCTL_SPKMONO_STEREO;
			ret = regmap_fields_write(i2sctl->spkmono, id,
						 LPAIF_I2SCTL_SPKMONO_STEREO);
		else
			regval |= LPAIF_I2SCTL_SPKMONO_MONO;
			ret = regmap_fields_write(i2sctl->spkmono, id,
						 LPAIF_I2SCTL_SPKMONO_MONO);
	} else {
		regval |= LPAIF_I2SCTL_MICMODE(mode);

		ret = regmap_fields_write(i2sctl->micmode, id,
					 LPAIF_I2SCTL_MICMODE(mode));
		if (ret) {
			dev_err(dai->dev, "error writing to i2sctl mic mode: %d\n",
				ret);
			return ret;
		}
		if (channels >= 2)
			regval |= LPAIF_I2SCTL_MICMONO_STEREO;
			ret = regmap_fields_write(i2sctl->micmono, id,
						 LPAIF_I2SCTL_MICMONO_STEREO);
		else
			regval |= LPAIF_I2SCTL_MICMONO_MONO;
			ret = regmap_fields_write(i2sctl->micmono, id,
						 LPAIF_I2SCTL_MICMONO_MONO);
	}

	ret = regmap_write(drvdata->lpaif_map,
			   LPAIF_I2SCTL_REG(drvdata->variant, dai->driver->id),
			   regval);
	if (ret) {
		dev_err(dai->dev, "error writing to i2sctl reg: %d\n", ret);
		dev_err(dai->dev, "error writing to i2sctl channels mode: %d\n",
			ret);
		return ret;
	}

	ret = clk_set_rate(drvdata->mi2s_bit_clk[dai->driver->id],
	ret = clk_set_rate(drvdata->mi2s_bit_clk[id],
			   rate * bitwidth * 2);
	if (ret) {
		dev_err(dai->dev, "error setting mi2s bitclk to %u: %d\n",
@@ -228,22 +285,20 @@ static int lpass_cpu_daiops_prepare(struct snd_pcm_substream *substream,
		struct snd_soc_dai *dai)
{
	struct lpass_data *drvdata = snd_soc_dai_get_drvdata(dai);
	struct lpaif_i2sctl *i2sctl = drvdata->i2sctl;
	unsigned int id = dai->driver->id;
	int ret;
	unsigned int val, mask;

	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
		val = LPAIF_I2SCTL_SPKEN_ENABLE;
		mask = LPAIF_I2SCTL_SPKEN_MASK;
		ret = regmap_fields_write(i2sctl->spken, id,
					 LPAIF_I2SCTL_SPKEN_ENABLE);
	} else {
		val = LPAIF_I2SCTL_MICEN_ENABLE;
		mask = LPAIF_I2SCTL_MICEN_MASK;
		ret = regmap_fields_write(i2sctl->micen, id,
					 LPAIF_I2SCTL_MICEN_ENABLE);
	}

	ret = regmap_update_bits(drvdata->lpaif_map,
			LPAIF_I2SCTL_REG(drvdata->variant, dai->driver->id),
			mask, val);
	if (ret)
		dev_err(dai->dev, "error writing to i2sctl reg: %d\n", ret);
		dev_err(dai->dev, "error writing to i2sctl enable: %d\n", ret);

	return ret;
}
@@ -252,25 +307,21 @@ static int lpass_cpu_daiops_trigger(struct snd_pcm_substream *substream,
		int cmd, struct snd_soc_dai *dai)
{
	struct lpass_data *drvdata = snd_soc_dai_get_drvdata(dai);
	struct lpaif_i2sctl *i2sctl = drvdata->i2sctl;
	unsigned int id = dai->driver->id;
	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;
			ret = regmap_fields_write(i2sctl->spken, id,
						 LPAIF_I2SCTL_SPKEN_ENABLE);
		} else  {
			val = LPAIF_I2SCTL_MICEN_ENABLE;
			mask = LPAIF_I2SCTL_MICEN_MASK;
			ret = regmap_fields_write(i2sctl->micen, id,
						 LPAIF_I2SCTL_MICEN_ENABLE);
		}

		ret = regmap_update_bits(drvdata->lpaif_map,
				LPAIF_I2SCTL_REG(drvdata->variant,
						dai->driver->id),
				mask, val);
		if (ret)
			dev_err(dai->dev, "error writing to i2sctl reg: %d\n",
				ret);
@@ -279,17 +330,12 @@ static int lpass_cpu_daiops_trigger(struct snd_pcm_substream *substream,
	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;
			ret = regmap_fields_write(i2sctl->spken, id,
						 LPAIF_I2SCTL_SPKEN_DISABLE);
		} else  {
			val = LPAIF_I2SCTL_MICEN_DISABLE;
			mask = LPAIF_I2SCTL_MICEN_MASK;
			ret = regmap_fields_write(i2sctl->micen, id,
						 LPAIF_I2SCTL_MICEN_DISABLE);
		}

		ret = regmap_update_bits(drvdata->lpaif_map,
				LPAIF_I2SCTL_REG(drvdata->variant,
						dai->driver->id),
				mask, val);
		if (ret)
			dev_err(dai->dev, "error writing to i2sctl reg: %d\n",
				ret);
@@ -599,6 +645,18 @@ int asoc_qcom_lpass_cpu_platform_probe(struct platform_device *pdev)
		}
	}

	/* Allocation for i2sctl regmap fields */
	drvdata->i2sctl = devm_kzalloc(&pdev->dev, sizeof(struct lpaif_i2sctl),
					GFP_KERNEL);

	/* Initialize bitfields for dai I2SCTL register */
	ret = lpass_cpu_init_i2sctl_bitfields(dev, drvdata->i2sctl,
						drvdata->lpaif_map);
	if (ret) {
		dev_err(dev, "error init i2sctl field: %d\n", ret);
		return ret;
	}

	ret = devm_snd_soc_register_component(dev,
					      &lpass_cpu_comp_driver,
					      variant->dai_driver,
+24 −0
Original line number Diff line number Diff line
@@ -123,6 +123,30 @@ static struct lpass_variant ipq806x_data = {
	.wrdma_reg_stride	= 0x1000,
	.wrdma_channel_start	= 5,
	.wrdma_channels		= 4,
	.loopback		= REG_FIELD_ID(0x0010, 15, 15, 5, 0x4),
	.spken			= REG_FIELD_ID(0x0010, 14, 14, 5, 0x4),
	.spkmode		= REG_FIELD_ID(0x0010, 10, 13, 5, 0x4),
	.spkmono		= REG_FIELD_ID(0x0010, 9, 9, 5, 0x4),
	.micen			= REG_FIELD_ID(0x0010, 8, 8, 5, 0x4),
	.micmode		= REG_FIELD_ID(0x0010, 4, 7, 5, 0x4),
	.micmono		= REG_FIELD_ID(0x0010, 3, 3, 5, 0x4),
	.wssrc			= REG_FIELD_ID(0x0010, 2, 2, 5, 0x4),
	.bitwidth		= REG_FIELD_ID(0x0010, 0, 0, 5, 0x4),

	.rdma_dyncclk		= REG_FIELD_ID(0x6000, 12, 12, 4, 0x1000),
	.rdma_bursten		= REG_FIELD_ID(0x6000, 11, 11, 4, 0x1000),
	.rdma_wpscnt		= REG_FIELD_ID(0x6000, 8, 10, 4, 0x1000),
	.rdma_intf		= REG_FIELD_ID(0x6000, 4, 7, 4, 0x1000),
	.rdma_fifowm		= REG_FIELD_ID(0x6000, 1, 3, 4, 0x1000),
	.rdma_enable		= REG_FIELD_ID(0x6000, 0, 0, 4, 0x1000),

	.wrdma_dyncclk		= REG_FIELD_ID(0xB000, 12, 12, 4, 0x1000),
	.wrdma_bursten		= REG_FIELD_ID(0xB000, 11, 11, 4, 0x1000),
	.wrdma_wpscnt		= REG_FIELD_ID(0xB000, 8, 10, 4, 0x1000),
	.wrdma_intf		= REG_FIELD_ID(0xB000, 4, 7, 4, 0x1000),
	.wrdma_fifowm		= REG_FIELD_ID(0xB000, 1, 3, 4, 0x1000),
	.wrdma_enable		= REG_FIELD_ID(0xB000, 0, 0, 4, 0x1000),

	.dai_driver		= &ipq806x_lpass_cpu_dai_driver,
	.num_dai		= 1,
	.dai_osr_clk_names	= (const char *[]) {
+84 −73
Original line number Diff line number Diff line
@@ -12,15 +12,12 @@
	(v->i2sctrl_reg_base + (addr) + v->i2sctrl_reg_stride * (port))

#define LPAIF_I2SCTL_REG(v, port)	LPAIF_I2SCTL_REG_ADDR(v, 0x0, (port))
#define LPAIF_I2SCTL_LOOPBACK_MASK	0x8000
#define LPAIF_I2SCTL_LOOPBACK_SHIFT	15
#define LPAIF_I2SCTL_LOOPBACK_DISABLE	(0 << LPAIF_I2SCTL_LOOPBACK_SHIFT)
#define LPAIF_I2SCTL_LOOPBACK_ENABLE	(1 << LPAIF_I2SCTL_LOOPBACK_SHIFT)

#define LPAIF_I2SCTL_SPKEN_MASK		0x4000
#define LPAIF_I2SCTL_SPKEN_SHIFT	14
#define LPAIF_I2SCTL_SPKEN_DISABLE	(0 << LPAIF_I2SCTL_SPKEN_SHIFT)
#define LPAIF_I2SCTL_SPKEN_ENABLE	(1 << LPAIF_I2SCTL_SPKEN_SHIFT)
#define LPAIF_I2SCTL_LOOPBACK_DISABLE	0
#define LPAIF_I2SCTL_LOOPBACK_ENABLE	1

#define LPAIF_I2SCTL_SPKEN_DISABLE	0
#define LPAIF_I2SCTL_SPKEN_ENABLE	1

#define LPAIF_I2SCTL_MODE_NONE		0
#define LPAIF_I2SCTL_MODE_SD0		1
@@ -31,40 +28,37 @@
#define LPAIF_I2SCTL_MODE_QUAD23	6
#define LPAIF_I2SCTL_MODE_6CH		7
#define LPAIF_I2SCTL_MODE_8CH		8
#define LPAIF_I2SCTL_MODE_10CH		9
#define LPAIF_I2SCTL_MODE_12CH		10
#define LPAIF_I2SCTL_MODE_14CH		11
#define LPAIF_I2SCTL_MODE_16CH		12
#define LPAIF_I2SCTL_MODE_SD4		13
#define LPAIF_I2SCTL_MODE_SD5		14
#define LPAIF_I2SCTL_MODE_SD6		15
#define LPAIF_I2SCTL_MODE_SD7		16
#define LPAIF_I2SCTL_MODE_QUAD45	17
#define LPAIF_I2SCTL_MODE_QUAD47	18
#define LPAIF_I2SCTL_MODE_8CH_2		19

#define LPAIF_I2SCTL_SPKMODE_MASK	0x3C00
#define LPAIF_I2SCTL_SPKMODE_SHIFT	10
#define LPAIF_I2SCTL_SPKMODE(mode)	((mode) << LPAIF_I2SCTL_SPKMODE_SHIFT)
#define LPAIF_I2SCTL_SPKMODE(mode)	mode

#define LPAIF_I2SCTL_SPKMONO_MASK	0x0200
#define LPAIF_I2SCTL_SPKMONO_SHIFT	9
#define LPAIF_I2SCTL_SPKMONO_STEREO	(0 << LPAIF_I2SCTL_SPKMONO_SHIFT)
#define LPAIF_I2SCTL_SPKMONO_MONO	(1 << LPAIF_I2SCTL_SPKMONO_SHIFT)
#define LPAIF_I2SCTL_SPKMONO_STEREO	0
#define LPAIF_I2SCTL_SPKMONO_MONO	1

#define LPAIF_I2SCTL_MICEN_MASK		GENMASK(8, 8)
#define LPAIF_I2SCTL_MICEN_SHIFT	8
#define LPAIF_I2SCTL_MICEN_DISABLE	(0 << LPAIF_I2SCTL_MICEN_SHIFT)
#define LPAIF_I2SCTL_MICEN_ENABLE	(1 << LPAIF_I2SCTL_MICEN_SHIFT)
#define LPAIF_I2SCTL_MICEN_DISABLE	0
#define LPAIF_I2SCTL_MICEN_ENABLE	1

#define LPAIF_I2SCTL_MICMODE_MASK	GENMASK(7, 4)
#define LPAIF_I2SCTL_MICMODE_SHIFT	4
#define LPAIF_I2SCTL_MICMODE(mode)	((mode) << LPAIF_I2SCTL_MICMODE_SHIFT)
#define LPAIF_I2SCTL_MICMODE(mode)	mode

#define LPAIF_I2SCTL_MIMONO_MASK	GENMASK(3, 3)
#define LPAIF_I2SCTL_MICMONO_SHIFT	3
#define LPAIF_I2SCTL_MICMONO_STEREO	(0 << LPAIF_I2SCTL_MICMONO_SHIFT)
#define LPAIF_I2SCTL_MICMONO_MONO	(1 << LPAIF_I2SCTL_MICMONO_SHIFT)
#define LPAIF_I2SCTL_MICMONO_STEREO	0
#define LPAIF_I2SCTL_MICMONO_MONO	1

#define LPAIF_I2SCTL_WSSRC_MASK		0x0004
#define LPAIF_I2SCTL_WSSRC_SHIFT	2
#define LPAIF_I2SCTL_WSSRC_INTERNAL	(0 << LPAIF_I2SCTL_WSSRC_SHIFT)
#define LPAIF_I2SCTL_WSSRC_EXTERNAL	(1 << LPAIF_I2SCTL_WSSRC_SHIFT)
#define LPAIF_I2SCTL_WSSRC_INTERNAL	0
#define LPAIF_I2SCTL_WSSRC_EXTERNAL	1

#define LPAIF_I2SCTL_BITWIDTH_MASK	0x0003
#define LPAIF_I2SCTL_BITWIDTH_SHIFT	0
#define LPAIF_I2SCTL_BITWIDTH_16	(0 << LPAIF_I2SCTL_BITWIDTH_SHIFT)
#define LPAIF_I2SCTL_BITWIDTH_24	(1 << LPAIF_I2SCTL_BITWIDTH_SHIFT)
#define LPAIF_I2SCTL_BITWIDTH_32	(2 << LPAIF_I2SCTL_BITWIDTH_SHIFT)
#define LPAIF_I2SCTL_BITWIDTH_16	0
#define LPAIF_I2SCTL_BITWIDTH_24	1
#define LPAIF_I2SCTL_BITWIDTH_32	2

/* LPAIF IRQ */
#define LPAIF_IRQ_REG_ADDR(v, addr, port) \
@@ -121,42 +115,59 @@
#define	LPAIF_DMAPER_REG(v, chan, dir) __LPAIF_DMA_REG(v, chan, dir, PER)
#define	LPAIF_DMAPERCNT_REG(v, chan, dir) __LPAIF_DMA_REG(v, chan, dir, PERCNT)

#define LPAIF_DMACTL_BURSTEN_MASK	0x800
#define LPAIF_DMACTL_BURSTEN_SHIFT	11
#define LPAIF_DMACTL_BURSTEN_SINGLE	(0 << LPAIF_DMACTL_BURSTEN_SHIFT)
#define LPAIF_DMACTL_BURSTEN_INCR4	(1 << LPAIF_DMACTL_BURSTEN_SHIFT)

#define LPAIF_DMACTL_WPSCNT_MASK	0x700
#define LPAIF_DMACTL_WPSCNT_SHIFT	8
#define LPAIF_DMACTL_WPSCNT_ONE	(0 << LPAIF_DMACTL_WPSCNT_SHIFT)
#define LPAIF_DMACTL_WPSCNT_TWO	(1 << LPAIF_DMACTL_WPSCNT_SHIFT)
#define LPAIF_DMACTL_WPSCNT_THREE	(2 << LPAIF_DMACTL_WPSCNT_SHIFT)
#define LPAIF_DMACTL_WPSCNT_FOUR	(3 << LPAIF_DMACTL_WPSCNT_SHIFT)
#define LPAIF_DMACTL_WPSCNT_SIX	(5 << LPAIF_DMACTL_WPSCNT_SHIFT)
#define LPAIF_DMACTL_WPSCNT_EIGHT	(7 << LPAIF_DMACTL_WPSCNT_SHIFT)

#define LPAIF_DMACTL_AUDINTF_MASK	0x0F0
#define LPAIF_DMACTL_AUDINTF_SHIFT	4
#define LPAIF_DMACTL_AUDINTF(id)	(id << LPAIF_DMACTL_AUDINTF_SHIFT)

#define LPAIF_DMACTL_FIFOWM_MASK	0x00E
#define LPAIF_DMACTL_FIFOWM_SHIFT	1
#define LPAIF_DMACTL_FIFOWM_1		(0 << LPAIF_DMACTL_FIFOWM_SHIFT)
#define LPAIF_DMACTL_FIFOWM_2		(1 << LPAIF_DMACTL_FIFOWM_SHIFT)
#define LPAIF_DMACTL_FIFOWM_3		(2 << LPAIF_DMACTL_FIFOWM_SHIFT)
#define LPAIF_DMACTL_FIFOWM_4		(3 << LPAIF_DMACTL_FIFOWM_SHIFT)
#define LPAIF_DMACTL_FIFOWM_5		(4 << LPAIF_DMACTL_FIFOWM_SHIFT)
#define LPAIF_DMACTL_FIFOWM_6		(5 << LPAIF_DMACTL_FIFOWM_SHIFT)
#define LPAIF_DMACTL_FIFOWM_7		(6 << LPAIF_DMACTL_FIFOWM_SHIFT)
#define LPAIF_DMACTL_FIFOWM_8		(7 << LPAIF_DMACTL_FIFOWM_SHIFT)

#define LPAIF_DMACTL_ENABLE_MASK	0x1
#define LPAIF_DMACTL_ENABLE_SHIFT	0
#define LPAIF_DMACTL_ENABLE_OFF	(0 << LPAIF_DMACTL_ENABLE_SHIFT)
#define LPAIF_DMACTL_ENABLE_ON		(1 << LPAIF_DMACTL_ENABLE_SHIFT)

#define LPAIF_DMACTL_DYNCLK_MASK	BIT(12)
#define LPAIF_DMACTL_DYNCLK_SHIFT	12
#define LPAIF_DMACTL_DYNCLK_OFF	(0 << LPAIF_DMACTL_DYNCLK_SHIFT)
#define LPAIF_DMACTL_DYNCLK_ON		(1 << LPAIF_DMACTL_DYNCLK_SHIFT)
#define LPAIF_DMACTL_BURSTEN_SINGLE	0
#define LPAIF_DMACTL_BURSTEN_INCR4	1

#define LPAIF_DMACTL_WPSCNT_ONE		0
#define LPAIF_DMACTL_WPSCNT_TWO		1
#define LPAIF_DMACTL_WPSCNT_THREE	2
#define LPAIF_DMACTL_WPSCNT_FOUR	3
#define LPAIF_DMACTL_WPSCNT_SIX		5
#define LPAIF_DMACTL_WPSCNT_EIGHT	7
#define LPAIF_DMACTL_WPSCNT_TEN		9
#define LPAIF_DMACTL_WPSCNT_TWELVE	11
#define LPAIF_DMACTL_WPSCNT_FOURTEEN	13
#define LPAIF_DMACTL_WPSCNT_SIXTEEN	15

#define LPAIF_DMACTL_AUDINTF(id)	id

#define LPAIF_DMACTL_FIFOWM_1		0
#define LPAIF_DMACTL_FIFOWM_2		1
#define LPAIF_DMACTL_FIFOWM_3		2
#define LPAIF_DMACTL_FIFOWM_4		3
#define LPAIF_DMACTL_FIFOWM_5		4
#define LPAIF_DMACTL_FIFOWM_6		5
#define LPAIF_DMACTL_FIFOWM_7		6
#define LPAIF_DMACTL_FIFOWM_8		7
#define LPAIF_DMACTL_FIFOWM_9		8
#define LPAIF_DMACTL_FIFOWM_10		9
#define LPAIF_DMACTL_FIFOWM_11		10
#define LPAIF_DMACTL_FIFOWM_12		11
#define LPAIF_DMACTL_FIFOWM_13		12
#define LPAIF_DMACTL_FIFOWM_14		13
#define LPAIF_DMACTL_FIFOWM_15		14
#define LPAIF_DMACTL_FIFOWM_16		15
#define LPAIF_DMACTL_FIFOWM_17		16
#define LPAIF_DMACTL_FIFOWM_18		17
#define LPAIF_DMACTL_FIFOWM_19		18
#define LPAIF_DMACTL_FIFOWM_20		19
#define LPAIF_DMACTL_FIFOWM_21		20
#define LPAIF_DMACTL_FIFOWM_22		21
#define LPAIF_DMACTL_FIFOWM_23		22
#define LPAIF_DMACTL_FIFOWM_24		23
#define LPAIF_DMACTL_FIFOWM_25		24
#define LPAIF_DMACTL_FIFOWM_26		25
#define LPAIF_DMACTL_FIFOWM_27		26
#define LPAIF_DMACTL_FIFOWM_28		27
#define LPAIF_DMACTL_FIFOWM_29		28
#define LPAIF_DMACTL_FIFOWM_30		29
#define LPAIF_DMACTL_FIFOWM_31		30
#define LPAIF_DMACTL_FIFOWM_32		31

#define LPAIF_DMACTL_ENABLE_OFF		0
#define LPAIF_DMACTL_ENABLE_ON		1

#define LPAIF_DMACTL_DYNCLK_OFF		0
#define LPAIF_DMACTL_DYNCLK_ON		1

#endif /* __LPASS_LPAIF_REG_H__ */
+115 −30
Original line number Diff line number Diff line
@@ -50,6 +50,53 @@ static const struct snd_pcm_hardware lpass_platform_pcm_hardware = {
	.fifo_size		=	0,
};

static int lpass_platform_alloc_dmactl_fields(struct device *dev,
					 struct regmap *map)
{
	struct lpass_data *drvdata = dev_get_drvdata(dev);
	struct lpass_variant *v = drvdata->variant;
	struct lpaif_dmactl *rd_dmactl, *wr_dmactl;

	drvdata->rd_dmactl = devm_kzalloc(dev, sizeof(struct lpaif_dmactl),
					  GFP_KERNEL);
	if (drvdata->rd_dmactl == NULL)
		return -ENOMEM;

	drvdata->wr_dmactl = devm_kzalloc(dev, sizeof(struct lpaif_dmactl),
					  GFP_KERNEL);
	if (drvdata->wr_dmactl == NULL)
		return -ENOMEM;

	rd_dmactl = drvdata->rd_dmactl;
	wr_dmactl = drvdata->wr_dmactl;

	rd_dmactl->bursten = devm_regmap_field_alloc(dev, map, v->rdma_bursten);
	rd_dmactl->wpscnt = devm_regmap_field_alloc(dev, map, v->rdma_wpscnt);
	rd_dmactl->fifowm = devm_regmap_field_alloc(dev, map, v->rdma_fifowm);
	rd_dmactl->intf = devm_regmap_field_alloc(dev, map, v->rdma_intf);
	rd_dmactl->enable = devm_regmap_field_alloc(dev, map, v->rdma_enable);
	rd_dmactl->dyncclk = devm_regmap_field_alloc(dev, map, v->rdma_dyncclk);

	if (IS_ERR(rd_dmactl->bursten) || IS_ERR(rd_dmactl->wpscnt) ||
	    IS_ERR(rd_dmactl->fifowm) || IS_ERR(rd_dmactl->intf) ||
	    IS_ERR(rd_dmactl->enable) || IS_ERR(rd_dmactl->dyncclk))
		return -EINVAL;

	wr_dmactl->bursten = devm_regmap_field_alloc(dev, map, v->wrdma_bursten);
	wr_dmactl->wpscnt = devm_regmap_field_alloc(dev, map, v->wrdma_wpscnt);
	wr_dmactl->fifowm = devm_regmap_field_alloc(dev, map, v->wrdma_fifowm);
	wr_dmactl->intf = devm_regmap_field_alloc(dev, map, v->wrdma_intf);
	wr_dmactl->enable = devm_regmap_field_alloc(dev, map, v->wrdma_enable);
	wr_dmactl->dyncclk = devm_regmap_field_alloc(dev, map, v->wrdma_dyncclk);

	if (IS_ERR(wr_dmactl->bursten) || IS_ERR(wr_dmactl->wpscnt) ||
	    IS_ERR(wr_dmactl->fifowm) || IS_ERR(wr_dmactl->intf) ||
	    IS_ERR(wr_dmactl->enable) || IS_ERR(wr_dmactl->dyncclk))
		return -EINVAL;

	return 0;
}

static int lpass_platform_pcmops_open(struct snd_soc_component *component,
				      struct snd_pcm_substream *substream)
{
@@ -134,11 +181,18 @@ static int lpass_platform_pcmops_hw_params(struct snd_soc_component *component,
	snd_pcm_format_t format = params_format(params);
	unsigned int channels = params_channels(params);
	unsigned int regval;
	int ch, dir = substream->stream;
	struct lpaif_dmactl *dmactl;
	int id, dir = substream->stream;
	int bitwidth;
	int ret, dma_port = pcm_data->i2s_port + v->dmactl_audif_start;

	ch = pcm_data->dma_ch;
	if (dir ==  SNDRV_PCM_STREAM_PLAYBACK) {
		dmactl = drvdata->rd_dmactl;
		id = pcm_data->dma_ch;
	} else {
		dmactl = drvdata->wr_dmactl;
		id = pcm_data->dma_ch - v->wrdma_channel_start;
	}

	bitwidth = snd_pcm_format_width(format);
	if (bitwidth < 0) {
@@ -147,25 +201,39 @@ static int lpass_platform_pcmops_hw_params(struct snd_soc_component *component,
		return bitwidth;
	}

	regval = LPAIF_DMACTL_BURSTEN_INCR4 |
			LPAIF_DMACTL_AUDINTF(dma_port) |
			LPAIF_DMACTL_FIFOWM_8;
	ret = regmap_fields_write(dmactl->bursten, id, LPAIF_DMACTL_BURSTEN_INCR4);
	if (ret) {
		dev_err(soc_runtime->dev, "error updating bursten field: %d\n", ret);
		return ret;
	}

	regmap_fields_write(dmactl->fifowm, id, LPAIF_DMACTL_FIFOWM_8);
	if (ret) {
		dev_err(soc_runtime->dev, "error updating fifowm field: %d\n", ret);
		return ret;
	}

	regmap_fields_write(dmactl->intf, id, LPAIF_DMACTL_AUDINTF(dma_port));
	if (ret) {
		dev_err(soc_runtime->dev, "error updating audintf field: %d\n", ret);
		return ret;
	}

	switch (bitwidth) {
	case 16:
		switch (channels) {
		case 1:
		case 2:
			regval |= LPAIF_DMACTL_WPSCNT_ONE;
			regval = LPAIF_DMACTL_WPSCNT_ONE;
			break;
		case 4:
			regval |= LPAIF_DMACTL_WPSCNT_TWO;
			regval = LPAIF_DMACTL_WPSCNT_TWO;
			break;
		case 6:
			regval |= LPAIF_DMACTL_WPSCNT_THREE;
			regval = LPAIF_DMACTL_WPSCNT_THREE;
			break;
		case 8:
			regval |= LPAIF_DMACTL_WPSCNT_FOUR;
			regval = LPAIF_DMACTL_WPSCNT_FOUR;
			break;
		default:
			dev_err(soc_runtime->dev,
@@ -178,19 +246,19 @@ static int lpass_platform_pcmops_hw_params(struct snd_soc_component *component,
	case 32:
		switch (channels) {
		case 1:
			regval |= LPAIF_DMACTL_WPSCNT_ONE;
			regval = LPAIF_DMACTL_WPSCNT_ONE;
			break;
		case 2:
			regval |= LPAIF_DMACTL_WPSCNT_TWO;
			regval = LPAIF_DMACTL_WPSCNT_TWO;
			break;
		case 4:
			regval |= LPAIF_DMACTL_WPSCNT_FOUR;
			regval = LPAIF_DMACTL_WPSCNT_FOUR;
			break;
		case 6:
			regval |= LPAIF_DMACTL_WPSCNT_SIX;
			regval = LPAIF_DMACTL_WPSCNT_SIX;
			break;
		case 8:
			regval |= LPAIF_DMACTL_WPSCNT_EIGHT;
			regval = LPAIF_DMACTL_WPSCNT_EIGHT;
			break;
		default:
			dev_err(soc_runtime->dev,
@@ -205,10 +273,9 @@ static int lpass_platform_pcmops_hw_params(struct snd_soc_component *component,
		return -EINVAL;
	}

	ret = regmap_write(drvdata->lpaif_map,
			LPAIF_DMACTL_REG(v, ch, dir), regval);
	ret = regmap_fields_write(dmactl->wpscnt, id, regval);
	if (ret) {
		dev_err(soc_runtime->dev, "error writing to rdmactl reg: %d\n",
		dev_err(soc_runtime->dev, "error writing to dmactl reg: %d\n",
			ret);
		return ret;
	}
@@ -245,9 +312,17 @@ static int lpass_platform_pcmops_prepare(struct snd_soc_component *component,
	struct snd_pcm_runtime *rt = substream->runtime;
	struct lpass_pcm_data *pcm_data = rt->private_data;
	struct lpass_variant *v = drvdata->variant;
	int ret, ch, dir = substream->stream;
	struct lpaif_dmactl *dmactl;
	int ret, id, ch, dir = substream->stream;

	ch = pcm_data->dma_ch;
	if (dir ==  SNDRV_PCM_STREAM_PLAYBACK) {
		dmactl = drvdata->rd_dmactl;
		id = pcm_data->dma_ch;
	} else {
		dmactl = drvdata->wr_dmactl;
		id = pcm_data->dma_ch - v->wrdma_channel_start;
	}

	ret = regmap_write(drvdata->lpaif_map,
			LPAIF_DMABASE_REG(v, ch, dir),
@@ -276,9 +351,7 @@ static int lpass_platform_pcmops_prepare(struct snd_soc_component *component,
		return ret;
	}

	ret = regmap_update_bits(drvdata->lpaif_map,
			LPAIF_DMACTL_REG(v, ch, dir),
			LPAIF_DMACTL_ENABLE_MASK, LPAIF_DMACTL_ENABLE_ON);
	ret = regmap_fields_write(dmactl->enable, id, LPAIF_DMACTL_ENABLE_ON);
	if (ret) {
		dev_err(soc_runtime->dev, "error writing to rdmactl reg: %d\n",
			ret);
@@ -297,9 +370,18 @@ static int lpass_platform_pcmops_trigger(struct snd_soc_component *component,
	struct snd_pcm_runtime *rt = substream->runtime;
	struct lpass_pcm_data *pcm_data = rt->private_data;
	struct lpass_variant *v = drvdata->variant;
	int ret, ch, dir = substream->stream;
	struct lpaif_dmactl *dmactl;
	int ret, ch, id;
	int dir = substream->stream;

	ch = pcm_data->dma_ch;
	if (dir ==  SNDRV_PCM_STREAM_PLAYBACK) {
		dmactl = drvdata->rd_dmactl;
		id = pcm_data->dma_ch;
	} else {
		dmactl = drvdata->wr_dmactl;
		id = pcm_data->dma_ch - v->wrdma_channel_start;
	}

	switch (cmd) {
	case SNDRV_PCM_TRIGGER_START:
@@ -325,9 +407,7 @@ static int lpass_platform_pcmops_trigger(struct snd_soc_component *component,
			return ret;
		}

		ret = regmap_update_bits(drvdata->lpaif_map,
				LPAIF_DMACTL_REG(v, ch, dir),
				LPAIF_DMACTL_ENABLE_MASK,
		ret = regmap_fields_write(dmactl->enable, id,
					 LPAIF_DMACTL_ENABLE_ON);
		if (ret) {
			dev_err(soc_runtime->dev,
@@ -338,9 +418,7 @@ static int lpass_platform_pcmops_trigger(struct snd_soc_component *component,
	case SNDRV_PCM_TRIGGER_STOP:
	case SNDRV_PCM_TRIGGER_SUSPEND:
	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
		ret = regmap_update_bits(drvdata->lpaif_map,
				LPAIF_DMACTL_REG(v, ch, dir),
				LPAIF_DMACTL_ENABLE_MASK,
		ret = regmap_fields_write(dmactl->enable, id,
					 LPAIF_DMACTL_ENABLE_OFF);
		if (ret) {
			dev_err(soc_runtime->dev,
@@ -580,6 +658,13 @@ int asoc_qcom_lpass_platform_register(struct platform_device *pdev)
		return ret;
	}

	ret = lpass_platform_alloc_dmactl_fields(&pdev->dev,
						 drvdata->lpaif_map);
	if (ret) {
		dev_err(&pdev->dev,
			"error initializing dmactl fields: %d\n", ret);
		return ret;
	}

	return devm_snd_soc_register_component(&pdev->dev,
			&lpass_component_driver, NULL, 0);
Loading