Messages in this thread | | | Date | Sat, 26 Feb 2022 11:28:03 +0530 | Subject | Re: [PATCH v16 6/9] ASoC: qcom: Add support for codec dma driver | From | Srinivasa Rao Mandadapu <> |
| |
On 2/25/2022 5:10 AM, Stephen Boyd wrote: Thanks for your time Stephen!!! > Quoting Srinivasa Rao Mandadapu (2022-02-24 07:33:45) >> 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. Okay. will fix it. > >> 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 Here dma_buffer structure has virtual address(buf->area) of unsigned char pointer but memremap returns void pointer. > this looks wrong. Why can't MEMREMAP_WC be used? But if it's DMA then Okay. Will update the flag MEMREMAP_WT > why isn't dma_map_resource() being used?
I am sorry bit confused here. You mean some thing like below.
For Physical address mapping: buf->addr = dma_map_resource(pcm->card->dev, drvdata->va_cdc_dma_lpm_buf, buf->bytes, DMA_BIDIRECTIONAL, 0); For virtual address mapping. buf->area = (unsigned char * __force)memremap(buf->addr, buf->bytes, MEMREMAP_WC);
> >> + >> + 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); >> :
| |