Skip to content

Commit

Permalink
ASoC: qcom: lpass: Use regmap_field for i2sctl and dmactl registers
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Rohit kumar authored and Mark Brown committed Aug 17, 2020
1 parent 5fd1882 commit b5022a3
Show file tree
Hide file tree
Showing 6 changed files with 407 additions and 152 deletions.
24 changes: 24 additions & 0 deletions sound/soc/qcom/lpass-apq8016.c
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down
156 changes: 107 additions & 49 deletions sound/soc/qcom/lpass-cpu.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
{
Expand Down Expand Up @@ -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);
Expand All @@ -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");
Expand Down Expand Up @@ -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",
Expand Down Expand Up @@ -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;
} else {
val = LPAIF_I2SCTL_MICEN_ENABLE;
mask = LPAIF_I2SCTL_MICEN_MASK;
ret = regmap_fields_write(i2sctl->spken, id,
LPAIF_I2SCTL_SPKEN_ENABLE);
} else {
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;
}
Expand All @@ -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);
Expand All @@ -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);
Expand Down Expand Up @@ -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,
Expand Down
24 changes: 24 additions & 0 deletions sound/soc/qcom/lpass-ipq806x.c
Original file line number Diff line number Diff line change
Expand Up @@ -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 *[]) {
Expand Down
Loading

0 comments on commit b5022a3

Please sign in to comment.