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.

Troubled when convert raw video data using EDMA3 link



Hi all,

I need to convert the raw video data captured by dm6467 from yuv422 to yuyv422 using edma3 link

src data type yuv422:

dst data type yuyv422:

C code:

struct timeval dma_begin_t;

struct timeval dma_end_t;

static void callMe(unsigned lch, u16 ch_status, void *data)

{

       int elapse;

       switch(ch_status)

       {

       case DMA_COMPLETE:

              irqraised1 = 1;       

              do_gettimeofday(&dma_end_t);

           elapse = 1000000 * (dma_end_t.tv_sec - dma_begin_t.tv_sec) + (dma_end_t.tv_usec - dma_begin_t.tv_usec); //us

        printk("in callme dma absync transf consume %d us\n", elapse);         

              break;

       case DMA_CC_ERROR:

              irqraised1 = -1;

              printk ("\nFrom callMe : DMA_CC_ERROR occured "

                            "on Channel %d\n", lch);

              break;

       default:

              break;

       }

}

/*

  * yuv422->yuyv422 use dma link

  *

  * width is the width of the video resolution

  * height is the height of the video resolution

  * dst is destination address of dma transfer

  * src is source address of dma transfer

  */

int dm646x_edma_transf_sort_e(dma_addr_t dst, dma_addr_t src, int width, int height)

{

       int channel1 = -1;//transfer Y data

       int channel2 = -1;//transfer UV data

      

       u16 ch_status = 0;

       int ret_val = -1;

       int i,j;

      

       int acnt = 1;

       int ccnt = 64;

       int bcnt = width*height/ccnt;

      

       s16 srcbidx = 1;

       s16 srccidx = bcnt;

       s16 dstbidx = 2;

       s16 dstcidx = 2*bcnt;

       struct edmacc_param param_set;

       struct timeval Start_Val,End_Val;

    unsigned int timeuse;

       channel1 = edma_alloc_channel(EDMA_CHANNEL_ANY, callMe, (void*)ch_status,

                                                               EVENTQ_DEFAULT);

       if (channel1 < 0)

       {

              return ret_val;

      } 

       edma_set_src(channel1, src, INCR, W8BIT);    //Y

       edma_set_dest(channel1, dst, INCR, W8BIT);

 

       edma_set_src_index(channel1, srcbidx, srccidx);

       edma_set_dest_index(channel1, dstbidx, dstcidx);      

      

       edma_set_transfer_params(channel1, acnt, bcnt, ccnt, 0, ABSYNC);

 

       /* Enable the Interrupts on Channel 1 */

       edma_read_slot(channel1, &param_set);

       param_set.opt |= (1 << ITCINTEN_SHIFT);

       param_set.opt |= (1 << TCINTEN_SHIFT);

       param_set.opt |= EDMA_TCC(EDMA_CHAN_SLOT(channel1));

       edma_write_slot(channel1, &param_set);

      

       /* Request a Link Channel 2 */

       ret_val = edma_alloc_slot(0, EDMA_SLOT_ANY);

       if (ret_val < 0)

       {

              printk ("\ndm646x_edma_tranf_sort_e::edma_alloc_slot "

                            "failed for channel2, error:%d\n", ret_val);

              return ret_val;

       }

       channel2 = ret_val;

       edma_set_src(channel2, src+width*height, INCR, W8BIT);  //UV

       edma_set_dest(channel2, dst+1, INCR, W8BIT);

       edma_set_src_index(channel2, srcbidx, srccidx);

       edma_set_dest_index(channel2, dstbidx, dstcidx);

       edma_set_transfer_params(channel2, acnt, bcnt, ccnt, 0, ABSYNC);

 

       /* Enable the Interrupts on Channel 2 */

       edma_read_slot(channel2, &param_set);

       param_set.opt |= (1 << ITCINTEN_SHIFT);

       param_set.opt |= (1 << TCINTEN_SHIFT);

       param_set.opt |= EDMA_TCC(EDMA_CHAN_SLOT(channel1));

       edma_write_slot(channel2, &param_set);

 

       /* Link both the channels */

       edma_link(channel1, channel2);

      

    do_gettimeofday(&Start_Val);

       for (i = 0; i < 2*ccnt; i++)

       {

              irqraised1 = 0;             

              do_gettimeofday(&dma_begin_t);

              ret_val = edma_start(channel1);

              if (ret_val != 0)

              {

                     printk("davinci_start_dma failed. \n");

              }

              while (irqraised1 == 0u);         

              /* Check the status of the completed transfer */

              if (irqraised1 < 0)

              {

                     /* Some error occured, break from the FOR loop. */

                     printk("Event Miss Occured!!!\n");

              }

       }

    do_gettimeofday(&End_Val);

    timeuse = 1000000 * (End_Val.tv_sec - Start_Val.tv_sec) + (End_Val.tv_usec - Start_Val.tv_usec); //us

    printk("dma link transf consume %d us\n", timeuse);

      

       if (ret_val == 0)

       {

              edma_stop(channel1);

              edma_free_channel(channel1);

             

              edma_stop(channel2);

              edma_free_slot(channel2);

              edma_free_channel(channel2);       

       }    

       return ret_val;

}

The data is transfered correct, Here is the trouble:

The func callMe() is called 128 times, consume 340*128=43,520us

(in callme dma absync transf consume 340 us

in callme dma absync transf consume 330 us

in callme dma absync transf consume 330 us

in callme dma absync transf consume 350 us

),

But the total process consume 662,103us

(dma link transf consume 662103 us)

This performance can’t achieve requirement, I wanna know whether there is somewhere to optimize, or some better idea. Thanks!