mirror of
https://github.com/torvalds/linux.git
synced 2024-12-13 22:53:20 +00:00
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>
This commit is contained in:
parent
5fd188215d
commit
b5022a36d2
@ -240,6 +240,30 @@ static struct lpass_variant apq8016_data = {
|
|||||||
.wrdma_reg_stride = 0x1000,
|
.wrdma_reg_stride = 0x1000,
|
||||||
.wrdma_channel_start = 5,
|
.wrdma_channel_start = 5,
|
||||||
.wrdma_channels = 2,
|
.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*[]) {
|
.clk_name = (const char*[]) {
|
||||||
"pcnoc-mport-clk",
|
"pcnoc-mport-clk",
|
||||||
"pcnoc-sway-clk",
|
"pcnoc-sway-clk",
|
||||||
|
@ -29,6 +29,32 @@
|
|||||||
#define LPASS_CPU_I2S_SD0_1_2_MASK GENMASK(2, 0)
|
#define LPASS_CPU_I2S_SD0_1_2_MASK GENMASK(2, 0)
|
||||||
#define LPASS_CPU_I2S_SD0_1_2_3_MASK GENMASK(3, 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,
|
static int lpass_cpu_daiops_set_sysclk(struct snd_soc_dai *dai, int clk_id,
|
||||||
unsigned int freq, int dir)
|
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 snd_pcm_hw_params *params, struct snd_soc_dai *dai)
|
||||||
{
|
{
|
||||||
struct lpass_data *drvdata = snd_soc_dai_get_drvdata(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);
|
snd_pcm_format_t format = params_format(params);
|
||||||
unsigned int channels = params_channels(params);
|
unsigned int channels = params_channels(params);
|
||||||
unsigned int rate = params_rate(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;
|
return bitwidth;
|
||||||
}
|
}
|
||||||
|
|
||||||
regval = LPAIF_I2SCTL_LOOPBACK_DISABLE |
|
ret = regmap_fields_write(i2sctl->loopback, id,
|
||||||
LPAIF_I2SCTL_WSSRC_INTERNAL;
|
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) {
|
switch (bitwidth) {
|
||||||
case 16:
|
case 16:
|
||||||
regval |= LPAIF_I2SCTL_BITWIDTH_16;
|
regval = LPAIF_I2SCTL_BITWIDTH_16;
|
||||||
break;
|
break;
|
||||||
case 24:
|
case 24:
|
||||||
regval |= LPAIF_I2SCTL_BITWIDTH_24;
|
regval = LPAIF_I2SCTL_BITWIDTH_24;
|
||||||
break;
|
break;
|
||||||
case 32:
|
case 32:
|
||||||
regval |= LPAIF_I2SCTL_BITWIDTH_32;
|
regval = LPAIF_I2SCTL_BITWIDTH_32;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
dev_err(dai->dev, "invalid bitwidth given: %d\n", bitwidth);
|
dev_err(dai->dev, "invalid bitwidth given: %d\n", bitwidth);
|
||||||
return -EINVAL;
|
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)
|
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
|
||||||
mode = drvdata->mi2s_playback_sd_mode[dai->driver->id];
|
mode = drvdata->mi2s_playback_sd_mode[id];
|
||||||
else
|
else
|
||||||
mode = drvdata->mi2s_capture_sd_mode[dai->driver->id];
|
mode = drvdata->mi2s_capture_sd_mode[id];
|
||||||
|
|
||||||
if (!mode) {
|
if (!mode) {
|
||||||
dev_err(dai->dev, "no line is assigned\n");
|
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) {
|
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)
|
if (channels >= 2)
|
||||||
regval |= LPAIF_I2SCTL_SPKMONO_STEREO;
|
ret = regmap_fields_write(i2sctl->spkmono, id,
|
||||||
|
LPAIF_I2SCTL_SPKMONO_STEREO);
|
||||||
else
|
else
|
||||||
regval |= LPAIF_I2SCTL_SPKMONO_MONO;
|
ret = regmap_fields_write(i2sctl->spkmono, id,
|
||||||
|
LPAIF_I2SCTL_SPKMONO_MONO);
|
||||||
} else {
|
} 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)
|
if (channels >= 2)
|
||||||
regval |= LPAIF_I2SCTL_MICMONO_STEREO;
|
ret = regmap_fields_write(i2sctl->micmono, id,
|
||||||
|
LPAIF_I2SCTL_MICMONO_STEREO);
|
||||||
else
|
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) {
|
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;
|
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);
|
rate * bitwidth * 2);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
dev_err(dai->dev, "error setting mi2s bitclk to %u: %d\n",
|
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 snd_soc_dai *dai)
|
||||||
{
|
{
|
||||||
struct lpass_data *drvdata = snd_soc_dai_get_drvdata(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;
|
int ret;
|
||||||
unsigned int val, mask;
|
|
||||||
|
|
||||||
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
|
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
|
||||||
val = LPAIF_I2SCTL_SPKEN_ENABLE;
|
ret = regmap_fields_write(i2sctl->spken, id,
|
||||||
mask = LPAIF_I2SCTL_SPKEN_MASK;
|
LPAIF_I2SCTL_SPKEN_ENABLE);
|
||||||
} else {
|
} else {
|
||||||
val = LPAIF_I2SCTL_MICEN_ENABLE;
|
ret = regmap_fields_write(i2sctl->micen, id,
|
||||||
mask = LPAIF_I2SCTL_MICEN_MASK;
|
LPAIF_I2SCTL_MICEN_ENABLE);
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = regmap_update_bits(drvdata->lpaif_map,
|
|
||||||
LPAIF_I2SCTL_REG(drvdata->variant, dai->driver->id),
|
|
||||||
mask, val);
|
|
||||||
if (ret)
|
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;
|
return ret;
|
||||||
}
|
}
|
||||||
@ -252,25 +307,21 @@ static int lpass_cpu_daiops_trigger(struct snd_pcm_substream *substream,
|
|||||||
int cmd, struct snd_soc_dai *dai)
|
int cmd, struct snd_soc_dai *dai)
|
||||||
{
|
{
|
||||||
struct lpass_data *drvdata = snd_soc_dai_get_drvdata(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;
|
int ret = -EINVAL;
|
||||||
unsigned int val, mask;
|
|
||||||
|
|
||||||
switch (cmd) {
|
switch (cmd) {
|
||||||
case SNDRV_PCM_TRIGGER_START:
|
case SNDRV_PCM_TRIGGER_START:
|
||||||
case SNDRV_PCM_TRIGGER_RESUME:
|
case SNDRV_PCM_TRIGGER_RESUME:
|
||||||
case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
|
case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
|
||||||
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
|
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
|
||||||
val = LPAIF_I2SCTL_SPKEN_ENABLE;
|
ret = regmap_fields_write(i2sctl->spken, id,
|
||||||
mask = LPAIF_I2SCTL_SPKEN_MASK;
|
LPAIF_I2SCTL_SPKEN_ENABLE);
|
||||||
} else {
|
} else {
|
||||||
val = LPAIF_I2SCTL_MICEN_ENABLE;
|
ret = regmap_fields_write(i2sctl->micen, id,
|
||||||
mask = LPAIF_I2SCTL_MICEN_MASK;
|
LPAIF_I2SCTL_MICEN_ENABLE);
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = regmap_update_bits(drvdata->lpaif_map,
|
|
||||||
LPAIF_I2SCTL_REG(drvdata->variant,
|
|
||||||
dai->driver->id),
|
|
||||||
mask, val);
|
|
||||||
if (ret)
|
if (ret)
|
||||||
dev_err(dai->dev, "error writing to i2sctl reg: %d\n",
|
dev_err(dai->dev, "error writing to i2sctl reg: %d\n",
|
||||||
ret);
|
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_SUSPEND:
|
||||||
case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
|
case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
|
||||||
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
|
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
|
||||||
val = LPAIF_I2SCTL_SPKEN_DISABLE;
|
ret = regmap_fields_write(i2sctl->spken, id,
|
||||||
mask = LPAIF_I2SCTL_SPKEN_MASK;
|
LPAIF_I2SCTL_SPKEN_DISABLE);
|
||||||
} else {
|
} else {
|
||||||
val = LPAIF_I2SCTL_MICEN_DISABLE;
|
ret = regmap_fields_write(i2sctl->micen, id,
|
||||||
mask = LPAIF_I2SCTL_MICEN_MASK;
|
LPAIF_I2SCTL_MICEN_DISABLE);
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = regmap_update_bits(drvdata->lpaif_map,
|
|
||||||
LPAIF_I2SCTL_REG(drvdata->variant,
|
|
||||||
dai->driver->id),
|
|
||||||
mask, val);
|
|
||||||
if (ret)
|
if (ret)
|
||||||
dev_err(dai->dev, "error writing to i2sctl reg: %d\n",
|
dev_err(dai->dev, "error writing to i2sctl reg: %d\n",
|
||||||
ret);
|
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,
|
ret = devm_snd_soc_register_component(dev,
|
||||||
&lpass_cpu_comp_driver,
|
&lpass_cpu_comp_driver,
|
||||||
variant->dai_driver,
|
variant->dai_driver,
|
||||||
|
@ -123,6 +123,30 @@ static struct lpass_variant ipq806x_data = {
|
|||||||
.wrdma_reg_stride = 0x1000,
|
.wrdma_reg_stride = 0x1000,
|
||||||
.wrdma_channel_start = 5,
|
.wrdma_channel_start = 5,
|
||||||
.wrdma_channels = 4,
|
.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,
|
.dai_driver = &ipq806x_lpass_cpu_dai_driver,
|
||||||
.num_dai = 1,
|
.num_dai = 1,
|
||||||
.dai_osr_clk_names = (const char *[]) {
|
.dai_osr_clk_names = (const char *[]) {
|
||||||
|
@ -12,15 +12,12 @@
|
|||||||
(v->i2sctrl_reg_base + (addr) + v->i2sctrl_reg_stride * (port))
|
(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_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_LOOPBACK_DISABLE 0
|
||||||
#define LPAIF_I2SCTL_SPKEN_SHIFT 14
|
#define LPAIF_I2SCTL_LOOPBACK_ENABLE 1
|
||||||
#define LPAIF_I2SCTL_SPKEN_DISABLE (0 << LPAIF_I2SCTL_SPKEN_SHIFT)
|
|
||||||
#define LPAIF_I2SCTL_SPKEN_ENABLE (1 << LPAIF_I2SCTL_SPKEN_SHIFT)
|
#define LPAIF_I2SCTL_SPKEN_DISABLE 0
|
||||||
|
#define LPAIF_I2SCTL_SPKEN_ENABLE 1
|
||||||
|
|
||||||
#define LPAIF_I2SCTL_MODE_NONE 0
|
#define LPAIF_I2SCTL_MODE_NONE 0
|
||||||
#define LPAIF_I2SCTL_MODE_SD0 1
|
#define LPAIF_I2SCTL_MODE_SD0 1
|
||||||
@ -31,40 +28,37 @@
|
|||||||
#define LPAIF_I2SCTL_MODE_QUAD23 6
|
#define LPAIF_I2SCTL_MODE_QUAD23 6
|
||||||
#define LPAIF_I2SCTL_MODE_6CH 7
|
#define LPAIF_I2SCTL_MODE_6CH 7
|
||||||
#define LPAIF_I2SCTL_MODE_8CH 8
|
#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(mode) mode
|
||||||
#define LPAIF_I2SCTL_SPKMODE_SHIFT 10
|
|
||||||
#define LPAIF_I2SCTL_SPKMODE(mode) ((mode) << LPAIF_I2SCTL_SPKMODE_SHIFT)
|
|
||||||
|
|
||||||
#define LPAIF_I2SCTL_SPKMONO_MASK 0x0200
|
#define LPAIF_I2SCTL_SPKMONO_STEREO 0
|
||||||
#define LPAIF_I2SCTL_SPKMONO_SHIFT 9
|
#define LPAIF_I2SCTL_SPKMONO_MONO 1
|
||||||
#define LPAIF_I2SCTL_SPKMONO_STEREO (0 << LPAIF_I2SCTL_SPKMONO_SHIFT)
|
|
||||||
#define LPAIF_I2SCTL_SPKMONO_MONO (1 << LPAIF_I2SCTL_SPKMONO_SHIFT)
|
|
||||||
|
|
||||||
#define LPAIF_I2SCTL_MICEN_MASK GENMASK(8, 8)
|
#define LPAIF_I2SCTL_MICEN_DISABLE 0
|
||||||
#define LPAIF_I2SCTL_MICEN_SHIFT 8
|
#define LPAIF_I2SCTL_MICEN_ENABLE 1
|
||||||
#define LPAIF_I2SCTL_MICEN_DISABLE (0 << LPAIF_I2SCTL_MICEN_SHIFT)
|
|
||||||
#define LPAIF_I2SCTL_MICEN_ENABLE (1 << LPAIF_I2SCTL_MICEN_SHIFT)
|
|
||||||
|
|
||||||
#define LPAIF_I2SCTL_MICMODE_MASK GENMASK(7, 4)
|
#define LPAIF_I2SCTL_MICMODE(mode) mode
|
||||||
#define LPAIF_I2SCTL_MICMODE_SHIFT 4
|
|
||||||
#define LPAIF_I2SCTL_MICMODE(mode) ((mode) << LPAIF_I2SCTL_MICMODE_SHIFT)
|
|
||||||
|
|
||||||
#define LPAIF_I2SCTL_MIMONO_MASK GENMASK(3, 3)
|
#define LPAIF_I2SCTL_MICMONO_STEREO 0
|
||||||
#define LPAIF_I2SCTL_MICMONO_SHIFT 3
|
#define LPAIF_I2SCTL_MICMONO_MONO 1
|
||||||
#define LPAIF_I2SCTL_MICMONO_STEREO (0 << LPAIF_I2SCTL_MICMONO_SHIFT)
|
|
||||||
#define LPAIF_I2SCTL_MICMONO_MONO (1 << LPAIF_I2SCTL_MICMONO_SHIFT)
|
|
||||||
|
|
||||||
#define LPAIF_I2SCTL_WSSRC_MASK 0x0004
|
#define LPAIF_I2SCTL_WSSRC_INTERNAL 0
|
||||||
#define LPAIF_I2SCTL_WSSRC_SHIFT 2
|
#define LPAIF_I2SCTL_WSSRC_EXTERNAL 1
|
||||||
#define LPAIF_I2SCTL_WSSRC_INTERNAL (0 << LPAIF_I2SCTL_WSSRC_SHIFT)
|
|
||||||
#define LPAIF_I2SCTL_WSSRC_EXTERNAL (1 << LPAIF_I2SCTL_WSSRC_SHIFT)
|
|
||||||
|
|
||||||
#define LPAIF_I2SCTL_BITWIDTH_MASK 0x0003
|
#define LPAIF_I2SCTL_BITWIDTH_16 0
|
||||||
#define LPAIF_I2SCTL_BITWIDTH_SHIFT 0
|
#define LPAIF_I2SCTL_BITWIDTH_24 1
|
||||||
#define LPAIF_I2SCTL_BITWIDTH_16 (0 << LPAIF_I2SCTL_BITWIDTH_SHIFT)
|
#define LPAIF_I2SCTL_BITWIDTH_32 2
|
||||||
#define LPAIF_I2SCTL_BITWIDTH_24 (1 << LPAIF_I2SCTL_BITWIDTH_SHIFT)
|
|
||||||
#define LPAIF_I2SCTL_BITWIDTH_32 (2 << LPAIF_I2SCTL_BITWIDTH_SHIFT)
|
|
||||||
|
|
||||||
/* LPAIF IRQ */
|
/* LPAIF IRQ */
|
||||||
#define LPAIF_IRQ_REG_ADDR(v, addr, port) \
|
#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_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_DMAPERCNT_REG(v, chan, dir) __LPAIF_DMA_REG(v, chan, dir, PERCNT)
|
||||||
|
|
||||||
#define LPAIF_DMACTL_BURSTEN_MASK 0x800
|
#define LPAIF_DMACTL_BURSTEN_SINGLE 0
|
||||||
#define LPAIF_DMACTL_BURSTEN_SHIFT 11
|
#define LPAIF_DMACTL_BURSTEN_INCR4 1
|
||||||
#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_ONE 0
|
||||||
#define LPAIF_DMACTL_WPSCNT_SHIFT 8
|
#define LPAIF_DMACTL_WPSCNT_TWO 1
|
||||||
#define LPAIF_DMACTL_WPSCNT_ONE (0 << LPAIF_DMACTL_WPSCNT_SHIFT)
|
#define LPAIF_DMACTL_WPSCNT_THREE 2
|
||||||
#define LPAIF_DMACTL_WPSCNT_TWO (1 << LPAIF_DMACTL_WPSCNT_SHIFT)
|
#define LPAIF_DMACTL_WPSCNT_FOUR 3
|
||||||
#define LPAIF_DMACTL_WPSCNT_THREE (2 << LPAIF_DMACTL_WPSCNT_SHIFT)
|
#define LPAIF_DMACTL_WPSCNT_SIX 5
|
||||||
#define LPAIF_DMACTL_WPSCNT_FOUR (3 << LPAIF_DMACTL_WPSCNT_SHIFT)
|
#define LPAIF_DMACTL_WPSCNT_EIGHT 7
|
||||||
#define LPAIF_DMACTL_WPSCNT_SIX (5 << LPAIF_DMACTL_WPSCNT_SHIFT)
|
#define LPAIF_DMACTL_WPSCNT_TEN 9
|
||||||
#define LPAIF_DMACTL_WPSCNT_EIGHT (7 << LPAIF_DMACTL_WPSCNT_SHIFT)
|
#define LPAIF_DMACTL_WPSCNT_TWELVE 11
|
||||||
|
#define LPAIF_DMACTL_WPSCNT_FOURTEEN 13
|
||||||
|
#define LPAIF_DMACTL_WPSCNT_SIXTEEN 15
|
||||||
|
|
||||||
#define LPAIF_DMACTL_AUDINTF_MASK 0x0F0
|
#define LPAIF_DMACTL_AUDINTF(id) id
|
||||||
#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_1 0
|
||||||
#define LPAIF_DMACTL_FIFOWM_SHIFT 1
|
#define LPAIF_DMACTL_FIFOWM_2 1
|
||||||
#define LPAIF_DMACTL_FIFOWM_1 (0 << LPAIF_DMACTL_FIFOWM_SHIFT)
|
#define LPAIF_DMACTL_FIFOWM_3 2
|
||||||
#define LPAIF_DMACTL_FIFOWM_2 (1 << LPAIF_DMACTL_FIFOWM_SHIFT)
|
#define LPAIF_DMACTL_FIFOWM_4 3
|
||||||
#define LPAIF_DMACTL_FIFOWM_3 (2 << LPAIF_DMACTL_FIFOWM_SHIFT)
|
#define LPAIF_DMACTL_FIFOWM_5 4
|
||||||
#define LPAIF_DMACTL_FIFOWM_4 (3 << LPAIF_DMACTL_FIFOWM_SHIFT)
|
#define LPAIF_DMACTL_FIFOWM_6 5
|
||||||
#define LPAIF_DMACTL_FIFOWM_5 (4 << LPAIF_DMACTL_FIFOWM_SHIFT)
|
#define LPAIF_DMACTL_FIFOWM_7 6
|
||||||
#define LPAIF_DMACTL_FIFOWM_6 (5 << LPAIF_DMACTL_FIFOWM_SHIFT)
|
#define LPAIF_DMACTL_FIFOWM_8 7
|
||||||
#define LPAIF_DMACTL_FIFOWM_7 (6 << LPAIF_DMACTL_FIFOWM_SHIFT)
|
#define LPAIF_DMACTL_FIFOWM_9 8
|
||||||
#define LPAIF_DMACTL_FIFOWM_8 (7 << LPAIF_DMACTL_FIFOWM_SHIFT)
|
#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_MASK 0x1
|
#define LPAIF_DMACTL_ENABLE_OFF 0
|
||||||
#define LPAIF_DMACTL_ENABLE_SHIFT 0
|
#define LPAIF_DMACTL_ENABLE_ON 1
|
||||||
#define LPAIF_DMACTL_ENABLE_OFF (0 << LPAIF_DMACTL_ENABLE_SHIFT)
|
|
||||||
#define LPAIF_DMACTL_ENABLE_ON (1 << LPAIF_DMACTL_ENABLE_SHIFT)
|
#define LPAIF_DMACTL_DYNCLK_OFF 0
|
||||||
|
#define LPAIF_DMACTL_DYNCLK_ON 1
|
||||||
|
|
||||||
#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)
|
|
||||||
#endif /* __LPASS_LPAIF_REG_H__ */
|
#endif /* __LPASS_LPAIF_REG_H__ */
|
||||||
|
@ -50,6 +50,53 @@ static const struct snd_pcm_hardware lpass_platform_pcm_hardware = {
|
|||||||
.fifo_size = 0,
|
.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,
|
static int lpass_platform_pcmops_open(struct snd_soc_component *component,
|
||||||
struct snd_pcm_substream *substream)
|
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);
|
snd_pcm_format_t format = params_format(params);
|
||||||
unsigned int channels = params_channels(params);
|
unsigned int channels = params_channels(params);
|
||||||
unsigned int regval;
|
unsigned int regval;
|
||||||
int ch, dir = substream->stream;
|
struct lpaif_dmactl *dmactl;
|
||||||
|
int id, dir = substream->stream;
|
||||||
int bitwidth;
|
int bitwidth;
|
||||||
int ret, dma_port = pcm_data->i2s_port + v->dmactl_audif_start;
|
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);
|
bitwidth = snd_pcm_format_width(format);
|
||||||
if (bitwidth < 0) {
|
if (bitwidth < 0) {
|
||||||
@ -147,25 +201,39 @@ static int lpass_platform_pcmops_hw_params(struct snd_soc_component *component,
|
|||||||
return bitwidth;
|
return bitwidth;
|
||||||
}
|
}
|
||||||
|
|
||||||
regval = LPAIF_DMACTL_BURSTEN_INCR4 |
|
ret = regmap_fields_write(dmactl->bursten, id, LPAIF_DMACTL_BURSTEN_INCR4);
|
||||||
LPAIF_DMACTL_AUDINTF(dma_port) |
|
if (ret) {
|
||||||
LPAIF_DMACTL_FIFOWM_8;
|
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) {
|
switch (bitwidth) {
|
||||||
case 16:
|
case 16:
|
||||||
switch (channels) {
|
switch (channels) {
|
||||||
case 1:
|
case 1:
|
||||||
case 2:
|
case 2:
|
||||||
regval |= LPAIF_DMACTL_WPSCNT_ONE;
|
regval = LPAIF_DMACTL_WPSCNT_ONE;
|
||||||
break;
|
break;
|
||||||
case 4:
|
case 4:
|
||||||
regval |= LPAIF_DMACTL_WPSCNT_TWO;
|
regval = LPAIF_DMACTL_WPSCNT_TWO;
|
||||||
break;
|
break;
|
||||||
case 6:
|
case 6:
|
||||||
regval |= LPAIF_DMACTL_WPSCNT_THREE;
|
regval = LPAIF_DMACTL_WPSCNT_THREE;
|
||||||
break;
|
break;
|
||||||
case 8:
|
case 8:
|
||||||
regval |= LPAIF_DMACTL_WPSCNT_FOUR;
|
regval = LPAIF_DMACTL_WPSCNT_FOUR;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
dev_err(soc_runtime->dev,
|
dev_err(soc_runtime->dev,
|
||||||
@ -178,19 +246,19 @@ static int lpass_platform_pcmops_hw_params(struct snd_soc_component *component,
|
|||||||
case 32:
|
case 32:
|
||||||
switch (channels) {
|
switch (channels) {
|
||||||
case 1:
|
case 1:
|
||||||
regval |= LPAIF_DMACTL_WPSCNT_ONE;
|
regval = LPAIF_DMACTL_WPSCNT_ONE;
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
regval |= LPAIF_DMACTL_WPSCNT_TWO;
|
regval = LPAIF_DMACTL_WPSCNT_TWO;
|
||||||
break;
|
break;
|
||||||
case 4:
|
case 4:
|
||||||
regval |= LPAIF_DMACTL_WPSCNT_FOUR;
|
regval = LPAIF_DMACTL_WPSCNT_FOUR;
|
||||||
break;
|
break;
|
||||||
case 6:
|
case 6:
|
||||||
regval |= LPAIF_DMACTL_WPSCNT_SIX;
|
regval = LPAIF_DMACTL_WPSCNT_SIX;
|
||||||
break;
|
break;
|
||||||
case 8:
|
case 8:
|
||||||
regval |= LPAIF_DMACTL_WPSCNT_EIGHT;
|
regval = LPAIF_DMACTL_WPSCNT_EIGHT;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
dev_err(soc_runtime->dev,
|
dev_err(soc_runtime->dev,
|
||||||
@ -205,10 +273,9 @@ static int lpass_platform_pcmops_hw_params(struct snd_soc_component *component,
|
|||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = regmap_write(drvdata->lpaif_map,
|
ret = regmap_fields_write(dmactl->wpscnt, id, regval);
|
||||||
LPAIF_DMACTL_REG(v, ch, dir), regval);
|
|
||||||
if (ret) {
|
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);
|
ret);
|
||||||
return 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 snd_pcm_runtime *rt = substream->runtime;
|
||||||
struct lpass_pcm_data *pcm_data = rt->private_data;
|
struct lpass_pcm_data *pcm_data = rt->private_data;
|
||||||
struct lpass_variant *v = drvdata->variant;
|
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;
|
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,
|
ret = regmap_write(drvdata->lpaif_map,
|
||||||
LPAIF_DMABASE_REG(v, ch, dir),
|
LPAIF_DMABASE_REG(v, ch, dir),
|
||||||
@ -276,9 +351,7 @@ static int lpass_platform_pcmops_prepare(struct snd_soc_component *component,
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = regmap_update_bits(drvdata->lpaif_map,
|
ret = regmap_fields_write(dmactl->enable, id, LPAIF_DMACTL_ENABLE_ON);
|
||||||
LPAIF_DMACTL_REG(v, ch, dir),
|
|
||||||
LPAIF_DMACTL_ENABLE_MASK, LPAIF_DMACTL_ENABLE_ON);
|
|
||||||
if (ret) {
|
if (ret) {
|
||||||
dev_err(soc_runtime->dev, "error writing to rdmactl reg: %d\n",
|
dev_err(soc_runtime->dev, "error writing to rdmactl reg: %d\n",
|
||||||
ret);
|
ret);
|
||||||
@ -297,9 +370,18 @@ static int lpass_platform_pcmops_trigger(struct snd_soc_component *component,
|
|||||||
struct snd_pcm_runtime *rt = substream->runtime;
|
struct snd_pcm_runtime *rt = substream->runtime;
|
||||||
struct lpass_pcm_data *pcm_data = rt->private_data;
|
struct lpass_pcm_data *pcm_data = rt->private_data;
|
||||||
struct lpass_variant *v = drvdata->variant;
|
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;
|
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) {
|
switch (cmd) {
|
||||||
case SNDRV_PCM_TRIGGER_START:
|
case SNDRV_PCM_TRIGGER_START:
|
||||||
@ -325,9 +407,7 @@ static int lpass_platform_pcmops_trigger(struct snd_soc_component *component,
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = regmap_update_bits(drvdata->lpaif_map,
|
ret = regmap_fields_write(dmactl->enable, id,
|
||||||
LPAIF_DMACTL_REG(v, ch, dir),
|
|
||||||
LPAIF_DMACTL_ENABLE_MASK,
|
|
||||||
LPAIF_DMACTL_ENABLE_ON);
|
LPAIF_DMACTL_ENABLE_ON);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
dev_err(soc_runtime->dev,
|
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_STOP:
|
||||||
case SNDRV_PCM_TRIGGER_SUSPEND:
|
case SNDRV_PCM_TRIGGER_SUSPEND:
|
||||||
case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
|
case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
|
||||||
ret = regmap_update_bits(drvdata->lpaif_map,
|
ret = regmap_fields_write(dmactl->enable, id,
|
||||||
LPAIF_DMACTL_REG(v, ch, dir),
|
|
||||||
LPAIF_DMACTL_ENABLE_MASK,
|
|
||||||
LPAIF_DMACTL_ENABLE_OFF);
|
LPAIF_DMACTL_ENABLE_OFF);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
dev_err(soc_runtime->dev,
|
dev_err(soc_runtime->dev,
|
||||||
@ -580,6 +658,13 @@ int asoc_qcom_lpass_platform_register(struct platform_device *pdev)
|
|||||||
return ret;
|
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,
|
return devm_snd_soc_register_component(&pdev->dev,
|
||||||
&lpass_component_driver, NULL, 0);
|
&lpass_component_driver, NULL, 0);
|
||||||
|
@ -17,6 +17,28 @@
|
|||||||
#define LPASS_MAX_MI2S_PORTS (8)
|
#define LPASS_MAX_MI2S_PORTS (8)
|
||||||
#define LPASS_MAX_DMA_CHANNELS (8)
|
#define LPASS_MAX_DMA_CHANNELS (8)
|
||||||
|
|
||||||
|
struct lpaif_i2sctl {
|
||||||
|
struct regmap_field *loopback;
|
||||||
|
struct regmap_field *spken;
|
||||||
|
struct regmap_field *spkmode;
|
||||||
|
struct regmap_field *spkmono;
|
||||||
|
struct regmap_field *micen;
|
||||||
|
struct regmap_field *micmode;
|
||||||
|
struct regmap_field *micmono;
|
||||||
|
struct regmap_field *wssrc;
|
||||||
|
struct regmap_field *bitwidth;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
struct lpaif_dmactl {
|
||||||
|
struct regmap_field *bursten;
|
||||||
|
struct regmap_field *wpscnt;
|
||||||
|
struct regmap_field *intf;
|
||||||
|
struct regmap_field *fifowm;
|
||||||
|
struct regmap_field *enable;
|
||||||
|
struct regmap_field *dyncclk;
|
||||||
|
};
|
||||||
|
|
||||||
/* Both the CPU DAI and platform drivers will access this data */
|
/* Both the CPU DAI and platform drivers will access this data */
|
||||||
struct lpass_data {
|
struct lpass_data {
|
||||||
|
|
||||||
@ -55,6 +77,10 @@ struct lpass_data {
|
|||||||
struct clk_bulk_data *clks;
|
struct clk_bulk_data *clks;
|
||||||
int num_clks;
|
int num_clks;
|
||||||
|
|
||||||
|
/* Regmap fields of I2SCTL & DMACTL registers bitfields */
|
||||||
|
struct lpaif_i2sctl *i2sctl;
|
||||||
|
struct lpaif_dmactl *rd_dmactl;
|
||||||
|
struct lpaif_dmactl *wr_dmactl;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Vairant data per each SOC */
|
/* Vairant data per each SOC */
|
||||||
@ -72,6 +98,33 @@ struct lpass_variant {
|
|||||||
u32 wrdma_reg_stride;
|
u32 wrdma_reg_stride;
|
||||||
u32 wrdma_channels;
|
u32 wrdma_channels;
|
||||||
|
|
||||||
|
/* I2SCTL Register fields */
|
||||||
|
struct reg_field loopback;
|
||||||
|
struct reg_field spken;
|
||||||
|
struct reg_field spkmode;
|
||||||
|
struct reg_field spkmono;
|
||||||
|
struct reg_field micen;
|
||||||
|
struct reg_field micmode;
|
||||||
|
struct reg_field micmono;
|
||||||
|
struct reg_field wssrc;
|
||||||
|
struct reg_field bitwidth;
|
||||||
|
|
||||||
|
/* RD_DMA Register fields */
|
||||||
|
struct reg_field rdma_bursten;
|
||||||
|
struct reg_field rdma_wpscnt;
|
||||||
|
struct reg_field rdma_intf;
|
||||||
|
struct reg_field rdma_fifowm;
|
||||||
|
struct reg_field rdma_enable;
|
||||||
|
struct reg_field rdma_dyncclk;
|
||||||
|
|
||||||
|
/* WR_DMA Register fields */
|
||||||
|
struct reg_field wrdma_bursten;
|
||||||
|
struct reg_field wrdma_wpscnt;
|
||||||
|
struct reg_field wrdma_intf;
|
||||||
|
struct reg_field wrdma_fifowm;
|
||||||
|
struct reg_field wrdma_enable;
|
||||||
|
struct reg_field wrdma_dyncclk;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* on SOCs like APQ8016 the channel control bits start
|
* on SOCs like APQ8016 the channel control bits start
|
||||||
* at different offset to ipq806x
|
* at different offset to ipq806x
|
||||||
|
Loading…
Reference in New Issue
Block a user