omap24xxvout.c
来自「omap3 linux 2.6 用nocc去除了冗余代码」· C语言 代码 · 共 2,498 行 · 第 1/5 页
C
2,498 行
(struct omap24xxvout_colorkey *) arg; if (colorkey->output_dev != OMAP2_OUTPUT_LCD && colorkey->output_dev != OMAP2_OUTPUT_TV) return -EINVAL; omap2_disp_get_dss(); omap2_disp_get_colorkey (colorkey->output_dev, &colorkey->key_type, &colorkey->key_val); omap2_disp_put_dss(); return 0; } case VIDIOC_S_OMAP2_BGCOLOR: { struct omap24xxvout_bgcolor *bgcolor = (struct omap24xxvout_bgcolor *) arg; if (bgcolor->output_dev != OMAP2_OUTPUT_LCD && bgcolor->output_dev != OMAP2_OUTPUT_TV) return -EINVAL; omap2_disp_get_dss(); omap2_disp_set_bg_color (bgcolor->output_dev, bgcolor->color); omap2_disp_put_dss(); return 0; } case VIDIOC_G_OMAP2_BGCOLOR: { struct omap24xxvout_bgcolor *bgcolor = (struct omap24xxvout_bgcolor *) arg; if (bgcolor->output_dev != OMAP2_OUTPUT_LCD && bgcolor->output_dev != OMAP2_OUTPUT_TV) return -EINVAL; omap2_disp_get_dss(); omap2_disp_get_bg_color (bgcolor->output_dev, &bgcolor->color); omap2_disp_put_dss(); return 0; } case VIDIOC_OMAP2_COLORKEY_ENABLE: { int *output_dev = arg; if (*output_dev != OMAP2_OUTPUT_LCD && *output_dev != OMAP2_OUTPUT_TV) return -EINVAL; omap2_disp_get_dss(); omap2_disp_enable_colorkey (*output_dev); omap2_disp_put_dss(); return 0; } case VIDIOC_OMAP2_COLORKEY_DISABLE: { int *output_dev = arg; if (*output_dev != OMAP2_OUTPUT_LCD && *output_dev != OMAP2_OUTPUT_TV) return -EINVAL; omap2_disp_get_dss(); omap2_disp_disable_colorkey (*output_dev); omap2_disp_put_dss(); return 0; } case VIDIOC_S_OMAP2_COLORCONV: { int v; struct omap24xxvout_colconv *ccmtx = (struct omap24xxvout_colconv *) arg; if(vout->vid == OMAP2_VIDEO1) v =0; else v =1; current_colorconv_values[v][0][0]=ccmtx->RY; current_colorconv_values[v][0][1]=ccmtx->RCr; current_colorconv_values[v][0][2]=ccmtx->RCb; current_colorconv_values[v][1][0]=ccmtx->GY; current_colorconv_values[v][1][1]=ccmtx->GCr; current_colorconv_values[v][1][2]=ccmtx->GCb; current_colorconv_values[v][2][0]=ccmtx->BY; current_colorconv_values[v][2][1]=ccmtx->BCr; current_colorconv_values[v][2][2]=ccmtx->BCb; omap2_disp_get_dss(); omap2_disp_set_colorconv(vout->vid, &vout->pix); omap2_disp_put_dss(); return 0; } case VIDIOC_G_OMAP2_COLORCONV: { int v; struct omap24xxvout_colconv *ccmtx = (struct omap24xxvout_colconv *) arg; if(vout->vid == OMAP2_VIDEO1) v =0; else v =1; ccmtx->RY = current_colorconv_values[v][0][0]; ccmtx->RCr= current_colorconv_values[v][0][1]; ccmtx->RCb= current_colorconv_values[v][0][2]; ccmtx->GY = current_colorconv_values[v][1][0]; ccmtx->GCr= current_colorconv_values[v][1][1]; ccmtx->GCb= current_colorconv_values[v][1][2]; ccmtx->BY = current_colorconv_values[v][2][0]; ccmtx->BCr= current_colorconv_values[v][2][1]; ccmtx->BCb= current_colorconv_values[v][2][2]; return 0; } case VIDIOC_S_OMAP2_DEFCOLORCONV: { omap2_disp_get_dss(); omap2_disp_set_default_colorconv(vout->vid, &vout->pix); omap2_disp_put_dss(); return 0; } default: /* unrecognized ioctl */ return -ENOIOCTLCMD; } /* End of switch(cmd) */ return 0;}/* * file operations */static void omap24xxvout_vm_open (struct vm_area_struct *vma){ struct omap24xxvout_device *vout = vma->vm_private_data; DPRINTK ("vm_open [vma=%08lx-%08lx]\n", vma->vm_start, vma->vm_end); vout->mmap_count++;}static void omap24xxvout_vm_close (struct vm_area_struct *vma){ struct omap24xxvout_device *vout = vma->vm_private_data; DPRINTK ("vm_close [vma=%08lx-%08lx]\n", vma->vm_start, vma->vm_end); vout->mmap_count--;}static struct vm_operations_struct omap24xxvout_vm_ops = { .open = omap24xxvout_vm_open, .close = omap24xxvout_vm_close,};static int omap24xxvout_mmap (struct file *file, struct vm_area_struct *vma){ struct omap24xxvout_fh *fh = file->private_data; struct omap24xxvout_device *vout = fh->vout; struct videobuf_queue *q = &fh->vbq; unsigned long size = (vma->vm_end - vma->vm_start); unsigned long start = vma->vm_start; int i; void *pos; struct videobuf_dmabuf *dmabuf=NULL; DPRINTK ("pgoff=0x%x, start=0x%x, end=0x%x\n", vma->vm_pgoff, vma->vm_start, vma->vm_end); /* look for the buffer to map */ for (i = 0; i < VIDEO_MAX_FRAME; i++) { if (NULL == q->bufs[i]) continue; if (V4L2_MEMORY_MMAP != q->bufs[i]->memory) continue; if (q->bufs[i]->boff == (vma->vm_pgoff << PAGE_SHIFT)) break; } if (VIDEO_MAX_FRAME == i) { DPRINTK ("offset invalid [offset=0x%lx]\n", (vma->vm_pgoff << PAGE_SHIFT)); return -EINVAL; } q->bufs[i]->baddr = vma->vm_start; vma->vm_flags |= VM_RESERVED; vma->vm_page_prot = pgprot_writecombine (vma->vm_page_prot); vma->vm_ops = &omap24xxvout_vm_ops; vma->vm_private_data = (void *) vout; dmabuf = videobuf_to_dma(q->bufs[i]); pos = dmabuf->vmalloc; while (size > 0) { /* size is page-aligned */ if (vm_insert_page(vma, start, vmalloc_to_page(pos) )) { return -EAGAIN; } start += PAGE_SIZE; pos += PAGE_SIZE; size -= PAGE_SIZE; } vma->vm_flags &= ~VM_IO; /* using shared anonymous pages */ /* under investigation. clearing this bit allows video-buf to accept buffers alloacted here but has troube when unmap */ vout->mmap_count++; return 0;}static int omap24xxvout_ioctl (struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg){ struct omap24xxvout_fh *fh = file->private_data; struct omap24xxvout_device *vout = fh->vout; omap24xxvout_suspend_lockout (vout, file); return video_usercopy (inode, file, cmd, arg, omap24xxvout_do_ioctl);}static void omap24xxvout_free_allbuffers(struct omap24xxvout_device *vout){ int num_buffers = 0, i; num_buffers = (vout->vid == OMAP2_VIDEO1) ? video1_numbuffers : video2_numbuffers; for(i = num_buffers ; i < vout->buffer_allocated ; i ++) { if(vout->buf_virt_addr[i]) { omap35xvout_free_buffer(vout->buf_virt_addr[i], vout->buf_phy_addr[i], vout->buffer_size); } vout->buf_virt_addr[i] = 0; vout->buf_phy_addr[i] = 0; } for(i = 0 ; i < 4 ; i ++) { if(vout->smsshado_virt_addr[i]) { omap35xvout_free_buffer(vout->smsshado_virt_addr[i], vout->smsshado_phy_addr[i], vout->smsshado_size); vout->smsshado_virt_addr[i]=0; vout->smsshado_phy_addr[i]=0; } } vout->buffer_allocated = num_buffers;}static int omap24xxvout_release (struct inode *inode, struct file *file){ struct omap24xxvout_fh *fh = file->private_data; struct omap24xxvout_device *vout; struct videobuf_queue *q; DPRINTK ("entering\n"); if (fh == 0) return 0; if ((vout = fh->vout) == 0) return 0; q = &fh->vbq; omap2_disp_get_dss(); omap24xxvout_suspend_lockout (vout, file); /* * Check if the hidden buffer transfer is happening with DMA * if yes then stop it */ if (vout->rotation > 0) { if (vout->vrfb_dma_tx.tx_status == 0) { /* * DMA will be stopped once here and again after * wakeup to avoid race conditions due to time * taken to wakeup the sleeping process */ omap_stop_dma (vout->vrfb_dma_tx.dma_ch); wake_up_interruptible(&vout->vrfb_dma_tx.wait); } } if(fh->io_allowed) { videobuf_streamoff(q); videobuf_queue_cancel(q); /* Free all buffers */ omap24xxvout_free_allbuffers(vout); videobuf_mmap_free(q); } omap2_disp_disable_layer (vout->vid); if ((vout_linked != -1) && (vout->vid != vout_linked)) omap2_disp_disable_layer ((vout->vid == OMAP2_VIDEO1) ? OMAP2_VIDEO2 : OMAP2_VIDEO1); if (vout->streaming == fh) vout->streaming = NULL; if (vout->mmap_count != 0){ vout->mmap_count = 0; printk("mmap count is not zero!\n"); } omap2_disp_release_layer (vout->vid); omap2_disp_put_dss (); vout->opened -= 1; file->private_data = NULL; if (vout->buffer_allocated) videobuf_mmap_free(q); kfree (fh); /* need to remove the link when the either slave or master is gone */ spin_lock (&vout_link_lock); if (vout_linked != -1) { vout_linked = -1; } spin_unlock (&vout_link_lock); return 0;}static int omap24xxvout_open (struct inode *inode, struct file *file){ int minor = MINOR (file->f_dentry->d_inode->i_rdev); struct omap24xxvout_device *vout = NULL; struct omap24xxvout_fh *fh; struct videobuf_queue *q; /*int i;*/ DPRINTK ("entering\n"); if (saved_v1out && saved_v1out->vfd && (saved_v1out->vfd->minor == minor)) { vout = saved_v1out; } if (vout == NULL) { if (saved_v2out && saved_v2out->vfd && (saved_v2out->vfd->minor == minor)) { vout = saved_v2out; } } if (vout == NULL) return -ENODEV; /* for now, we only support single open */ if (vout->opened) return -EBUSY; vout->opened += 1; if (!omap2_disp_request_layer (vout->vid)) { vout->opened -= 1; return -ENODEV; } omap2_disp_get_dss (); omap24xxvout_suspend_lockout (vout, file); /* allocate per-filehandle data */ fh = kmalloc (sizeof (*fh), GFP_KERNEL); if (NULL == fh) { omap2_disp_release_layer (vout->vid); omap2_disp_put_dss (); vout->opened -= 1; return -ENOMEM; } memset(fh, 0, sizeof(*fh)); file->private_data = fh; fh->vout = vout; fh->type = V4L2_BUF_TYPE_VIDEO_OUTPUT; q = &fh->vbq; video_vbq_ops.buf_setup = omap35x_buffer_setup; video_vbq_ops.buf_prepare = omap35x_buffer_prepare; video_vbq_ops.buf_release = omap35x_buffer_release; video_vbq_ops.buf_queue = omap35x_buffer_queue; spin_lock_init(&vout->vbq_lock); videobuf_queue_pci_init (q, &video_vbq_ops, NULL, &vout->vbq_lock, fh->type, V4L2_FIELD_NONE, sizeof (struct videobuf_buffer), fh); omap2_disp_put_dss(); return 0;}static struct file_operations omap24xxvout_fops = { .owner = THIS_MODULE, .llseek = no_llseek, .ioctl = omap24xxvout_ioctl, .mmap = omap24xxvout_mmap, .open = omap24xxvout_open, .release = omap24xxvout_release,};static int omap24xxvout_suspend (struct platform_device *dev, pm_message_t state){ struct omap24xxvout_device *vout = platform_get_drvdata (dev); /* lock-out applications during suspend */ if(vout->suspended == 1) return 0; if (vout->opened) { /* stall vid DMA */ if (vout->streaming) { omap2_disp_disable_layer (vout->vid); /* * Check if the hidden buffer transfer is happening * with DMA if yes then stop it */ if (vout->rotation > 0) { if (vout->vrfb_dma_tx.tx_status == 0) { /* * DMA will be stopped once here * and again after wakeup to * avoid race conditions due to time * taken to wakeup the sleeping * process */ omap_stop_dma ( vout->vrfb_dma_tx.dma_ch); wake_up_interruptible ( &vout->vrfb_dma_tx.wait); } } } vout->suspended = 1; omap2_disp_put_dss (); } return 0;}static int omap24xxvout_resume (struct platform_device *dev){ struct omap24xxvout_device *vout = platform_get_drvdata (dev); if(vout->suspended == 0) return 0; if (vout->opened) { omap2_disp_get_dss (); /* resume vid DMA */ if (vout->streaming) omap2_disp_enable_layer (vout->vid); /* wake up applications waiting on suspend queue */ vout->suspended = 0; wake_up (&vout->suspend_wq); } return 0;}static intomap24xxvout_probe (struct platform_device *dev){ return 0;}static void omap35x_platform_release(struct device *device){ /* This is called when the reference count goes to zero */}static struct platform_device omap24xxv1out_dev = { .name = V1OUT_NAME, .id = 11, //.devid = OMAP24xx_V1OUT_DEVID, // .busid = OMAP_BUS_L3, .dev = { .release = omap35x_platform_release,
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?