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(¶ms, 0, sizeof(params));
147
148 ipu_ch_param_set_field(¶ms, 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(¶ms, 0, 138, 12, (height / 2) - 1);
152 ipu_ch_param_set_field(¶ms, 1, 102, 14, (stride * 2) - 1);
153 } else {
154 ipu_ch_param_set_field(¶ms, 0, 138, 12, height - 1);
155 ipu_ch_param_set_field(¶ms, 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(¶ms, 1, 0, 29, addr0 >> 3);
160 ipu_ch_param_set_field(¶ms, 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(¶ms, 0, 107, 3, 5); /* bits/pixel */
172 ipu_ch_param_set_field(¶ms, 1, 85, 4, 6); /* pix format */
173 ipu_ch_param_set_field(¶ms, 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(¶ms, 0, 107, 3, 3); /* bits/pixel */
181 ipu_ch_param_set_field(¶ms, 1, 85, 4, 7); /* pix format */
182 ipu_ch_param_set_field(¶ms, 1, 78, 7, 15); /* burst size */
183
184 _ipu_ch_params_set_packing(¶ms, 5, 0, 6, 5, 5, 11, 8, 16);
185 break;
186 case IPU_PIX_FMT_BGR24:
187 ipu_ch_param_set_field(¶ms, 0, 107, 3, 1); /* bits/pixel */
188 ipu_ch_param_set_field(¶ms, 1, 85, 4, 7); /* pix format */
189 ipu_ch_param_set_field(¶ms, 1, 78, 7, 19); /* burst size */
190
191 _ipu_ch_params_set_packing(¶ms, 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(¶ms, 0, 107, 3, 1); /* bits/pixel */
196 ipu_ch_param_set_field(¶ms, 1, 85, 4, 7); /* pix format */
197 ipu_ch_param_set_field(¶ms, 1, 78, 7, 19); /* burst size */
198
199 _ipu_ch_params_set_packing(¶ms, 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(¶ms, 0, 107, 3, 0); /* bits/pixel */
204 ipu_ch_param_set_field(¶ms, 1, 85, 4, 7); /* pix format */
205 ipu_ch_param_set_field(¶ms, 1, 78, 7, 15); /* burst size */
206
207 _ipu_ch_params_set_packing(¶ms, 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(¶ms, 0, 107, 3, 0); /* bits/pixel */
212 ipu_ch_param_set_field(¶ms, 1, 85, 4, 7); /* pix format */
213 ipu_ch_param_set_field(¶ms, 1, 78, 7, 15); /* burst size */
214
215 _ipu_ch_params_set_packing(¶ms, 8, 24, 8, 16, 8, 8, 8, 0);
216 break;
217 case IPU_PIX_FMT_ABGR32:
218 ipu_ch_param_set_field(¶ms, 0, 107, 3, 0); /* bits/pixel */
219 ipu_ch_param_set_field(¶ms, 1, 85, 4, 7); /* pix format */
220 ipu_ch_param_set_field(¶ms, 1, 78, 7, 15); /* burst size */
221
222 _ipu_ch_params_set_packing(¶ms, 8, 0, 8, 8, 8, 16, 8, 24);
223 break;
224 case IPU_PIX_FMT_UYVY:
225 ipu_ch_param_set_field(¶ms, 0, 107, 3, 3); /* bits/pixel */
226 ipu_ch_param_set_field(¶ms, 1, 85, 4, 0xA); /* pix format */
227 if ((ch == 8) || (ch == 9) || (ch == 10)) {
228 ipu_ch_param_set_field(¶ms, 1, 78, 7, 15); /* burst size */
229 } else {
230 ipu_ch_param_set_field(¶ms, 1, 78, 7, 31); /* burst size */
231 }
232 break;
233 case IPU_PIX_FMT_YUYV:
234 ipu_ch_param_set_field(¶ms, 0, 107, 3, 3); /* bits/pixel */
235 ipu_ch_param_set_field(¶ms, 1, 85, 4, 0x8); /* pix format */
236 if ((ch == 8) || (ch == 9) || (ch == 10)) {
237 ipu_ch_param_set_field(¶ms, 1, 78, 7, 15); /* burst size */
238 } else {
239 ipu_ch_param_set_field(¶ms, 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(¶ms, 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(¶ms, 1, 78, 7, 15); /* burst size */
253 uv_stride = uv_stride*2;
254 } else {
255 ipu_ch_param_set_field(¶ms, 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(¶ms, 1, 85, 4, 1); /* pix format */
261 ipu_ch_param_set_field(¶ms, 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(¶ms, 1, 85, 4, 1); /* pix format */
272 ipu_ch_param_set_field(¶ms, 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(¶ms, 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(¶ms, 1, 78, 7, 15); /* burst size */
287 uv_stride = uv_stride*2;
288 } else {
289 ipu_ch_param_set_field(¶ms, 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(¶ms, 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(¶ms, 0, 46, 22, u_offset / 8);
323 ipu_ch_param_set_field(¶ms, 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), ¶ms, 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 };