freescale R10 ipu lib 分析 - ipu_param_mem.h

来源:互联网 发布:windows errorcode 编辑:程序博客网 时间:2024/04/28 05:57

原文地址:http://blog.csdn.net/kickxxx/archive/2011/06/24/6566121.aspx

作者:kickxxx
ipu_param_mem.h

 21 struct ipu_ch_param_word {
 22     uint32_t data[5];
 23     uint32_t res[3];
 24 };

 26 struct ipu_ch_param {
 27     struct ipu_ch_param_word word[2];
 28 };

每个ipu channel 都对应着两个mega-words, 一个mega word大小是160bits, 也就是5x32bits,

 30 #define ipu_ch_param_addr(ch) (((struct ipu_ch_param *)ipu_cpmem_base) + (ch))

但是每个word都是8x32bits对齐的, 因此23行增加了res[3]

 32 #define _param_word(base, w) /
 33     (((struct ipu_ch_param *)(base))->word[(w)].data)

base 是channel number,w=0 channel parameters第一个mega word; w=1 第二个mega word

 35 #define ipu_ch_param_set_field(base, w, bit, size, v) { /
 36     int i = (bit) / 32; /
 37     int off = (bit) % 32; /
 38     _param_word(base, w)[i] |= (v) << off; /
 39     if (((bit)+(size)-1)/32 > i) { /
 40         _param_word(base, w)[i + 1] |= (v) >> (off ? (32 - off) : 0); /
 41     } /
 42 }

@base: channel  number

@w: channel param entry index

@bit: 160bits中的位数

@size: 要设置的位数

@val:

向指定channel parameter @base, 指定entry index@w 指定位置bit, 指定长度@size, 或上指定值@v

 44 #define ipu_ch_param_mod_field(base, w, bit, size, v) { /
 45     int i = (bit) / 32; /
 46     int off = (bit) % 32; /
 47     u32 mask = (1UL << size) - 1; /
 48     u32 temp = _param_word(base, w)[i]; /
 49     temp &= ~(mask << off); /
 50     _param_word(base, w)[i] = temp | (v) << off; /
 51     if (((bit)+(size)-1)/32 > i) { /
 52         temp = _param_word(base, w)[i + 1]; /
 53         temp &= ~(mask >> (32 - off)); /
 54         _param_word(base, w)[i + 1] = /
 55             temp | ((v) >> (off ? (32 - off) : 0)); /
 56     } /
 57 }
向指定channel parameter @base, 指定entry index@w 指定位置bit, 指定长度@size, 写入指定值@v

这个宏和ipu_ch_param_set_field的区别就是前者写入@v,而后者要用@v或上原来值

 59 #define ipu_ch_param_read_field(base, w, bit, size) ({ /
 60     u32 temp2; /
 61     int i = (bit) / 32; /
 62     int off = (bit) % 32; /
 63     u32 mask = (1UL << size) - 1; /
 64     u32 temp1 = _param_word(base, w)[i]; /
 65     temp1 = mask & (temp1 >> off); /
 66     if (((bit)+(size)-1)/32 > i) { /
 67         temp2 = _param_word(base, w)[i + 1]; /
 68         temp2 &= mask >> (off ? (32 - off) : 0); /
 69         temp1 |= temp2 << (off ? (32 - off) : 0); /
 70     } /
 71     temp1; /
 72 })
读出channel paremeter的值,返回值存放在temp1中

