summaryrefslogtreecommitdiffstats
path: root/sound/soc/qcom/lpass-platform.c
diff options
context:
space:
mode:
authorRohit kumar <rohitkr@codeaurora.org>2020-08-14 16:23:01 +0530
committerMark Brown <broonie@kernel.org>2020-08-17 14:39:29 +0100
commitb5022a36d28f6a99c1a57f54246e8b566cf094d5 (patch)
treeda5450fe62bba1d1b788fd727c4e79c1a714c2a8 /sound/soc/qcom/lpass-platform.c
parent5fd188215d4eb52703600d8986b22311099a5940 (diff)
downloadlinux-b5022a36d28f6a99c1a57f54246e8b566cf094d5.tar.bz2
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: Rohit kumar <rohitkr@codeaurora.org> Link: https://lore.kernel.org/r/1597402388-14112-6-git-send-email-rohitkr@codeaurora.org Signed-off-by: Mark Brown <broonie@kernel.org>
Diffstat (limited to 'sound/soc/qcom/lpass-platform.c')
-rw-r--r--sound/soc/qcom/lpass-platform.c145
1 files changed, 115 insertions, 30 deletions
diff --git a/sound/soc/qcom/lpass-platform.c b/sound/soc/qcom/lpass-platform.c
index 315feda414d9..35aead1bfdf8 100644
--- a/sound/soc/qcom/lpass-platform.c
+++ b/sound/soc/qcom/lpass-platform.c
@@ -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,10 +407,8 @@ 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,
- 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);
@@ -338,10 +418,8 @@ 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,
- LPAIF_DMACTL_ENABLE_OFF);
+ ret = regmap_fields_write(dmactl->enable, id,
+ LPAIF_DMACTL_ENABLE_OFF);
if (ret) {
dev_err(soc_runtime->dev,
"error writing to rdmactl reg: %d\n", ret);
@@ -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);