Re: [PATCH v16 6/9] ASoC: qcom: Add support for codec dma driver
From: Stephen Boyd <hidden>
Date: 2022-02-24 23:41:02
Also in:
alsa-devel, linux-arm-msm, lkml
Quoting Srinivasa Rao Mandadapu (2022-02-24 07:33:45)
quoted hunk ↗ jump to hunk
diff --git a/sound/soc/qcom/lpass-platform.c b/sound/soc/qcom/lpass-platform.c index 198f27c..b3af971 100644 --- a/sound/soc/qcom/lpass-platform.c +++ b/sound/soc/qcom/lpass-platform.c@@ -684,6 +953,17 @@ static irqreturn_t lpass_dma_interrupt_handler( reg = LPAIF_IRQCLEAR_REG(v, LPAIF_IRQ_PORT_HOST); val = 0; break; + case LPASS_CDC_DMA_RX0 ... LPASS_CDC_DMA_RX9: + case LPASS_CDC_DMA_TX0 ... LPASS_CDC_DMA_TX8: + map = drvdata->rxtx_lpaif_map; + reg = LPAIF_RXTX_IRQCLEAR_REG(v, LPAIF_IRQ_PORT_HOST); + val = 0; + break; + case LPASS_CDC_DMA_VA_TX0 ... LPASS_CDC_DMA_VA_TX8: + map = drvdata->va_lpaif_map; + reg = LPAIF_VA_IRQCLEAR_REG(v, LPAIF_IRQ_PORT_HOST); + val = 0; + break;
These breaks have the wrong indentation.
quoted hunk ↗ jump to hunk
default: dev_err(soc_runtime->dev, "%s: invalid %d interface\n", __func__, dai_id); return -EINVAL;@@ -791,16 +1071,115 @@ static irqreturn_t lpass_platform_hdmiif_irq(int irq, void *data) return rv; } } + return IRQ_HANDLED; +} + +static irqreturn_t lpass_platform_rxtxif_irq(int irq, void *data) +{ + struct lpass_data *drvdata = data; + struct lpass_variant *v = drvdata->variant; + unsigned int irqs; + irqreturn_t rv; + int chan; + + rv = regmap_read(drvdata->rxtx_lpaif_map, + LPAIF_RXTX_IRQSTAT_REG(v, LPAIF_IRQ_PORT_HOST), &irqs); + + /* Handle per channel interrupts */ + for (chan = 0; chan < LPASS_MAX_CDC_DMA_CHANNELS; chan++) { + if (irqs & LPAIF_IRQ_ALL(chan) && drvdata->rxtx_substream[chan]) { + rv = lpass_dma_interrupt_handler( + drvdata->rxtx_substream[chan], + drvdata, chan, irqs); + if (rv != IRQ_HANDLED) + return rv; + } + } + + return IRQ_HANDLED; +} + +static irqreturn_t lpass_platform_vaif_irq(int irq, void *data) +{ + struct lpass_data *drvdata = data; + struct lpass_variant *v = drvdata->variant; + unsigned int irqs; + irqreturn_t rv; + int chan; + + rv = regmap_read(drvdata->va_lpaif_map, + LPAIF_VA_IRQSTAT_REG(v, LPAIF_IRQ_PORT_HOST), &irqs); + /* Handle per channel interrupts */ + for (chan = 0; chan < LPASS_MAX_VA_CDC_DMA_CHANNELS; chan++) { + if (irqs & LPAIF_IRQ_ALL(chan) && drvdata->va_substream[chan]) { + rv = lpass_dma_interrupt_handler( + drvdata->va_substream[chan], + drvdata, chan, irqs); + if (rv != IRQ_HANDLED) + return rv; + } + } return IRQ_HANDLED; } +static int lpass_platform_prealloc_cdc_dma_buffer(struct snd_soc_component *component, + struct snd_pcm *pcm, int dai_id) +{ + struct lpass_data *drvdata = snd_soc_component_get_drvdata(component); + struct snd_pcm_substream *substream; + struct snd_dma_buffer *buf; + + if (pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream) + substream = pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream; + else + substream = pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream; + + buf = &substream->dma_buffer; + buf->dev.dev = pcm->card->dev; + buf->private_data = NULL; + + /* Assign Codec DMA buffer pointers */ + buf->dev.type = SNDRV_DMA_TYPE_CONTINUOUS; + + switch (dai_id) { + case LPASS_CDC_DMA_RX0 ... LPASS_CDC_DMA_RX9: + buf->bytes = lpass_platform_rxtx_hardware.buffer_bytes_max; + buf->addr = drvdata->rxtx_cdc_dma_lpm_buf; + break; + case LPASS_CDC_DMA_TX0 ... LPASS_CDC_DMA_TX8: + buf->bytes = lpass_platform_rxtx_hardware.buffer_bytes_max; + buf->addr = drvdata->rxtx_cdc_dma_lpm_buf + LPASS_RXTX_CDC_DMA_LPM_BUFF_SIZE; + break; + case LPASS_CDC_DMA_VA_TX0 ... LPASS_CDC_DMA_VA_TX8: + buf->bytes = lpass_platform_va_hardware.buffer_bytes_max; + buf->addr = drvdata->va_cdc_dma_lpm_buf; + break; + default: + break; + } + + buf->area = (unsigned char * __force)memremap(buf->addr, buf->bytes, MEMREMAP_WT);
What's the cast and __force for now? MEMREMAP_WT is almost never used so this looks wrong. Why can't MEMREMAP_WC be used? But if it's DMA then why isn't dma_map_resource() being used?
+
+ return 0;
+}
+
static int lpass_platform_pcm_new(struct snd_soc_component *component,
struct snd_soc_pcm_runtime *soc_runtime)
{
struct snd_pcm *pcm = soc_runtime->pcm;
+ struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(soc_runtime, 0);
+ unsigned int dai_id = cpu_dai->driver->id;
+
size_t size = lpass_platform_pcm_hardware.buffer_bytes_max;
+ /*
+ * Lpass codec dma can access only lpass lpm hardware memory.
+ * ioremap is for HLOS to access hardware memory.
+ */
+ if (is_cdc_dma_port(dai_id))
+ return lpass_platform_prealloc_cdc_dma_buffer(component, pcm, dai_id);
+
return snd_pcm_set_fixed_buffer_all(pcm, SNDRV_DMA_TYPE_DEV,
component->dev, size);
}