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.

audio playback in dm6441 processor

 Hi,

 I m using dm6441 processor in which i ported a audio codec driver written in linux. Initially i works fine with aplay utility and with gstreamer or any other encoding and decoding application is used there will be a crackling  noise during the audio playback.  I found in errata document that this processor needs internal ram for asp transfer. So i implemented ping/pong buffering. Now what happens s that randomly the buffer get swapped by another one and sometimes the upper layer not giving proper buffer to lower layer leads to underrun.

Please help me in this.

 

Thanks

  • I believe the problem you're seeing is in the alsa linux kernel driver for the davinci + similiar.

    The function edma_read_slot() in

    arch/arm/mach-davinci/dma.c

    The function does a byte by byte copy of a structure from hardware registers. Some of the registers contain hardware pointers into the buffers used for audio data. The pointers are being updated by the hardware as the bytes are being read, so the value read back from a 32 bit address can be incorrect. An error occurs when the pointer rolls over a page boundary (256 bytes). In that case, since we are little endia, we've read an old byte pointer in the FC or FE realm, but when we read the pointer value for the next 8 bits the pointer has advanced. So we read a value that appears to be some 256 bytes ahead of where it actually should be.

    So the driver thinks more audio data has been read than it has, so it resets the pointers. And audio data that was written to the device is lost.

    Here is a code section:

    void edma_read_slot(unsigned slot, struct edmacc_param *param)
    {
        unsigned ctlr;

        ctlr = EDMA_CTLR(slot);
        slot = EDMA_CHAN_SLOT(slot);

        if (slot >= edma_info[ctlr]->num_slots)
            return;
        if(1)
        {
    //(DA) Dave Ashley
    // Awful bug found, problem was when reading the dma pointers on a byte
    // basis (as memcpy_fromio does) there can be skew right on page boundaries,
    // where you get a low byte of fe and by the time you read the 2nd byte
    // you get a value that is +1 from what it was before...
    // Example: you get b602 when you wanted b5fe
            int i, *p;
            int slot_off;
            slot_off = PARM_OFFSET(slot);
            p = (void *)param;
            for(i=0;i<PARM_SIZE;i+=sizeof(int))
                p[i>>2] = edma_read(ctlr, slot_off+i);
        } else
            memcpy_fromio(param, edmacc_regs_base[ctlr] + PARM_OFFSET(slot),
                PARM_SIZE);
    }

    This problem probably affects multiple TI chips.

    -Dave