EdmaMgr : Added support for transfers with large pitch.
[mfp/fcdev.git] / packages / ti / sdo / fc / edmamgr / edmamgr_xfer.h
1 /*
2  * Copyright (c) 2013-2014, Texas Instruments Incorporated
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  *
9  * *  Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  *
12  * *  Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  *
16  * *  Neither the name of Texas Instruments Incorporated nor the names of
17  *    its contributors may be used to endorse or promote products derived
18  *    from this software without specific prior written permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
22  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
24  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
25  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
26  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
27  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
28  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
29  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
30  * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31  */
33 #ifdef ti_sdo_fc_edmamgr_EdmaMgr_
35 #ifndef ti_sdo_fc_edmamgr_EdmaMgr_XFER_
36 #define ti_sdo_fc_edmamgr_EdmaMgr_XFER_
38 /*---------------------------------------------------------------*/
39 /* This function convert single local address to global addresse */
40 /*---------------------------------------------------------------*/
41 extern cregister volatile unsigned int DNUM;
42 static inline void *restrict EDMA_MGR_ADDR_LOC_TO_GLOB(void *restrict loc_addr)
43 {
44    unsigned int tmp = (unsigned int)loc_addr;
46    if((tmp & 0xFF000000) == 0)
47    {
48       return (void *)((1 << 28) | (DNUM << 24) | tmp);
49    } else return loc_addr;
50 }
53 /*-----------------------------------------------------------*/
54 /*  This function waits for all transfers on a specific      */
55 /*  ECPY channel to complete. It is a blocking call          */
56 /*  in the sense that CPU will wait until all transfers      */
57 /*  are completed.                                           */
58 /*-----------------------------------------------------------*/
60 #if defined (EDMAMGR_INLINE_ALL)
61 static __inline
62 #endif
63 void EdmaMgr_wait(EdmaMgr_Handle h)
64 {
65   EdmaMgr_Channel  *edmamgrChan = (EdmaMgr_Channel *)h;
67   if (edmamgrChan->xferPending) {
68     ECPY_directWait(edmamgrChan->ecpyHandle);
70     if ( edmamgrChan->chainedChannel )
71       ECPY_directWait(edmamgrChan->chainedChannel->ecpyHandle);
73     edmamgrChan->xferPending = FALSE;
74   }
75   return;
76 }
78 /*------------------------------------------------------------*/
79 /* The following function performs a single 1D->1D transfer   */
80 /* transferring "num_bytes" bytes from "src" which is the     */
81 /* source address to "dst" which is the destination. This     */
82 /* function uses the channel number "chan_num". It is assumed */
83 /* by this function that there are no pending transfers on    */
84 /* "chan_num".                                                */
85 /*------------------------------------------------------------*/
87 #if defined (EDMAMGR_INLINE_ALL)
88 static __inline
89 #endif
90 int32_t EdmaMgr_copy1D1D
91 (
92     EdmaMgr_Handle            h,
93     void     *restrict        src,
94     void     *restrict        dst,
95     int32_t                   num_bytes
96 )
97 {
98   EdmaMgr_Channel *edmamgrChan = (EdmaMgr_Channel *)h;
99   ECPY_Params p;
100 #if 1
101   uint32_t r, n = 0, a_cnt = num_bytes, i = 0;
102   char *c_src = (char *)src, *c_dst = (char *)dst;
104   /*
105    * This abstracts an effective 1D1D transfer which can transfer more than the 16-bit limit set by the HW.
106    *
107    * This is done by splitting the transfer into 2 transfers:
108    *   - One 2D1D transfer.
109    *   - One 1D1D transfer for the remainder.
110    */
112   while ( a_cnt > 0xFFFF )
113   {
114     a_cnt >>= 1;
115     n++;
116   }
118   r = num_bytes - (a_cnt << n);
120   if ( r > 0 )
121   {
122     src = (void *)c_src;
123     dst = (void *)c_dst;
125     memset(&p, 0, sizeof(ECPY_Params));
126     p.transferType = ECPY_1D1D;
127     p.dstAddr     = (void *)EDMA_MGR_ADDR_LOC_TO_GLOB(dst);
128     p.srcAddr     = (void *)EDMA_MGR_ADDR_LOC_TO_GLOB(src);
129     p.elementSize = r;
130     p.numElements = 1;
131     p.numFrames   = 1;
133     i++;
134     ECPY_directConfigure(edmamgrChan->ecpyHandle, &p, i);
136     ECPY_directSetFinal(edmamgrChan->ecpyHandle, i);
137     ECPY_directStartEdma(edmamgrChan->ecpyHandle);
139     c_src += r;
140     c_dst += r;
142     src = (void *)c_src;
143     dst = (void *)c_dst;
145     ECPY_directWait(edmamgrChan->ecpyHandle);
146     i = 0;
147   }
149   memset(&p, 0, sizeof(ECPY_Params));
150   p.transferType = ECPY_2D1D;
151   p.dstAddr     = (void *)EDMA_MGR_ADDR_LOC_TO_GLOB(dst);
152   p.srcAddr     = (void *)EDMA_MGR_ADDR_LOC_TO_GLOB(src);
153   p.elementSize = (1<<n);
154   p.numElements = a_cnt;
155   p.numFrames   = 1;
156   p.srcElementIndex = (1<<n);
157   p.dstElementIndex = (1<<n);
159   i++;
160   ECPY_directConfigure(edmamgrChan->ecpyHandle, &p, i);
162   ECPY_directSetFinal(edmamgrChan->ecpyHandle, i);
163   ECPY_directStartEdma(edmamgrChan->ecpyHandle);
165   edmamgrChan->xferPending = TRUE;
167 #else
168     /*
169      *  Single 1D1D transfer.
170      *
171      *  NOTE: Max size of transfer is limited by 16-bit integer (65535 bytes)
172      */
174     memset(&p, 0, sizeof(ECPY_Params));
175     p.transferType = ECPY_1D1D;
176     p.dstAddr     = (void *)EDMA_MGR_ADDR_LOC_TO_GLOB(dst);
177     p.srcAddr     = (void *)EDMA_MGR_ADDR_LOC_TO_GLOB(src);
178     p.elementSize = num_bytes;
179     p.numElements = 1;
180     p.numFrames   = 1;
182     ECPY_directConfigure(edmamgrChan->ecpyHandle, &p, 1);
184     ECPY_directSetFinal(edmamgrChan->ecpyHandle, 1);
185     ECPY_directStartEdma(edmamgrChan->ecpyHandle);
187     edmamgrChan->xferPending = TRUE;
189 #endif
190   return(0);
193 /*----------------------------------------------------------*/
194 /*  The following function performs a 1D->2D transfer       */
195 /*  where the source is 1D one dimensional and destination  */
196 /*  is 2D two dimensional. This function uses channel       */
197 /*  number "chan_num" to transfer "num_lines" lines         */
198 /*  each of "num_bytes" bytes. In this case after every     */
199 /*  line of "num_bytes" is transferred, "src" source is     */
200 /*  incremeneted by "num_bytes" and "dst" destination is    */
201 /*  incremenetd by "pitch" bytes.                           */
202 /*----------------------------------------------------------*/
203 #if defined (EDMAMGR_INLINE_ALL)
204 static __inline
205 #endif
206 int32_t EdmaMgr_copy1D2D
208   EdmaMgr_Handle    h,
209   void *restrict    src,
210   void *restrict    dst,
211   int32_t           num_bytes,
212   int32_t           num_lines,
213   int32_t           pitch
216   EdmaMgr_Channel *edmamgrChan = (EdmaMgr_Channel *)h;
217   ECPY_Params p;
219   /* Setting up the parameters for the transfer */
220   memset(&p, 0, sizeof(ECPY_Params));
221   p.transferType = ECPY_1D2D;
222   p.numFrames    = 1;
223   p.elementSize = num_bytes;
224   p.numElements  = num_lines;
225   p.srcElementIndex = num_bytes;
226   p.dstElementIndex = pitch;
227   p.srcAddr = (void *)EDMA_MGR_ADDR_LOC_TO_GLOB(src);
228   p.dstAddr = (void *)EDMA_MGR_ADDR_LOC_TO_GLOB(dst);
230   ECPY_directConfigure(edmamgrChan->ecpyHandle, &p, 1);
232   ECPY_directSetFinal(edmamgrChan->ecpyHandle, 1);
233   ECPY_directStartEdma(edmamgrChan->ecpyHandle);
235   edmamgrChan->xferPending = TRUE;
237   return(0);
240 /*----------------------------------------------------------*/
241 /* This function performs a 2D->1D transfer by usinng the   */
242 /* channel number "chan_num" by performing a transfer from  */
243 /* source "src" to destination "dst", "num_lines" lines     */
244 /* each of "num_bytes" bytes. At the end of transferring    */
245 /* "num_bytes" bytes per line, the source is incremented    */
246 /* by "pitch" bytes and the destination is incremented by   */
247 /* "num_bytes" bytes as "src" is 2D and "dst" is 1D.        */
248 /*----------------------------------------------------------*/
249 #if defined (EDMAMGR_INLINE_ALL)
250 static __inline
251 #endif
252 int32_t EdmaMgr_copy2D1D
254   EdmaMgr_Handle    h,
255   void *restrict    src,
256   void *restrict    dst,
257   int32_t           num_bytes,
258   int32_t           num_lines,
259   int32_t           pitch
262   EdmaMgr_Channel *edmamgrChan = (EdmaMgr_Channel *)h;
263   ECPY_Params p;
265   /* Setting up the parameters for the first transfer (data grp 1) */
266   memset(&p, 0, sizeof(ECPY_Params));
267   p.transferType = ECPY_2D1D;
268   p.numFrames    = 1;
269   p.elementSize = num_bytes;
270   p.numElements  = num_lines;
271   p.srcElementIndex = pitch;
272   p.dstElementIndex = num_bytes;
273   p.srcAddr = (void *)EDMA_MGR_ADDR_LOC_TO_GLOB(src);
274   p.dstAddr = (void *)EDMA_MGR_ADDR_LOC_TO_GLOB(dst);
276   ECPY_directConfigure(edmamgrChan->ecpyHandle, &p, 1);
278   ECPY_directSetFinal(edmamgrChan->ecpyHandle, 1);
279   ECPY_directStartEdma(edmamgrChan->ecpyHandle);
281   edmamgrChan->xferPending = TRUE;
283   return(0);
286 /*----------------------------------------------------------*/
287 /* This function performs a 2D->2D transfer by using the    */
288 /* channel number "chan_num" by performing a transfer from  */
289 /* source "src" to destination "dst", "num_lines" lines     */
290 /* each of "num_bytes" bytes. At the end of transferring    */
291 /* "num_bytes" bytes per line, the source is incremented    */
292 /* by "pitch" bytes and the destination is incremented by   */
293 /* "pitch" bytes as well as "src" is 2D and "dst" is 2D.    */
294 /*----------------------------------------------------------*/
295 #if defined (EDMAMGR_INLINE_ALL)
296 static __inline
297 #endif
298 int32_t EdmaMgr_copy2D2D
300   EdmaMgr_Handle    h,
301   void *restrict    src,
302   void *restrict    dst,
303   int32_t           num_bytes,
304   int32_t           num_lines,
305   int32_t           pitch
308   EdmaMgr_Channel *edmamgrChan = (EdmaMgr_Channel *)h;
309   ECPY_Params p;
311   /* Setting up the parameters for the transfer */
312   memset(&p, 0, sizeof(ECPY_Params));
313   p.transferType = ECPY_2D2D;
314   p.numFrames    = 1;
315   p.elementSize = num_bytes;
316   p.numElements  = num_lines;
317   p.srcElementIndex = pitch;
318   p.dstElementIndex = pitch;
319   p.srcAddr = (void *)EDMA_MGR_ADDR_LOC_TO_GLOB(src);
320   p.dstAddr = (void *)EDMA_MGR_ADDR_LOC_TO_GLOB(dst);
322   ECPY_directConfigure(edmamgrChan->ecpyHandle, &p, 1);
324   ECPY_directSetFinal(edmamgrChan->ecpyHandle, 1);
325   ECPY_directStartEdma(edmamgrChan->ecpyHandle);
327   edmamgrChan->xferPending = TRUE;
329   return(0);
332 /*----------------------------------------------------------*/
333 /* This function performs a 2D->2D transfer by usinng the   */
334 /* channel number "chan_num" by performing a transfer from  */
335 /* source "src" to destination "dst", "num_lines" lines     */
336 /* each of "num_bytes" bytes. At the end of transferring    */
337 /* "num_bytes" bytes per line, the source is incremented    */
338 /* by "dst_pitch" bytes and the destination is incremented  */
339 /* by "src_pitch" bytes as well as "src" is 2D and "dst"    */
340 /* is 2D. This function thus allows independent "src" and   */
341 /* "dst" pitches.                                           */
342 /*----------------------------------------------------------*/
343 #if defined (EDMAMGR_INLINE_ALL)
344 static __inline
345 #endif
346 int32_t EdmaMgr_copy2D2DSep
348   EdmaMgr_Handle    h,
349   void *restrict    src,
350   void *restrict    dst,
351   int32_t           num_bytes,
352   int32_t           num_lines,
353   int32_t           src_pitch,
354   int32_t           dst_pitch
357   EdmaMgr_Channel *edmamgrChan = (EdmaMgr_Channel *)h;
358   ECPY_Params p;
360   /* Setting up the parameters for the transfer */
361   memset(&p, 0, sizeof(ECPY_Params));
362   p.transferType = ECPY_2D2D;
363   p.numFrames    = 1;
364   p.elementSize = num_bytes;
365   p.numElements  = num_lines;
366   p.srcElementIndex = src_pitch;
367   p.dstElementIndex = dst_pitch;
368   p.srcAddr = (void *)EDMA_MGR_ADDR_LOC_TO_GLOB(src);
369   p.dstAddr = (void *)EDMA_MGR_ADDR_LOC_TO_GLOB(dst);
371   ECPY_directConfigure(edmamgrChan->ecpyHandle, &p, 1);
373   ECPY_directSetFinal(edmamgrChan->ecpyHandle, 1);
374   ECPY_directStartEdma(edmamgrChan->ecpyHandle);
376   edmamgrChan->xferPending = TRUE;
378   return(0);
381 /*-----------------------------------------------------------*/
382 /*  This function accepts an array of transfer parameters    */
383 /*  and performs a group of 1D->1D linked transfers.         */
384 /*                                                           */
385 /*  edmamgrChan: pointer to ALG ECPY channel data structure. */
386 /*  chan_num: Channel number on which transfer is issued.    */
387 /*  src: Array of source addresses.                          */
388 /*  dst: Array of destination addresses.                     */
389 /*  num_bytes: Array of the number of bytes to transfer.     */
390 /*  num_transfers: The number of transfers to perform.       */
391 /*-----------------------------------------------------------*/
392 #if defined (EDMAMGR_INLINE_ALL)
393 static __inline
394 #endif
395 int32_t EdmaMgr_copy1D1DLinked
397   EdmaMgr_Handle    h,
398   void *restrict    src[],
399   void *restrict    dst[],
400   int32_t           num_bytes[],
401   int32_t           num_transfers
404   EdmaMgr_Channel *edmamgrChan = (EdmaMgr_Channel *)h;
405   int32_t         i, j;
406   ECPY_Params p;
408   /* Setting up the parameters for the transfer */
409   memset(&p, 0, sizeof(ECPY_Params));
410   p.transferType = ECPY_1D1D;
411   p.numFrames    = 1;
412   p.numElements  = 1;
414   for (i=0; i<num_transfers; i++)
415   {
416     j = i+1;
417     p.elementSize = num_bytes[i];
418     p.srcAddr = (void *)EDMA_MGR_ADDR_LOC_TO_GLOB(src[i]);
419     p.dstAddr = (void *)EDMA_MGR_ADDR_LOC_TO_GLOB(dst[i]);
420     ECPY_configure(edmamgrChan->ecpyHandle, &p, j);
421   }
422   ECPY_setFinal(edmamgrChan->ecpyHandle, num_transfers);
423   ECPY_start(edmamgrChan->ecpyHandle);
425   edmamgrChan->xferPending = TRUE;
427   return(0);
429 /*-----------------------------------------------------------*/
430 /*  This function accepts an array of transfer parameters    */
431 /*  and performs a group of src 1D-> dst 2D linked transfers */
432 /*                                                           */
433 /*  edmamgrChan: pointer to ALG ECPY channel data structure. */
434 /*  chan_num:   Channel number to use for transfer.          */
435 /*  src     :   Array of source addresses to use.            */
436 /*  dst     :   Array of destination addresses to use.       */
437 /*  num_bytes:  Number of bytes to transfer per line.        */
438 /*  num_lines:  Number of such lines to transfer.            */
439 /*  pitch:      Destination pitch to use between lines.      */
440 /*  num_tfrs:   Number of transfers.                         */
441 /*-----------------------------------------------------------*/
444 #if defined (EDMAMGR_INLINE_ALL)
445 static __inline
446 #endif
447 int32_t EdmaMgr_copy1D2DLinked
449   EdmaMgr_Handle    h,
450   void *restrict    src[],
451   void *restrict    dst[],
452   int32_t           num_bytes[],
453   int32_t           num_lines[],
454   int32_t           pitch[],
455   int32_t           num_transfers
458   EdmaMgr_Channel *edmamgrChan = (EdmaMgr_Channel *)h;
459   int32_t         i, j;
460   ECPY_Params p;
462   /* Setting up the parameters for the transfer */
463   memset(&p, 0, sizeof(ECPY_Params));
464   p.transferType = ECPY_1D2D;
465   p.numFrames    = 1;
467   for (i=0; i<num_transfers; i++)
468   {
469     j = i+1;
470     p.elementSize = num_bytes[i];
471     p.numElements  = num_lines[i];
472     p.srcElementIndex = num_bytes[i];
473     p.dstElementIndex = pitch[i];
474     p.srcAddr = (void *)EDMA_MGR_ADDR_LOC_TO_GLOB(src[i]);
475     p.dstAddr = (void *)EDMA_MGR_ADDR_LOC_TO_GLOB(dst[i]);
476     ECPY_configure(edmamgrChan->ecpyHandle, &p, j);
477   }
478   ECPY_setFinal(edmamgrChan->ecpyHandle, num_transfers);
479   ECPY_start(edmamgrChan->ecpyHandle);
481   edmamgrChan->xferPending = TRUE;
483   return(0);
487 /*-----------------------------------------------------------*/
488 /*  This function accepts an array of transfer parameters    */
489 /*  and performs a group of src 2D-> dst 1D linked transfers */
490 /*                                                           */
491 /*  edmamgrChan: pointer to ALG ECPY channel data structure. */
492 /*  chan_num:   Channel number to use for transfer.          */
493 /*  src     :   Array of source addresses to use.            */
494 /*  dst     :   Array of destination addresses to use.       */
495 /*  num_bytes:  Number of bytes to transfer per line.        */
496 /*  num_lines:  Number of such lines to transfer.            */
497 /*  pitch:      Source pitch to use between lines.           */
498 /*  num_tfrs:   Number of transfers.                         */
499 /*-----------------------------------------------------------*/
500 #if defined (EDMAMGR_INLINE_ALL)
501 static __inline
502 #endif
503 int32_t EdmaMgr_copy2D1DLinked
505   EdmaMgr_Handle    h,
506   void *restrict    src[],
507   void *restrict    dst[],
508   int32_t           num_bytes[],
509   int32_t           num_lines[],
510   int32_t           pitch[],
511   int32_t           num_transfers
514   EdmaMgr_Channel *edmamgrChan = (EdmaMgr_Channel *)h;
515   int32_t         i, j;
516   ECPY_Params p;
518   /* Setting up the parameters for the transfer */
519   memset(&p, 0, sizeof(ECPY_Params));
520   p.transferType = ECPY_2D1D;
521   p.numFrames    = 1;
523   for (i=0; i<num_transfers; i++)
524   {
525     j = i+1;
526     p.elementSize = num_bytes[i];
527     p.numElements  = num_lines[i];
528     p.srcElementIndex = pitch[i];
529     p.dstElementIndex = num_bytes[i];
530     p.srcAddr = (void *)EDMA_MGR_ADDR_LOC_TO_GLOB(src[i]);
531     p.dstAddr = (void *)EDMA_MGR_ADDR_LOC_TO_GLOB(dst[i]);
532     ECPY_configure(edmamgrChan->ecpyHandle, &p, j);
533   }
534   ECPY_setFinal(edmamgrChan->ecpyHandle, num_transfers);
535   ECPY_start(edmamgrChan->ecpyHandle);
537   edmamgrChan->xferPending = TRUE;
539   return(0);
541 /*-----------------------------------------------------------*/
542 /*  This function accepts an array of transfer parameters    */
543 /*  and performs a group of src 2D-> dst 2D linked transfers */
544 /*                                                           */
545 /*  edmamgrChan: pointer to ALG ECPY channel data structure. */
546 /*  chan_num:   Channel number to use for transfer.          */
547 /*  src     :   Array of source addresses to use.            */
548 /*  dst     :   Array of destination addresses to use.       */
549 /*  num_bytes:  Number of bytes to transfer per line.        */
550 /*  num_lines:  Number of such lines to transfer.            */
551 /*  pitch:      Source, Dest pitch to use between lines.     */
552 /*  num_tfrs:   Number of transfers.                         */
553 /*-----------------------------------------------------------*/
554 #if defined (EDMAMGR_INLINE_ALL)
555 static __inline
556 #endif
557 int32_t EdmaMgr_copy2D2DLinked
559   EdmaMgr_Handle    h,
560   void *restrict    src[],
561   void *restrict    dst[],
562   int32_t           num_bytes[],
563   int32_t           num_lines[],
564   int32_t           pitch[],
565   int32_t           num_transfers
568   EdmaMgr_Channel *edmamgrChan = (EdmaMgr_Channel *)h;
569   int32_t         i, j;
570   ECPY_Params p;
572   /* Setting up the parameters for the transfer */
573   memset(&p, 0, sizeof(ECPY_Params));
574   p.transferType = ECPY_2D2D;
575   p.numFrames    = 1;
577   for (i=0; i<num_transfers; i++)
578   {
579     j = i+1;
580     p.elementSize = num_bytes[i];
581     p.numElements  = num_lines[i];
582     p.srcElementIndex = pitch[i];
583     p.dstElementIndex = pitch[i];
584     p.srcAddr = (void *)EDMA_MGR_ADDR_LOC_TO_GLOB(src[i]);
585     p.dstAddr = (void *)EDMA_MGR_ADDR_LOC_TO_GLOB(dst[i]);
586     ECPY_configure(edmamgrChan->ecpyHandle, &p, j);
587   }
588   ECPY_setFinal(edmamgrChan->ecpyHandle, num_transfers);
589   ECPY_start(edmamgrChan->ecpyHandle);
591   edmamgrChan->xferPending = TRUE;
593   return(0);
596 /*-----------------------------------------------------------*/
597 /*  This function accepts an array of transfer parameters    */
598 /*  and performs a group of src 2D-> dst 2D linked transfers */
599 /*                                                           */
600 /*  edmamgrChan: pointer to ALG ECPY channel data structure. */
601 /*  chan_num:   Channel number to use for transfer.          */
602 /*  src     :   Array of source addresses to use.            */
603 /*  dst     :   Array of destination addresses to use.       */
604 /*  num_bytes:  Number of bytes to transfer per line.        */
605 /*  num_lines:  Number of such lines to transfer.            */
606 /*  pitchsrc:   Source pitch to use between lines.           */
607 /*  pitchdst:   Destination pitch to use between lines.      */
608 /*  num_tfrs:   Number of transfers.                         */
609 /*-----------------------------------------------------------*/
610 #if defined (EDMAMGR_INLINE_ALL)
611 static __inline
612 #endif
613 int32_t EdmaMgr_copy2D2DSepLinked
615   EdmaMgr_Handle    h,
616   void *restrict    src[],
617   void *restrict    dst[],
618   int32_t           num_bytes[],
619   int32_t           num_lines[],
620   int32_t           src_pitch[],
621   int32_t           dst_pitch[],
622   int32_t           num_transfers
625   EdmaMgr_Channel *edmamgrChan = (EdmaMgr_Channel *)h;
626   int32_t         i, j;
627   ECPY_Params p;
629   /* Setting up the parameters for the transfer */
630   memset(&p, 0, sizeof(ECPY_Params));
631   p.transferType = ECPY_2D2D;
632   p.numFrames    = 1;
634   for (i=0; i<num_transfers; i++)
635   {
636     j = i+1;
637     p.elementSize = num_bytes[i];
638     p.numElements  = num_lines[i];
639     p.srcElementIndex = src_pitch[i];
640     p.dstElementIndex = dst_pitch[i];
641     p.srcAddr = (void *)EDMA_MGR_ADDR_LOC_TO_GLOB(src[i]);
642     p.dstAddr = (void *)EDMA_MGR_ADDR_LOC_TO_GLOB(dst[i]);
643     ECPY_configure(edmamgrChan->ecpyHandle, &p, j);
644   }
645   ECPY_setFinal(edmamgrChan->ecpyHandle, num_transfers);
646   ECPY_start(edmamgrChan->ecpyHandle);
648   edmamgrChan->xferPending = TRUE;
650   return(0);
653 #if defined (EDMAMGR_INLINE_ALL)
654 static __inline
655 #endif
656 int32_t EdmaMgr_copyFast
658   EdmaMgr_Handle    h,
659   void *restrict    src,
660   void *restrict    dst
663   EdmaMgr_Channel *edmamgrChan = (EdmaMgr_Channel *)h;
665   ECPY_directConfigure32(edmamgrChan->ecpyHandle, ECPY_PARAMFIELD_SRCADDR,
666           (uint32_t)EDMA_MGR_ADDR_LOC_TO_GLOB(src), 1);
667   ECPY_directConfigure32(edmamgrChan->ecpyHandle, ECPY_PARAMFIELD_DSTADDR,
668           (uint32_t)EDMA_MGR_ADDR_LOC_TO_GLOB(dst), 1);
670   ECPY_directStartEdma(edmamgrChan->ecpyHandle);
672   edmamgrChan->xferPending = TRUE;
674   return (0);
678 #if defined (EDMAMGR_INLINE_ALL)
679 static __inline
680 #endif
681 int32_t EdmaMgr_copyLinkedFast
683   EdmaMgr_Handle    h,
684   void *restrict    src[],
685   void *restrict    dst[],
686   int32_t           num_transfers
689   EdmaMgr_Channel *edmamgrChan = (EdmaMgr_Channel *)h;
690   int32_t i, j;
692   for (i=0; i<num_transfers; i++)
693   {
694     j = i+1;
695     ECPY_configure32(edmamgrChan->ecpyHandle, ECPY_PARAMFIELD_SRCADDR,
696             (uint32_t)EDMA_MGR_ADDR_LOC_TO_GLOB(src[i]), j);
697     ECPY_configure32(edmamgrChan->ecpyHandle, ECPY_PARAMFIELD_DSTADDR,
698             (uint32_t)EDMA_MGR_ADDR_LOC_TO_GLOB(dst[i]), j);
699   }
700   ECPY_start(edmamgrChan->ecpyHandle);
702   edmamgrChan->xferPending = TRUE;
704   return (0);
708 /*----------------------------------------------------------*/
709 /*  The following function performs a 1D->2D transfer       */
710 /*  where the source is 1D one dimensional and destination  */
711 /*  is 2D two dimensional. This function uses channel       */
712 /*  number "chan_num" to transfer "num_lines" lines         */
713 /*  each of "num_bytes" bytes. In this case after every     */
714 /*  line of "num_bytes" is transferred, "src" source is     */
715 /*  incremeneted by "num_bytes" and "dst" destination is    */
716 /*  incremenetd by "pitch" bytes.                           */
717 /*----------------------------------------------------------*/
718 #if defined (EDMAMGR_INLINE_ALL)
719 static __inline
720 #endif
721 int32_t EdmaMgr_copy1D2DLarge
723   EdmaMgr_Handle    h,
724   void *restrict    src,
725   void *restrict    dst,
726   int32_t           num_bytes,
727   int32_t           num_lines,
728   int32_t           pitch
731   EdmaMgr_Channel *edmamgrChan = (EdmaMgr_Channel *)h;
732   ECPY_Params p;
734   /* Setting up the parameters for the transfer */
735   memset(&p, 0, sizeof(ECPY_Params));
737   if ( (pitch & (~0xFFFF)) == 0 ) {
738     /* If pitch fits in HW reg, fall back on basic 1D2D transfer */
739     p.transferType = ECPY_1D2D;
740     p.numFrames    = 1;
741     p.elementSize = num_bytes;
742     p.numElements  = num_lines;
743     p.srcElementIndex = num_bytes;
744     p.dstElementIndex = pitch;
745     p.srcAddr = (void *)EDMA_MGR_ADDR_LOC_TO_GLOB(src);
746     p.dstAddr = (void *)EDMA_MGR_ADDR_LOC_TO_GLOB(dst);
748     ECPY_directConfigure(edmamgrChan->ecpyHandle, &p, 1);
750     ECPY_directSetFinal(edmamgrChan->ecpyHandle, 1);
752   } else {
753     int32_t i;
754     uint32_t  *addrTable = (uint32_t *)edmamgrChan->addrTable.base;
755     IRES_EDMA3CHAN_PaRamStruct *paRam;
756     ECPY_Params p_0;
757     memset (&p_0, 0, sizeof(ECPY_Params));
759     /* Set address lookup table based on "dst" and "pitch" */
760     for ( i = 0; i < num_lines; i++) {
761         addrTable[i] = (uint32_t)dst + i*pitch;
762     }
764     /*
765      *  PaRAM for channel 1
766      *
767      *  This PaRAM set is responsible for populating the "dst" field of the
768      *  PaRAM set for the second channel.
769      */
771     /*
772      *  1D2D so that destination address (channel 2's PaRAM "dst" field) is
773      *  constant.
774      */
775     p_0.transferType  = ECPY_1D2D;
777     /*
778      *  elementSize is the size of "dst" address.
779      */
780     p_0.elementSize = sizeof(uint32_t);
782     /*
783      *  Transfer 1 address per synchronization event.
784      */
785     p_0.numElements = 1;
787     /*
788      *  "num_lines" is the total number of addresses to transfer as well as the
789      *  number of synchronization events.
790      */
791     p_0.numFrames   = num_lines;
793     /*
794      *  After an address is transferred, point to the next one.
795      */
796     p_0.srcElementIndex = sizeof(uint32_t);
797     p_0.srcFrameIndex = sizeof(uint32_t);
799     /*
800      *  Do not increment the destination address since the destination for the
801      *  addresses is the second channel's PaRAM which remains constant.
802      */
803     p_0.dstElementIndex = 0;
804     p_0.dstFrameIndex = 0;
806     /*
807      *  src of this channel is the lookup table
808      */
809     p_0.srcAddr = (void *)EDMA_MGR_ADDR_LOC_TO_GLOB(addrTable);
811     /*
812      *  Obtain the address to the second channel's PaRam 'dst' field, and use
813      *  that for the first channels destination.
814      */
815     paRam = (IRES_EDMA3CHAN_PaRamStruct *)edmamgrChan->chainedChannel->edmaHandle->assignedPaRamAddresses[0];
816     p_0.dstAddr = (void *)&paRam->dst; /*PaRAM for chan2 dstAddr field*/
820     /*
821      *  PaRAM for channel 2
822      *
823      *  This PaRAM set is responsible for transfer the actual data of interest.
824      *  The 'dst' field of this set will be modified by the first channel.
825      */
827     /*
828      *  2D2D transfer
829      */
830     p.transferType = ECPY_2D2D;
832     /*
833      *  Number of bytes to transfer to each dst address in lookup table.
834      */
835     p.elementSize  = num_bytes;
836     p.numElements  = 1;
838     /*
839      *  Set C CNT to num_lines since using AB-sychronization.
840      */
841     p.numFrames    = num_lines;
843     /*
844      * SRC is linearized as a 1-D vector, so increment src by num_bytes.
845      */
846     p.srcElementIndex = num_bytes;
847     p.srcFrameIndex   = num_bytes;
849     /*
850      * DST will be updated by channel 1, so automatic incrementing is not needed.
851      */
852     p.dstElementIndex = 0;
853     p.dstFrameIndex   = 0;
855     /*
856      *  Set SRC to 1-D vector.
857      */
858     p.srcAddr = (void *)EDMA_MGR_ADDR_LOC_TO_GLOB(src);
860     /*
861      *  Don't Care as DST will be updated by channel 1.
862      */
863     p.dstAddr = (void *)NULL;  /* This will be updated by p_0 */
865     /* Write Channel 1 PaRAM to HW. */
866     ECPY_directConfigure(edmamgrChan->ecpyHandle, &p_0, 1);
867     ECPY_directSetFinal(edmamgrChan->ecpyHandle, 1);
869     /* Write Channel 2 PaRAM to HW. */
870     ECPY_directConfigure(edmamgrChan->chainedChannel->ecpyHandle, &p, 1);
871     ECPY_directSetFinal(edmamgrChan->chainedChannel->ecpyHandle, 1);
873     /* Override OPT for chaining */
874     paRam = (IRES_EDMA3CHAN_PaRamStruct *)edmamgrChan->edmaHandle->assignedPaRamAddresses[0];
875     paRam->opt = edmamgrChan->optChained;
877     paRam = (IRES_EDMA3CHAN_PaRamStruct *)edmamgrChan->chainedChannel->edmaHandle->assignedPaRamAddresses[0];
878     paRam->opt = edmamgrChan->chainedChannel->optChained;
880   }
882   /* Initiate transfer */
883   ECPY_directStartEdma(edmamgrChan->ecpyHandle);
885   edmamgrChan->xferPending = TRUE;
887   return(0);
890 /*----------------------------------------------------------*/
891 /* This function performs a 2D->1D transfer by usinng the   */
892 /* channel number "chan_num" by performing a transfer from  */
893 /* source "src" to destination "dst", "num_lines" lines     */
894 /* each of "num_bytes" bytes. At the end of transferring    */
895 /* "num_bytes" bytes per line, the source is incremented    */
896 /* by "pitch" bytes and the destination is incremented by   */
897 /* "num_bytes" bytes as "src" is 2D and "dst" is 1D.        */
898 /*----------------------------------------------------------*/
899 #if defined (EDMAMGR_INLINE_ALL)
900 static __inline
901 #endif
902 int32_t EdmaMgr_copy2D1DLarge
904   EdmaMgr_Handle    h,
905   void *restrict    src,
906   void *restrict    dst,
907   int32_t           num_bytes,
908   int32_t           num_lines,
909   int32_t           pitch
912   EdmaMgr_Channel *edmamgrChan = (EdmaMgr_Channel *)h;
913   ECPY_Params p;
915   /* Setting up the parameters for the first transfer (data grp 1) */
916   memset(&p, 0, sizeof(ECPY_Params));
918   if ( (pitch & (~0xFFFF)) == 0 ) {
919     /* If pitch fits in HW reg, fall back on basic 1D2D transfer */
920     p.transferType = ECPY_2D1D;
921     p.numFrames    = 1;
922     p.elementSize = num_bytes;
923     p.numElements  = num_lines;
924     p.srcElementIndex = pitch;
925     p.dstElementIndex = num_bytes;
926     p.srcAddr = (void *)EDMA_MGR_ADDR_LOC_TO_GLOB(src);
927     p.dstAddr = (void *)EDMA_MGR_ADDR_LOC_TO_GLOB(dst);
929     ECPY_directConfigure(edmamgrChan->ecpyHandle, &p, 1);
931     ECPY_directSetFinal(edmamgrChan->ecpyHandle, 1);
932   } else {
933     int32_t i;
934     uint32_t  *addrTable = (uint32_t *)edmamgrChan->addrTable.base;
935     IRES_EDMA3CHAN_PaRamStruct *paRam;
936     ECPY_Params p_0;
937     memset (&p_0, 0, sizeof(ECPY_Params));
939     /* Set address lookup table based on "src" and "pitch" */
940     for ( i = 0; i < num_lines; i++) {
941         addrTable[i] = (uint32_t)src + i*pitch;
942     }
944     /*
945      *  PaRAM for channel 1
946      *
947      *  This PaRAM set is responsible for populating the "src" field of the
948      *  PaRAM set for the second channel.
949      */
951     /*
952      *  1D2D so that destination address (channel 2's PaRAM "src" field) is
953      *  constant.
954      */
955     p_0.transferType  = ECPY_1D2D;
957     /*
958      *  elementSize is the size of "src" address.
959      */
960     p_0.elementSize = sizeof(uint32_t);
962     /*
963      *  Transfer 1 address per synchronization event.
964      */
965     p_0.numElements = 1;
967     /*
968      *  "num_lines" is the total number of addresses to transfer as well as the
969      *  number of synchronization events.
970      */
971     p_0.numFrames   = num_lines;
973     /*
974      *  After an address is transferred, point to the next one.
975      */
976     p_0.srcElementIndex = sizeof(uint32_t);
977     p_0.srcFrameIndex = sizeof(uint32_t);
979     /*
980      *  Do not increment the destination address since the destination for the
981      *  addresses is the second channel's PaRAM which remains constant.
982      */
983     p_0.dstElementIndex = 0;
984     p_0.dstFrameIndex = 0;
986     /*
987      *  src of this channel is the lookup table
988      */
989     p_0.srcAddr = (void *)EDMA_MGR_ADDR_LOC_TO_GLOB(addrTable);
991     /*
992      *  Obtain the address to the second channel's PaRam 'src' field, and use
993      *  that for the first channels destination.
994      */
995     paRam = (IRES_EDMA3CHAN_PaRamStruct *)edmamgrChan->chainedChannel->edmaHandle->assignedPaRamAddresses[0];
996     p_0.dstAddr = (void *)&paRam->src; /*PaRAM for chan2 srcAddr field*/
1000     /*
1001      *  PaRAM for channel 2
1002      *
1003      *  This PaRAM set is responsible for transfer the actual data of interest.
1004      *  The 'src' field of this set will be modified by the first channel.
1005      */
1007     /*
1008      *  2D2D transfer
1009      */
1010     p.transferType = ECPY_2D2D;
1012     /*
1013      *  Number of bytes to transfer from each src address in lookup table.
1014      */
1015     p.elementSize  = num_bytes;
1016     p.numElements  = 1;
1018     /*
1019      *  Set C CNT to num_lines since using AB-sychronization.
1020      */
1021     p.numFrames    = num_lines;
1023     /*
1024      * SRC will be updated by channel 1, so automatic incrementing is not needed.
1025      */
1026     p.srcElementIndex = 0;
1027     p.srcFrameIndex   = 0;
1029     /*
1030      * DST is linearized as a 1-D vector, so increment DST by num_bytes.
1031      */
1032     p.dstElementIndex = num_bytes;
1033     p.dstFrameIndex   = num_bytes;
1035     /*
1036      *  Don't Care as SRC will be updated by channel 1.
1037      */
1038     p.srcAddr = (void *)NULL;  /* This will be updated by p_0 */
1040     /*
1041      *  Set DST to 1-D vector.
1042      */
1043     p.dstAddr = (void *)EDMA_MGR_ADDR_LOC_TO_GLOB(dst);
1045     /* Write Channel 1 PaRAM to HW. */
1046     ECPY_directConfigure(edmamgrChan->ecpyHandle, &p_0, 1);
1047     ECPY_directSetFinal(edmamgrChan->ecpyHandle, 1);
1049     /* Write Channel 2 PaRAM to HW. */
1050     ECPY_directConfigure(edmamgrChan->chainedChannel->ecpyHandle, &p, 1);
1051     ECPY_directSetFinal(edmamgrChan->chainedChannel->ecpyHandle, 1);
1053     /* Override OPT for chaining */
1054     paRam = (IRES_EDMA3CHAN_PaRamStruct *)edmamgrChan->edmaHandle->assignedPaRamAddresses[0];
1055     paRam->opt = edmamgrChan->optChained;
1057     paRam = (IRES_EDMA3CHAN_PaRamStruct *)edmamgrChan->chainedChannel->edmaHandle->assignedPaRamAddresses[0];
1058     paRam->opt = edmamgrChan->chainedChannel->optChained;
1060   }
1062   /* Initiate transfer */
1063   ECPY_directStartEdma(edmamgrChan->ecpyHandle);
1065   edmamgrChan->xferPending = TRUE;
1067   return(0);
1071 #endif /* ti_sdo_fc_edmamgr_EdmaMgr_XFER_ */
1073 #else
1074 #error "ti/sdo/fc/edmamgr/edmamgr.h must be included first"
1075 #endif