原文:http://blog.csdn.net/kickxxx/archive/2011/06/22/6561804.aspx
这个函数很长,很简单,都是对ipu common函数的封装,先去分析ipu_common.c
这个文件创建了一个mxc_ipu字符设备节点,目的是为了ipu lib服务的,主要函数就是mxc_ipu_ioctl, app可以利用ipu lib实现如下功能:
474 int register_ipu_device()
475 {
476 int ret = 0;
477 struct device *temp;
478 mxc_ipu_major = register_chrdev(0, "mxc_ipu", &mxc_ipu_fops);
.................
510 }
478注册一个字符设备,应用通过/dev/mxc_ipu这个设备节点,操作IPU的channel,实现上述功能
87 static int mxc_ipu_ioctl(struct inode *inode, struct file *file,
88 unsigned int cmd, unsigned long arg)
89 {
90 int ret = 0;
91
92 switch (cmd) {
93 case IPU_INIT_CHANNEL:
94 {
95 ipu_channel_parm parm;
96
97 if (copy_from_user
98 (&parm, (ipu_channel_parm *) arg,
99 sizeof(ipu_channel_parm)))
100 return -EFAULT;
101
102 if (!parm.flag) {
103 ret =
104 ipu_init_channel(parm.channel,
105 &parm.params);
106 } else {
107 ret = ipu_init_channel(parm.channel, NULL);
108 }
109 }
110 break;
111 case IPU_UNINIT_CHANNEL:
112 {
113 ipu_channel_t ch;
114 int __user *argp = (void __user *)arg;
115 if (get_user(ch, argp))
116 return -EFAULT;
117 ipu_uninit_channel(ch);
118 }
119 break;
120 case IPU_INIT_CHANNEL_BUFFER:
121 {
122 ipu_channel_buf_parm parm;
123 if (copy_from_user
124 (&parm, (ipu_channel_buf_parm *) arg,
125 sizeof(ipu_channel_buf_parm)))
126 return -EFAULT;
127
128 ret =
129 ipu_init_channel_buffer(
130 parm.channel, parm.type,
131 parm.pixel_fmt,
132 parm.width, parm.height,
133 parm.stride,
134 parm.rot_mode,
135 parm.phyaddr_0,
136 parm.phyaddr_1,
137 parm.u_offset,
138 parm.v_offset);
139
140 }
141 break;
142 case IPU_UPDATE_CHANNEL_BUFFER:
143 {
144 ipu_channel_buf_parm parm;
145 if (copy_from_user
146 (&parm, (ipu_channel_buf_parm *) arg,
147 sizeof(ipu_channel_buf_parm)))
148 return -EFAULT;
149
150 if ((parm.phyaddr_0 != (dma_addr_t) NULL)
151 && (parm.phyaddr_1 == (dma_addr_t) NULL)) {
152 ret =
153 ipu_update_channel_buffer(
154 parm.channel,
155 parm.type,
156 parm.bufNum,
157 parm.phyaddr_0);
158 } else if ((parm.phyaddr_0 == (dma_addr_t) NULL)
159 && (parm.phyaddr_1 != (dma_addr_t) NULL)) {
160 ret =
161 ipu_update_channel_buffer(
162 parm.channel,
163 parm.type,
164 parm.bufNum,
165 parm.phyaddr_1);
166 } else {
167 ret = -1;
168 }
169
170 }
171 break;
172 case IPU_SELECT_CHANNEL_BUFFER:
173 {
174 ipu_channel_buf_parm parm;
175 if (copy_from_user
176 (&parm, (ipu_channel_buf_parm *) arg,
177 sizeof(ipu_channel_buf_parm)))
178 return -EFAULT;
179
180 ret =
181 ipu_select_buffer(parm.channel,
182 parm.type, parm.bufNum);
183
184 }
185 break;
186 case IPU_SELECT_MULTI_VDI_BUFFER:
187 {
188 uint32_t parm;
189 if (copy_from_user
190 (&parm, (uint32_t *) arg,
191 sizeof(uint32_t)))
192 return -EFAULT;
193
194 ret = ipu_select_multi_vdi_buffer(parm);
195 }
196 break;
197 case IPU_LINK_CHANNELS:
198 {
199 ipu_channel_link link;
200 if (copy_from_user
201 (&link, (ipu_channel_link *) arg,
202 sizeof(ipu_channel_link)))
203 return -EFAULT;
204
205 ret = ipu_link_channels(link.src_ch,
206 link.dest_ch);
207
208 }
209 break;
210 case IPU_UNLINK_CHANNELS:
211 {
212 ipu_channel_link link;
213 if (copy_from_user
214 (&link, (ipu_channel_link *) arg,
215 sizeof(ipu_channel_link)))
216 return -EFAULT;
217
218 ret = ipu_unlink_channels(link.src_ch,
219 link.dest_ch);
220
221 }
222 break;
223 case IPU_ENABLE_CHANNEL:
224 {
225 ipu_channel_t ch;
226 int __user *argp = (void __user *)arg;
227 if (get_user(ch, argp))
228 return -EFAULT;
229 ipu_enable_channel(ch);
230 }
231 break;
232 case IPU_DISABLE_CHANNEL:
233 {
234 ipu_channel_info info;
235 if (copy_from_user
236 (&info, (ipu_channel_info *) arg,
237 sizeof(ipu_channel_info)))
238 return -EFAULT;
239
240 ret = ipu_disable_channel(info.channel,
241 info.stop);
242 }
243 break;
244 case IPU_ENABLE_IRQ:
245 {
246 uint32_t irq;
247 int __user *argp = (void __user *)arg;
248 if (get_user(irq, argp))
249 return -EFAULT;
250 ipu_enable_irq(irq);
251 }
252 break;
253 case IPU_DISABLE_IRQ:
254 {
255 uint32_t irq;
256 int __user *argp = (void __user *)arg;
257 if (get_user(irq, argp))
258 return -EFAULT;
259 ipu_disable_irq(irq);
260 }
261 break;
262 case IPU_CLEAR_IRQ:
263 {
264 uint32_t irq;
265 int __user *argp = (void __user *)arg;
266 if (get_user(irq, argp))
267 return -EFAULT;
268 ipu_clear_irq(irq);
269 }
270 break;
271 case IPU_FREE_IRQ:
272 {
273 ipu_irq_info info;
274
275 if (copy_from_user
276 (&info, (ipu_irq_info *) arg,
277 sizeof(ipu_irq_info)))
278 return -EFAULT;
279
280 ipu_free_irq(info.irq, info.dev_id);
281 irq_info[info.irq].irq_pending = 0;
282 }
283 break;
284 case IPU_REQUEST_IRQ_STATUS:
285 {
286 uint32_t irq;
287 int __user *argp = (void __user *)arg;
288 if (get_user(irq, argp))
289 return -EFAULT;
290 ret = ipu_get_irq_status(irq);
291 }
292 break;
293 case IPU_REGISTER_GENERIC_ISR:
294 {
295 ipu_event_info info;
296 if (copy_from_user
297 (&info, (ipu_event_info *) arg,
298 sizeof(ipu_event_info)))
299 return -EFAULT;
300
301 ret =
302 ipu_request_irq(info.irq,
303 mxc_ipu_generic_handler,
304 0, "video_sink", info.dev);
305 if (ret == 0)
306 init_waitqueue_head(&(irq_info[info.irq].waitq));
307 }
308 break;
309 case IPU_GET_EVENT:
310 /* User will have to allocate event_type
311 structure and pass the pointer in arg */
312 {
313 ipu_event_info info;
314 int r = -1;
315
316 if (copy_from_user
317 (&info, (ipu_event_info *) arg,
318 sizeof(ipu_event_info)))
319 return -EFAULT;
320
321 r = get_events(&info);
322 if (r == -1) {
323 if ((file->f_flags & O_NONBLOCK) &&
324 (irq_info[info.irq].irq_pending == 0))
325 return -EAGAIN;
326 wait_event_interruptible_timeout(irq_info[info.irq].waitq,
327 (irq_info[info.irq].irq_pending != 0), 2 * HZ);
328 r = get_events(&info);
329 }
330 ret = -1;
331 if (r == 0) {
332 if (!copy_to_user((ipu_event_info *) arg,
333 &info, sizeof(ipu_event_info)))
334 ret = 0;
335 }
336 }
337 break;
338 case IPU_ALOC_MEM:
339 {
340 ipu_mem_info info;
341 if (copy_from_user
342 (&info, (ipu_mem_info *) arg,
343 sizeof(ipu_mem_info)))
344 return -EFAULT;
345
346 info.vaddr = dma_alloc_coherent(0,
347 PAGE_ALIGN(info.size),
348 &info.paddr,
349 GFP_DMA | GFP_KERNEL);
350 if (info.vaddr == 0) {
351 printk(KERN_ERR "dma alloc failed!/n");
352 return -ENOBUFS;
353 }
354 if (copy_to_user((ipu_mem_info *) arg, &info,
355 sizeof(ipu_mem_info)) > 0)
356 return -EFAULT;
357 }
358 break;
359 case IPU_FREE_MEM:
360 {
361 ipu_mem_info info;
362 if (copy_from_user
363 (&info, (ipu_mem_info *) arg,
364 sizeof(ipu_mem_info)))
365 return -EFAULT;
366
367 if (info.vaddr)
368 dma_free_coherent(0, PAGE_ALIGN(info.size),
369 info.vaddr, info.paddr);
370 else
371 return -EFAULT;
372 }
373 break;
374 case IPU_IS_CHAN_BUSY:
375 {
376 ipu_channel_t chan;
377 if (copy_from_user
378 (&chan, (ipu_channel_t *)arg,
379 sizeof(ipu_channel_t)))
380 return -EFAULT;
381
382 if (ipu_is_channel_busy(chan))
383 ret = 1;
384 else
385 ret = 0;
386 }
387 break;
388 case IPU_CALC_STRIPES_SIZE:
389 {
390 ipu_stripe_parm stripe_parm;
391
392 if (copy_from_user (&stripe_parm, (ipu_stripe_parm *)arg,
393 sizeof(ipu_stripe_parm)))
394 return -EFAULT;
395 ipu_calc_stripes_sizes(stripe_parm.input_width,
396 stripe_parm.output_width,
397 stripe_parm.maximal_stripe_width,
398 stripe_parm.cirr,
399 stripe_parm.equal_stripes,
400 stripe_parm.input_pixelformat,
401 stripe_parm.output_pixelformat,
402 &stripe_parm.left,
403 &stripe_parm.right);
404 if (copy_to_user((ipu_stripe_parm *) arg, &stripe_parm,
405 sizeof(ipu_stripe_parm)) > 0)
406 return -EFAULT;
407 }
408 break;
409 case IPU_UPDATE_BUF_OFFSET:
410 {
411 ipu_buf_offset_parm offset_parm;
412
413 if (copy_from_user (&offset_parm, (ipu_buf_offset_parm *)arg,
414 sizeof(ipu_buf_offset_parm)))
415 return -EFAULT;
416 ret = ipu_update_channel_offset(offset_parm.channel,
417 offset_parm.type,
418 offset_parm.pixel_fmt,
419 offset_parm.width,
420 offset_parm.height,
421 offset_parm.stride,
422 offset_parm.u_offset,
423 offset_parm.v_offset,
424 offset_parm.vertical_offset,
425 offset_parm.horizontal_offset);
426 }
427 break;
428 case IPU_CSC_UPDATE:
429 {
430 int param[5][3];
431 ipu_csc_update csc;
432 if (copy_from_user(&csc, (void *) arg,
433 sizeof(ipu_csc_update)))
434 return -EFAULT;
435 if (copy_from_user(¶m[0][0], (void *) csc.param,
436 sizeof(param)))
437 return -EFAULT;
438 ipu_set_csc_coefficients(csc.channel, param);
439 }
440 break;
441 default:
442 break;
443 }
444 return ret;
445 }