diff options
Diffstat (limited to 'sound/soc/qcom/lpass-cpu.c')
-rw-r--r-- | sound/soc/qcom/lpass-cpu.c | 49 |
1 files changed, 41 insertions, 8 deletions
diff --git a/sound/soc/qcom/lpass-cpu.c b/sound/soc/qcom/lpass-cpu.c index a6e95db6b3fb..3bd9eb3cc688 100644 --- a/sound/soc/qcom/lpass-cpu.c +++ b/sound/soc/qcom/lpass-cpu.c @@ -29,6 +29,15 @@ #define LPASS_CPU_I2S_SD0_1_2_MASK GENMASK(2, 0) #define LPASS_CPU_I2S_SD0_1_2_3_MASK GENMASK(3, 0) +/* + * Channel maps for Quad channel playbacks on MI2S Secondary + */ +static struct snd_pcm_chmap_elem lpass_quad_chmaps[] = { + { .channels = 4, + .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_RL, + SNDRV_CHMAP_FR, SNDRV_CHMAP_RR } }, + { } +}; static int lpass_cpu_init_i2sctl_bitfields(struct device *dev, struct lpaif_i2sctl *i2sctl, struct regmap *map) { @@ -403,6 +412,25 @@ const struct snd_soc_dai_ops asoc_qcom_lpass_cpu_dai_ops = { }; EXPORT_SYMBOL_GPL(asoc_qcom_lpass_cpu_dai_ops); +int lpass_cpu_pcm_new(struct snd_soc_pcm_runtime *rtd, + struct snd_soc_dai *dai) +{ + int ret; + struct snd_soc_dai_driver *drv = dai->driver; + struct lpass_data *drvdata = snd_soc_dai_get_drvdata(dai); + + if (drvdata->mi2s_playback_sd_mode[dai->id] == LPAIF_I2SCTL_MODE_QUAD01) { + ret = snd_pcm_add_chmap_ctls(rtd->pcm, SNDRV_PCM_STREAM_PLAYBACK, + lpass_quad_chmaps, drv->playback.channels_max, 0, + NULL); + if (ret < 0) + return ret; + } + + return 0; +} +EXPORT_SYMBOL_GPL(lpass_cpu_pcm_new); + int asoc_qcom_lpass_cpu_dai_probe(struct snd_soc_dai *dai) { struct lpass_data *drvdata = snd_soc_dai_get_drvdata(dai); @@ -497,6 +525,8 @@ static bool lpass_cpu_regmap_readable(struct device *dev, unsigned int reg) return true; for (i = 0; i < v->irq_ports; ++i) { + if (reg == LPAIF_IRQCLEAR_REG(v, i)) + return true; if (reg == LPAIF_IRQEN_REG(v, i)) return true; if (reg == LPAIF_IRQSTAT_REG(v, i)) @@ -538,9 +568,12 @@ static bool lpass_cpu_regmap_volatile(struct device *dev, unsigned int reg) struct lpass_variant *v = drvdata->variant; int i; - for (i = 0; i < v->irq_ports; ++i) + for (i = 0; i < v->irq_ports; ++i) { + if (reg == LPAIF_IRQCLEAR_REG(v, i)) + return true; if (reg == LPAIF_IRQSTAT_REG(v, i)) return true; + } for (i = 0; i < v->rdma_channels; ++i) if (reg == LPAIF_RDMACURR_REG(v, i)) @@ -839,7 +872,6 @@ int asoc_qcom_lpass_cpu_platform_probe(struct platform_device *pdev) { struct lpass_data *drvdata; struct device_node *dsp_of_node; - struct resource *res; struct lpass_variant *variant; struct device *dev = &pdev->dev; const struct of_device_id *match; @@ -865,9 +897,7 @@ int asoc_qcom_lpass_cpu_platform_probe(struct platform_device *pdev) of_lpass_cpu_parse_dai_data(dev, drvdata); - res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "lpass-lpaif"); - - drvdata->lpaif = devm_ioremap_resource(dev, res); + drvdata->lpaif = devm_platform_ioremap_resource_byname(pdev, "lpass-lpaif"); if (IS_ERR(drvdata->lpaif)) return PTR_ERR(drvdata->lpaif); @@ -884,9 +914,7 @@ int asoc_qcom_lpass_cpu_platform_probe(struct platform_device *pdev) } if (drvdata->hdmi_port_enable) { - res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "lpass-hdmiif"); - - drvdata->hdmiif = devm_ioremap_resource(dev, res); + drvdata->hdmiif = devm_platform_ioremap_resource_byname(pdev, "lpass-hdmiif"); if (IS_ERR(drvdata->hdmiif)) return PTR_ERR(drvdata->hdmiif); @@ -925,6 +953,11 @@ int asoc_qcom_lpass_cpu_platform_probe(struct platform_device *pdev) PTR_ERR(drvdata->mi2s_bit_clk[dai_id])); return PTR_ERR(drvdata->mi2s_bit_clk[dai_id]); } + if (drvdata->mi2s_playback_sd_mode[dai_id] == + LPAIF_I2SCTL_MODE_QUAD01) { + variant->dai_driver[dai_id].playback.channels_min = 4; + variant->dai_driver[dai_id].playback.channels_max = 4; + } } /* Allocation for i2sctl regmap fields */ |