135 static inline void _ipu_ch_param_init(int ch,
136                       uint32_t pixel_fmt, uint32_t width,
137                       uint32_t height, uint32_t stride,
138                       uint32_t u, uint32_t v,
139                       uint32_t uv_stride, dma_addr_t addr0,
140                       dma_addr_t addr1)
141 {
142     uint32_t u_offset = 0;
143     uint32_t v_offset = 0;
144     struct ipu_ch_param params;
145 
146     memset(&params, 0, sizeof(params));
147 
148     ipu_ch_param_set_field(&params, 0, 125, 13, width - 1);

设置frame width,在mx51文档,并没说明FW保存的是frame width minus 1, 但是这里却设置为width-1

149 
150     if ((ch == 8) || (ch == 9) || (ch == 10)) {
151         ipu_ch_param_set_field(&params, 0, 138, 12, (height / 2) - 1);
152         ipu_ch_param_set_field(&params, 1, 102, 14, (stride * 2) - 1);
153     } else {
154         ipu_ch_param_set_field(&params, 0, 138, 12, height - 1);
155         ipu_ch_param_set_field(&params, 1, 102, 14, stride - 1);
156     }
157

chanel 8, 9, 10是Fmem->VDI, 没明白为什么这样设置


158     /* EBA is 8-byte aligned */
159     ipu_ch_param_set_field(&params, 1, 0, 29, addr0 >> 3);
160     ipu_ch_param_set_field(&params, 1, 29, 29, addr1 >> 3);
161     if (addr0%8)
162         dev_warn(g_ipu_dev,
163              "IDMAC%d's EBA0 is not 8-byte aligned/n", ch);
164     if (addr1%8)
165         dev_warn(g_ipu_dev,
166              "IDMAC%d's EBA1 is not 8-byte aligned/n", ch);

存放double buffer destination address 的bit3~bit31,  因此这两个地址应该是8 bytes对齐的


167 
168     switch (pixel_fmt) {
169     case IPU_PIX_FMT_GENERIC:
170         /*Represents 8-bit Generic data */
171         ipu_ch_param_set_field(&params, 0, 107, 3, 5);  /* bits/pixel */
172         ipu_ch_param_set_field(&params, 1, 85, 4, 6);   /* pix format */
173         ipu_ch_param_set_field(&params, 1, 78, 7, 63);  /* burst size */

174

(0,107)是BPP; (1, 85)是PFS Pixel Format Select; (1, 78)是Number of pixel in whole burst access

175         break;
176     case IPU_PIX_FMT_GENERIC_32:
177         /*Represents 32-bit Generic data */
178         break;
179     case IPU_PIX_FMT_RGB565:

180         ipu_ch_param_set_field(&params, 0, 107, 3, 3);  /* bits/pixel */
181         ipu_ch_param_set_field(&params, 1, 85, 4, 7);   /* pix format */
182         ipu_ch_param_set_field(&params, 1, 78, 7, 15);  /* burst size */
183 
184         _ipu_ch_params_set_packing(&params, 5, 0, 6, 5, 5, 11, 8, 16);
185         break;
186     case IPU_PIX_FMT_BGR24:
187         ipu_ch_param_set_field(&params, 0, 107, 3, 1);  /* bits/pixel */
188         ipu_ch_param_set_field(&params, 1, 85, 4, 7);   /* pix format */
189         ipu_ch_param_set_field(&params, 1, 78, 7, 19);  /* burst size */
190 
191         _ipu_ch_params_set_packing(&params, 8, 0, 8, 8, 8, 16, 8, 24);
192         break;
193     case IPU_PIX_FMT_RGB24:
194     case IPU_PIX_FMT_YUV444:
195         ipu_ch_param_set_field(&params, 0, 107, 3, 1);  /* bits/pixel */
196         ipu_ch_param_set_field(&params, 1, 85, 4, 7);   /* pix format */
197         ipu_ch_param_set_field(&params, 1, 78, 7, 19);  /* burst size */
198 
199         _ipu_ch_params_set_packing(&params, 8, 16, 8, 8, 8, 0, 8, 24);
200         break;
201     case IPU_PIX_FMT_BGRA32:
202     case IPU_PIX_FMT_BGR32:
203         ipu_ch_param_set_field(&params, 0, 107, 3, 0);  /* bits/pixel */
204         ipu_ch_param_set_field(&params, 1, 85, 4, 7);   /* pix format */
205         ipu_ch_param_set_field(&params, 1, 78, 7, 15);  /* burst size */
206 
207         _ipu_ch_params_set_packing(&params, 8, 8, 8, 16, 8, 24, 8, 0);
208         break;
209     case IPU_PIX_FMT_RGBA32:
210     case IPU_PIX_FMT_RGB32:
211         ipu_ch_param_set_field(&params, 0, 107, 3, 0);  /* bits/pixel */
212         ipu_ch_param_set_field(&params, 1, 85, 4, 7);   /* pix format */
213         ipu_ch_param_set_field(&params, 1, 78, 7, 15);  /* burst size */
214 
215         _ipu_ch_params_set_packing(&params, 8, 24, 8, 16, 8, 8, 8, 0);
216         break;
217     case IPU_PIX_FMT_ABGR32:
218         ipu_ch_param_set_field(&params, 0, 107, 3, 0);  /* bits/pixel */
219         ipu_ch_param_set_field(&params, 1, 85, 4, 7);   /* pix format */
220         ipu_ch_param_set_field(&params, 1, 78, 7, 15);  /* burst size */
221 
222         _ipu_ch_params_set_packing(&params, 8, 0, 8, 8, 8, 16, 8, 24);
223         break;
224     case IPU_PIX_FMT_UYVY:
225         ipu_ch_param_set_field(&params, 0, 107, 3, 3);  /* bits/pixel */
226         ipu_ch_param_set_field(&params, 1, 85, 4, 0xA); /* pix format */
227         if ((ch == 8) || (ch == 9) || (ch == 10)) {
228             ipu_ch_param_set_field(&params, 1, 78, 7, 15);  /* burst size */
229         } else {
230             ipu_ch_param_set_field(&params, 1, 78, 7, 31);  /* burst size */
231         }
232         break;
233     case IPU_PIX_FMT_YUYV:
234         ipu_ch_param_set_field(&params, 0, 107, 3, 3);  /* bits/pixel */
235         ipu_ch_param_set_field(&params, 1, 85, 4, 0x8); /* pix format */
236         if ((ch == 8) || (ch == 9) || (ch == 10)) {
237             ipu_ch_param_set_field(&params, 1, 78, 7, 15);  /* burst size */
238         } else {
239             ipu_ch_param_set_field(&params, 1, 78, 7, 31);  /* burst size */
240         }
241         break;
242     case IPU_PIX_FMT_YUV420P2:
243     case IPU_PIX_FMT_YUV420P:
244         ipu_ch_param_set_field(&params, 1, 85, 4, 2);   /* pix format */
245 
246         if (uv_stride < stride / 2)
247             uv_stride = stride / 2;
248 
249         u_offset = stride * height;
250         v_offset = u_offset + (uv_stride * height / 2);
251         if ((ch == 8) || (ch == 9) || (ch == 10)) {
252             ipu_ch_param_set_field(&params, 1, 78, 7, 15);  /* burst size */
253             uv_stride = uv_stride*2;
254         } else {
255             ipu_ch_param_set_field(&params, 1, 78, 7, 31);  /* burst size */
256         }
257         break;
258     case IPU_PIX_FMT_YVU422P:
259         /* BPP & pixel format */
260         ipu_ch_param_set_field(&params, 1, 85, 4, 1);   /* pix format */
261         ipu_ch_param_set_field(&params, 1, 78, 7, 31);  /* burst size */
262 
263         if (uv_stride < stride / 2)
264             uv_stride = stride / 2;
265 
266         v_offset = (v == 0) ? stride * height : v;
267         u_offset = (u == 0) ? v_offset + v_offset / 2 : u;
268         break;
269     case IPU_PIX_FMT_YUV422P:

270         /* BPP & pixel format */
271         ipu_ch_param_set_field(&params, 1, 85, 4, 1);   /* pix format */
272         ipu_ch_param_set_field(&params, 1, 78, 7, 31);  /* burst size */
273 
274         if (uv_stride < stride / 2)
275             uv_stride = stride / 2;
276 
277         u_offset = (u == 0) ? stride * height : u;
278         v_offset = (v == 0) ? u_offset + u_offset / 2 : v;
279         break;
280     case IPU_PIX_FMT_NV12:
281         /* BPP & pixel format */
282         ipu_ch_param_set_field(&params, 1, 85, 4, 4);   /* pix format */
283         uv_stride = stride;
284         u_offset = (u == 0) ? stride * height : u;
285         if ((ch == 8) || (ch == 9) || (ch == 10)) {
286             ipu_ch_param_set_field(&params, 1, 78, 7, 15);  /* burst size */
287             uv_stride = uv_stride*2;
288         } else {
289             ipu_ch_param_set_field(&params, 1, 78, 7, 31);  /* burst size */
290         }
291         break;
292     default:
293         dev_err(g_ipu_dev, "mxc ipu: unimplemented pixel format/n");
294         break;
295     }
296     /*set burst size to 16*/
297 
298 
299     if (uv_stride)
300         ipu_ch_param_set_field(&params, 1, 128, 14, uv_stride - 1);

设置SLUV大小(每行包含的UV长度) yuv422 SLUV=SL; yuv420 SLUV=SL/2

301 
302     /* Get the uv offset from user when need cropping */
303     if (u || v) {
304         u_offset = u;
305         v_offset = v;
306     }
307 
308     /* UBO and VBO are 22-bit and 8-byte aligned */
309     if (u_offset/8 > 0x3fffff)
310         dev_warn(g_ipu_dev,
311              "IDMAC%d's U offset exceeds IPU limitation/n", ch);
312     if (v_offset/8 > 0x3fffff)
313         dev_warn(g_ipu_dev,
314              "IDMAC%d's V offset exceeds IPU limitation/n", ch);
315     if (u_offset%8)
316         dev_warn(g_ipu_dev,
317              "IDMAC%d's U offset is not 8-byte aligned/n", ch);
318     if (v_offset%8)
319         dev_warn(g_ipu_dev,
320              "IDMAC%d's V offset is not 8-byte aligned/n", ch);
321 
322     ipu_ch_param_set_field(&params, 0, 46, 22, u_offset / 8);
323     ipu_ch_param_set_field(&params, 0, 68, 22, v_offset / 8);
324 
325     pr_debug("initializing idma ch %d @ %p/n", ch, ipu_ch_param_addr(ch));
326     memcpy(ipu_ch_param_addr(ch), &params, sizeof(params));
327 };

