[RESEND PATCH v2 12/15] ASoC: qcom: qdsp6: Add support to q6asm dai driver
Srinivas Kandagatla
srinivas.kandagatla at linaro.org
Wed Jan 3 08:27:16 PST 2018
Thanks for the comments.
On 03/01/18 00:03, Bjorn Andersson wrote:
> On Thu 14 Dec 09:33 PST 2017, srinivas.kandagatla at linaro.org wrote:
>
> [..]
>> +
>> +enum stream_state {
>> + IDLE = 0,
>> + STOPPED,
>> + RUNNING,
>
> These are too generic.
>
Yep, I will prefix them with Q6ASM.
>> +};
>> +
>> +struct q6asm_dai_rtd {
>> + struct snd_pcm_substream *substream;
>> + dma_addr_t phys;
>> + unsigned int pcm_size;
>> + unsigned int pcm_count;
>> + unsigned int pcm_irq_pos; /* IRQ position */
>> + unsigned int periods;
>> + uint16_t bits_per_sample;
>> + uint16_t source; /* Encoding source bit mask */
>> +
>> + struct audio_client *audio_client;
>> + uint16_t session_id;
>> +
>> + enum stream_state state;
>> + bool set_channel_map;
>> + char channel_map[8];
>
> There's a define for this 8
Yes, this is max channels.
>
>> +};
>> +
>> +struct q6asm_dai_data {
>> + u64 sid;
>> +};
>> +
>> +static struct snd_pcm_hardware q6asm_dai_hardware_playback = {
>> + .info = (SNDRV_PCM_INFO_MMAP |
>> + SNDRV_PCM_INFO_BLOCK_TRANSFER |
>> + SNDRV_PCM_INFO_MMAP_VALID |
>> + SNDRV_PCM_INFO_INTERLEAVED |
>> + SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_RESUME),
>> + .formats = (SNDRV_PCM_FMTBIT_S16_LE |
>> + SNDRV_PCM_FMTBIT_S24_LE),
>> + .rates = SNDRV_PCM_RATE_8000_192000,
>> + .rate_min = 8000,
>> + .rate_max = 192000,
>> + .channels_min = 1,
>> + .channels_max = 8,
>> + .buffer_bytes_max = (PLAYBACK_MAX_NUM_PERIODS *
>> + PLAYBACK_MAX_PERIOD_SIZE),
>> + .period_bytes_min = PLAYBACK_MIN_PERIOD_SIZE,
>> + .period_bytes_max = PLAYBACK_MAX_PERIOD_SIZE,
>> + .periods_min = PLAYBACK_MIN_NUM_PERIODS,
>> + .periods_max = PLAYBACK_MAX_NUM_PERIODS,
>
> If you just put the numbers here, instead of using the PLAYBACK_
> defines, it's possible to grok the values of this struct without having
> to jump to the defines for each one.
This is usually done this way in may other drivers!,
>
>> + .fifo_size = 0,
>> +};
>> +
>> +/* Conventional and unconventional sample rate supported */
>> +static unsigned int supported_sample_rates[] = {
>> + 8000, 11025, 12000, 16000, 22050, 24000, 32000, 44100, 48000,
>> + 88200, 96000, 176400, 192000
>> +};
>> +
>> +static struct snd_pcm_hw_constraint_list constraints_sample_rates = {
>
It is used in q6asm_dai_open().
>
>> + .count = ARRAY_SIZE(supported_sample_rates),
>> + .list = supported_sample_rates,
>> + .mask = 0,
>> +};
>> +
>
>> +
>> +static int q6asm_dai_prepare(struct snd_pcm_substream *substream)
>> +{
>> + struct snd_pcm_runtime *runtime = substream->runtime;
>> + struct snd_soc_pcm_runtime *soc_prtd = substream->private_data;
>> + struct q6asm_dai_rtd *prtd = runtime->private_data;
>> + struct q6asm_dai_data *pdata;
>> + int ret;
>> +
>> + pdata = dev_get_drvdata(soc_prtd->platform->dev);
>> + if (!pdata)
>> + return -EINVAL;
>> +
>> + if (!prtd || !prtd->audio_client) {
>> + pr_err("%s: private data null or audio client freed\n",
>> + __func__);
>> + return -EINVAL;
>> + }
>> +
>> + prtd->pcm_count = snd_pcm_lib_period_bytes(substream);
>> + prtd->pcm_irq_pos = 0;
>> + /* rate and channels are sent to audio driver */
>> + if (prtd->state) {
>> + /* clear the previous setup if any */
>> + q6asm_cmd(prtd->audio_client, CMD_CLOSE);
>> + q6asm_unmap_memory_regions(substream->stream,
>> + prtd->audio_client);
>> + q6routing_dereg_phy_stream(soc_prtd->dai_link->id,
>> + SNDRV_PCM_STREAM_PLAYBACK);
>> + }
>> +
>> + ret = q6asm_map_memory_regions(substream->stream, prtd->audio_client,
>> + prtd->phys,
>> + (prtd->pcm_size / prtd->periods),
>> + prtd->periods);
>> +
>> + if (ret < 0) {
>> + pr_err("Audio Start: Buffer Allocation failed rc = %d\n",
>> + ret);
>> + return -ENOMEM;
>> + }
>> +
>> + ret = q6asm_open_write(prtd->audio_client, FORMAT_LINEAR_PCM,
>> + prtd->bits_per_sample);
>> + if (ret < 0) {
>> + pr_err("%s: q6asm_open_write failed\n", __func__);
>> + q6asm_audio_client_free(prtd->audio_client);
>> + prtd->audio_client = NULL;
>
> Do you need to roll back the q6asm_map_memory_regions?
>
yes you are correct, we should roll back the map.
>> + return -ENOMEM;
>> + }
>> +
>> + prtd->session_id = q6asm_get_session_id(prtd->audio_client);
>> + ret = q6routing_reg_phy_stream(soc_prtd->dai_link->id, LEGACY_PCM_MODE,
>> + prtd->session_id, substream->stream);
>> + if (ret) {
>> + pr_err("%s: stream reg failed ret:%d\n", __func__, ret);
>> + return ret;
>> + }
>> +
>> + ret = q6asm_media_format_block_multi_ch_pcm(
>> + prtd->audio_client, runtime->rate,
>> + runtime->channels, !prtd->set_channel_map,
>> + prtd->channel_map, prtd->bits_per_sample);
>
> set_channel_map and channel_map aren't referenced elsewhere. If this
> isn't used consider removing it for now.
>
Will take a closer look before sending next version.
>> + if (ret < 0)
>> + pr_info("%s: CMD Format block failed\n", __func__);
>> +
>> + prtd->state = RUNNING;
>> +
>> + return 0;
>> +}
>> +
> [..]
>> +static int q6asm_dai_pcm_new(struct snd_soc_pcm_runtime *rtd)
>> +{
>> + struct snd_pcm *pcm = rtd->pcm;
>> + struct snd_pcm_substream *substream;
>> + struct snd_card *card = rtd->card->snd_card;
>> + struct device *dev = card->dev;
>> + struct device_node *node = dev->of_node;
>> + struct q6asm_dai_data *pdata = dev_get_drvdata(rtd->platform->dev);
>> + struct of_phandle_args args;
>> +
>> + int size, ret = 0;
>> +
>> + ret = of_parse_phandle_with_fixed_args(node, "iommus", 1, 0, &args);
>> + if (ret < 0)
>> + pdata->sid = -1;
>> + else
>> + pdata->sid = args.args[0];
>> +
>
> Is this really how you're supposed to deal with the iommu?
>
Any suggestions are welcome, I did not find a better way to append sid
to iova address from iommu.
Currently downstream abstracts this in ion apis.
>> +
>> +
>> + substream = pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream;
>> + size = q6asm_dai_hardware_playback.buffer_bytes_max;
>> + ret = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, dev, size,
>> + &substream->dma_buffer);
>> + if (ret) {
>> + dev_err(dev, "Cannot allocate buffer(s)\n");
>> + return ret;
>
> Just fall through.
>
yep
>> + }
>> +
>> + return ret;
>> +}
>> +
> [..]
>> +static struct snd_soc_dai_driver q6asm_fe_dais[] = {
>> + {
>> + .playback = {
>> + .stream_name = "MultiMedia1 Playback",
>> + .rates = (SNDRV_PCM_RATE_8000_192000|
>> + SNDRV_PCM_RATE_KNOT),
>> + .formats = (SNDRV_PCM_FMTBIT_S16_LE |
>> + SNDRV_PCM_FMTBIT_S24_LE),
>> + .channels_min = 1,
>> + .channels_max = 8,
>> + .rate_min = 8000,
>> + .rate_max = 192000,
>> + },
>> + .name = "MM_DL1",
>> + .probe = fe_dai_probe,
>> + .id = MSM_FRONTEND_DAI_MULTIMEDIA1,
>> + },
>> + {
>> + .playback = {
>> + .stream_name = "MultiMedia2 Playback",
>> + .rates = (SNDRV_PCM_RATE_8000_192000|
>> + SNDRV_PCM_RATE_KNOT),
>> + .formats = (SNDRV_PCM_FMTBIT_S16_LE |
>> + SNDRV_PCM_FMTBIT_S24_LE),
>> + .channels_min = 1,
>> + .channels_max = 8,
>> + .rate_min = 8000,
>> + .rate_max = 192000,
>
> I presume the listed frontend DAIs needs to match the firmware of the
> DSP (and features of hardware)? Can we get away with a single list for
> all versions of the adsp?
>
Yes, DSP supports 8 concurrent streams both playback and record streams.
For now I have only added two entires to keep the patch simple but this
should be ideally 8 entries.
> In msm-4.4 the max rate for these where changed to 384000, see:
>
> 9c46f74b2724 ("ASoC: msm: add 384KHz playback support")
sure i will include that in next version.
>
>> + },
>> + .name = "MM_DL2",
>> + .probe = fe_dai_probe,
>> + .id = MSM_FRONTEND_DAI_MULTIMEDIA2,
>> + },
>> +};
>> +
>
> Regards,
> Bjorn
>
More information about the linux-arm-kernel
mailing list