freescale R10 ipu lib 分析 - ipu_device.c

ipu_device.c

这个文件创建了一个mxc_ipu字符设备节点,目的是为了ipu lib服务的,主要函数就是mxc_ipu_ioctl,  app可以利用ipu lib实现如下功能:

  1. Resize
  2. Rotation
  3. Color space/format convert
  4. Overlay combination with the same size which supports color ker and alpha blending
  5. Output display to frame buffer directly after IPU process
  6. Two outputs processed form one input
  7. Windows crop
  8. Local alpha blending

 

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(&param[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 }

 

这个函数很长,很简单,都是对ipu common函数的封装,先去分析ipu_common.c

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值