This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

Kernel 3.12 - McASP Division by zero

Hi,

I think I found a bug in the latest SDK version 7 for AM335x. The audio driver is causing a division by zero in the davinci_pcm_enqueue_dma when audio is played back as the active_serializers parameter is not set for the DMA.

This should happen within davinci_mcasp_hw_params:

dma_params->active_serializers=active_serializers;

Then audio playback works - see the whole function below:

static int davinci_mcasp_hw_params(struct snd_pcm_substream *substream,
                    struct snd_pcm_hw_params *params,
                    struct snd_soc_dai *cpu_dai)
{
    struct davinci_mcasp *mcasp = snd_soc_dai_get_drvdata(cpu_dai);
    struct davinci_pcm_dma_params *dma_params =
                    &mcasp->dma_params[substream->stream];
    struct snd_dmaengine_dai_dma_data *dma_data =
                    &mcasp->dma_data[substream->stream];
    int word_length;
    u8 fifo_level;
    u8 slots = mcasp->tdm_slots;
    u8 active_serializers;
    int channels = params_channels(params);
    int ret;

    ret = mcasp_common_hw_param(mcasp, substream->stream, channels);
    if (ret)
        return ret;

    if (mcasp->op_mode == DAVINCI_MCASP_DIT_MODE)
        ret = mcasp_dit_hw_param(mcasp);
    else
        ret = mcasp_i2s_hw_param(mcasp, substream->stream);

    if (ret)
        return ret;

    switch (params_format(params)) {
    case SNDRV_PCM_FORMAT_U8:
    case SNDRV_PCM_FORMAT_S8:
        dma_params->data_type = 1;
        word_length = 8;
        break;

    case SNDRV_PCM_FORMAT_U16_LE:
    case SNDRV_PCM_FORMAT_S16_LE:
        dma_params->data_type = 2;
        word_length = 16;
        break;

    case SNDRV_PCM_FORMAT_U24_3LE:
    case SNDRV_PCM_FORMAT_S24_3LE:
        dma_params->data_type = 3;
        word_length = 24;
        break;

    case SNDRV_PCM_FORMAT_U24_LE:
    case SNDRV_PCM_FORMAT_S24_LE:
    case SNDRV_PCM_FORMAT_U32_LE:
    case SNDRV_PCM_FORMAT_S32_LE:
        dma_params->data_type = 4;
        word_length = 32;
        break;

    default:
        printk(KERN_WARNING "davinci-mcasp: unsupported PCM format");
        return -EINVAL;
    }

    /* Calculate FIFO level */
    active_serializers = (channels + slots - 1) / slots;
    if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
        fifo_level = mcasp->txnumevt * active_serializers;
    else
        fifo_level = mcasp->rxnumevt * active_serializers;

    if (mcasp->version == MCASP_VERSION_2 && !fifo_level)
        dma_params->acnt = 4;
    else
        dma_params->acnt = dma_params->data_type;

    dma_params->fifo_level = fifo_level;
    dma_params->active_serializers=active_serializers;
    dma_data->maxburst = fifo_level;

    davinci_config_channel_size(mcasp, word_length);

    return 0;
}

Please see