329 static inline void _ipu_ch_param_set_burst_size(uint32_t ch,
330                         uint16_t burst_pixels)
331 {
332     ipu_ch_param_mod_field(ipu_ch_param_addr(ch), 1, 78, 7,
333                    burst_pixels - 1);
334 };

设置channel的burst access size

341 static inline int _ipu_ch_param_get_bpp(uint32_t ch)
342 {
343     return ipu_ch_param_read_field(ipu_ch_param_addr(ch), 0, 107, 3);
344 };

为什么只有interlaced模式有BPP, 而non-interlaced没有BPP

346 static inline void _ipu_ch_param_set_buffer(uint32_t ch, int bufNum,
347                         dma_addr_t phyaddr)
348 {
349     ipu_ch_param_mod_field(ipu_ch_param_addr(ch), 1, 29 * bufNum, 29,
350                    phyaddr / 8);
351 };

设置EBA0(Ext buffer address) EBA1

353 static inline void _ipu_ch_param_set_rotation(uint32_t ch,
354                           ipu_rotate_mode_t rot)
355 {
356     u32 temp_rot = bitrev8(rot) >> 5;
357     ipu_ch_param_mod_field(ipu_ch_param_addr(ch), 0, 119, 3, temp_rot);
358 };

119 120 121分别对应90 degree roration, horizition flip, vertical flip

406 static inline void _ipu_ch_param_set_interlaced_scan(uint32_t ch)
407 {
408     u32 stride;
409     ipu_ch_param_set_field(ipu_ch_param_addr(ch), 0, 113, 1, 1);
410     stride = ipu_ch_param_read_field(ipu_ch_param_addr(ch), 1, 102, 14) + 1;
411     /* ILO is 20-bit and 8-byte aligned */
412     if (stride/8 > 0xfffff)
413         dev_warn(g_ipu_dev,
414              "IDMAC%d's ILO exceeds IPU limitation/n", ch);
415     if (stride%8)
416         dev_warn(g_ipu_dev,
417              "IDMAC%d's ILO is not 8-byte aligned/n", ch);
418     ipu_ch_param_mod_field(ipu_ch_param_addr(ch), 1, 58, 20, stride / 8);
419     stride *= 2;
420     ipu_ch_param_mod_field(ipu_ch_param_addr(ch), 1, 102, 14, stride - 1);
421 };

设置dma scan order, channel will do de-interlaced

行409 对于interlaced的channel,第0word的113位定义了scan order: 0 is progressive, 1 is interlaced

行410 获取stride width per line, 需要加1, 因为param存放的是stride line minus 1

423 static inline void _ipu_ch_param_set_high_priority(uint32_t ch)
424 {
425     ipu_ch_param_mod_field(ipu_ch_param_addr(ch), 1, 93, 2, 1);
426 };

原创粉丝点击