omap24xxvout.c
来自「omap3 linux 2.6 用nocc去除了冗余代码」· C语言 代码 · 共 2,498 行 · 第 1/5 页
C
2,498 行
/* Frame index */ dest_frame_index = ((MAX_PIXELS_PER_LINE * pixsize) - (vout->pix.width * vout->bpp)) + 1; /* Source and destination parameters */ src_element_index = 0; src_frame_index = 0; dest_element_index = 1; /* Number of elements per frame */ elem_count = vout->pix.width * vout->bpp; frame_count = vout->pix.height; vout->vrfb_dma_tx.tx_status = 0; omap_set_dma_transfer_params (vout->vrfb_dma_tx.dma_ch, OMAP_DMA_DATA_TYPE_S32, (elem_count / 4), frame_count, OMAP_DMA_SYNC_ELEMENT,vout->vrfb_dma_tx.dev_id, 0x0); omap_set_dma_src_params (vout->vrfb_dma_tx.dma_ch, 0, /* src_port required only for OMAP1 */ OMAP_DMA_AMODE_POST_INC, dmabuf->bus_addr, src_element_index, src_frame_index); /*set dma source burst mode for VRFB*/ omap_set_dma_src_burst_mode(vout->vrfb_dma_tx.dma_ch, OMAP_DMA_DATA_BURST_16); if (vout->mirror == 1) { /* Following is used to select appropriate VRFB * memory space for rotation with mirroring */ mir_rot_deg = (vout->rotation == 90) ? (270 / 90): (vout->rotation == 270) ? (90 / 90): (vout->rotation == 180) ? (0 / 90) : (180 / 90); omap_set_dma_dest_params (vout->vrfb_dma_tx.dma_ch, 0, /* dest_port required only for OMAP1 */ OMAP_DMA_AMODE_DOUBLE_IDX, vout->sms_rot_phy[vb->i][mir_rot_deg], dest_element_index, dest_frame_index); } else { /* No Mirroring */ omap_set_dma_dest_params (vout->vrfb_dma_tx.dma_ch, 0, /* dest_port required only for OMAP1 */ OMAP_DMA_AMODE_DOUBLE_IDX, vout->sms_rot_phy[vb->i][vout->rotation/90], dest_element_index, dest_frame_index); } /*set dma dest burst mode for VRFB*/ omap_set_dma_dest_burst_mode(vout->vrfb_dma_tx.dma_ch, OMAP_DMA_DATA_BURST_16); omap_dma_set_global_params(DMA_DEFAULT_ARB_RATE, 0x20, 0); omap_start_dma (vout->vrfb_dma_tx.dma_ch); interruptible_sleep_on_timeout (&vout->vrfb_dma_tx.wait, VRFB_TX_TIMEOUT); if (vout->vrfb_dma_tx.tx_status == 0) { omap_stop_dma (vout->vrfb_dma_tx.dma_ch); return -EINVAL; } /* Store buffers physical address into an array. Addresses * from this array will be used to configure DSS */ vout->queued_buf_addr[vb->i] = (u8*)vout->sms_rot_phy[vb->i][0]; } else { dmabuf = videobuf_to_dma(q->bufs[vb->i]); vout->queued_buf_addr[vb->i] = (u8*)dmabuf->bus_addr; } return 0;}/* Buffer queue funtion will be called from the videobuf layer when _QBUF * ioctl is called. It is used to enqueue buffer, which is ready to be * displayed. */static void omap35x_buffer_queue(struct videobuf_queue *q, struct videobuf_buffer *vb){ struct omap24xxvout_fh *fh = (struct omap24xxvout_fh *)q->priv_data; struct omap24xxvout_device *vout = fh->vout; /* Driver is also maintainig a queue. So enqueue buffer in the driver * queue */ list_add_tail(&vb->queue, &vout->dma_queue); vb->state = VIDEOBUF_PREPARED;}/* Buffer release function is called from videobuf layer to release buffer * which are already allocated */static void omap35x_buffer_release(struct videobuf_queue *q, struct videobuf_buffer *vb){ struct omap24xxvout_fh *fh = (struct omap24xxvout_fh *)q->priv_data; struct omap24xxvout_device *vout = fh->vout; vb->state = VIDEOBUF_NEEDS_INIT; if(V4L2_MEMORY_MMAP != vout->memory) return;}static int omap35xvout_calculate_offset(struct omap24xxvout_device *vout){ struct v4l2_pix_format *pix = &(vout->pix); struct v4l2_rect *crop = &(vout->crop); struct v4l2_window *win = &(vout->win); int rotation_deg; int mirroring = vout->mirror; int vr_ps = 1, ps = 2, temp_ps = 2; int offset=0, ctop=0, cleft=0, line_length=0; int *cropped_offset = &(vout->cropped_offset); if ((omap2_disp_get_output_dev(vout->vid) == OMAP2_OUTPUT_TV) && ((win->w.width == crop->width) && (win->w.height == crop->height))) vout->flicker_filter = 0; // was 1 else vout->flicker_filter = 0; if(1 == vout->mirror && vout->rotation > 0) { rotation_deg = (vout->rotation == 90)? 270: (vout->rotation == 270)? 90: (vout->rotation == 180)? 0:180; } else if(vout->rotation > 0) { rotation_deg = vout->rotation; } else { rotation_deg = -1; } if (V4L2_PIX_FMT_YUYV == pix->pixelformat || V4L2_PIX_FMT_UYVY == pix->pixelformat) { if (rotation_deg >= 0 || mirroring == 1){ /* * ps - Actual pixel size for YUYV/UYVY for * VRFB/Mirroring is 4 bytes * vr_ps - Virtually pixel size for YUYV/UYVY is * 2 bytes */ ps = 4; vr_ps = 2; } else { ps = 2; /* otherwise the pixel size is 2 byte */ } } else if(V4L2_PIX_FMT_RGB32 == pix->pixelformat) { ps = 4; } else if(V4L2_PIX_FMT_RGB24 == pix->pixelformat) { ps = 3; } vout->ps = ps; vout->vr_ps = vr_ps; if (rotation_deg >= 0) { line_length = MAX_PIXELS_PER_LINE; ctop = (pix->height - crop->height) - crop->top; cleft = (pix->width - crop->width) - crop->left; } else { line_length = pix->width; } vout->line_length = line_length; switch (rotation_deg) { case 90: offset = (omap2_disp_get_vrfb_offset(pix->width, ps, SIDE_H) - (pix->width/vr_ps)) * ps * line_length; temp_ps = ps/vr_ps; if (mirroring == 0) { *cropped_offset = offset + line_length * temp_ps * cleft + crop->top * temp_ps; } else { *cropped_offset = offset + line_length * temp_ps * cleft + crop->top * temp_ps + (line_length * ( (crop->width/(vr_ps)) - 1) * ps); } break; case 180: offset = (omap2_disp_get_vrfb_offset(pix->height, ps, SIDE_H) - pix->height) * ps * line_length + (omap2_disp_get_vrfb_offset(pix->width, ps, SIDE_W) - (pix->width/vr_ps)) * ps; if (mirroring == 0) { *cropped_offset = offset + (line_length * ps * ctop) + (cleft/vr_ps) * ps; } else { *cropped_offset = offset + (line_length * ps * ctop) + (cleft/vr_ps) * ps + (line_length * (crop->height - 1) * ps); } break; case 270: offset = (omap2_disp_get_vrfb_offset(pix->height, ps, SIDE_W) - pix->height) * ps; temp_ps = ps/vr_ps; if (mirroring == 0) { *cropped_offset = offset + line_length * temp_ps * crop->left + ctop * ps; } else { *cropped_offset = offset + line_length * temp_ps * crop->left + ctop * ps + (line_length * ((crop->width/vr_ps) - 1) * ps); } break; case 0: if (mirroring == 0) { *cropped_offset = (line_length * ps) * crop->top + (crop->left/vr_ps) * ps; } else { *cropped_offset = (line_length * ps) * crop->top + (crop->left/vr_ps) * ps + (line_length * (crop->height - 1) * ps); } break; default: if (mirroring == 0) { *cropped_offset = line_length * ps * crop->top + crop->left * ps; } else { *cropped_offset = (line_length * ps * crop->top) / vr_ps + (crop->left * ps) / vr_ps + ((crop->width / vr_ps) - 1) * ps; } break; } if(vout->flicker_filter == 1) vout->tv_field1_offset = 0; else if(vout->rotation > 0) { if(vout->mirror == 1) vout->tv_field1_offset = -vout->line_length * vout->ps; else vout->tv_field1_offset = vout->line_length * vout->ps; } else { if(vout->mirror == 1) vout->tv_field1_offset = vout->line_length * vout->ps/vout->vr_ps; else vout->tv_field1_offset = vout->line_length * vout->ps; } return 0;}static intomap24xxvout_do_ioctl (struct inode *inode, struct file *file, unsigned int cmd, void *arg){ struct omap24xxvout_fh *fh = (struct omap24xxvout_fh *)file->private_data; struct omap24xxvout_device *vout = fh->vout; int err; switch (cmd){ case VIDIOC_ENUMOUTPUT: { struct v4l2_output *output = (struct v4l2_output *) arg; int index = output->index; if (index > 0) return -EINVAL; memset (output, 0, sizeof (*output)); output->index = index; strncpy (output->name, "video out", sizeof ( output->name)); output->type = V4L2_OUTPUT_TYPE_MODULATOR; return 0; } case VIDIOC_G_OUTPUT: { unsigned int *output = arg; *output = 0; return 0; } case VIDIOC_S_OUTPUT: { unsigned int *output = arg; if (*output > 0) return -EINVAL; return 0; } case VIDIOC_QUERYCAP: { struct v4l2_capability *cap = (struct v4l2_capability *) arg; memset (cap, 0, sizeof (*cap)); strncpy (cap->driver, VOUT_NAME, sizeof (cap->driver)); strncpy (cap->card, vout->vfd->name, sizeof (cap->card)); cap->bus_info[0] = '\0'; cap->capabilities = V4L2_CAP_STREAMING | V4L2_CAP_VIDEO_OUTPUT; return 0; } case VIDIOC_ENUM_FMT: { struct v4l2_fmtdesc *fmt = arg; int index = fmt->index; enum v4l2_buf_type type = fmt->type; memset (fmt, 0, sizeof (*fmt)); fmt->index = index; fmt->type = type; switch (fmt->type){ case V4L2_BUF_TYPE_VIDEO_OUTPUT: case V4L2_BUF_TYPE_VIDEO_OVERLAY: if (index >= NUM_OUTPUT_FORMATS) return -EINVAL; break; default: return -EINVAL; } fmt->flags = omap2_formats[index].flags; strncpy (fmt->description, omap2_formats[index].description, sizeof (fmt->description)); fmt->pixelformat = omap2_formats[index].pixelformat; return 0; } case VIDIOC_G_FMT: { struct v4l2_format *f = (struct v4l2_format *) arg; switch (f->type){ case V4L2_BUF_TYPE_VIDEO_OUTPUT: { struct v4l2_pix_format *pix = &f->fmt.pix; memset (pix, 0, sizeof (*pix)); *pix = vout->pix; return 0; } case V4L2_BUF_TYPE_VIDEO_OVERLAY: { struct v4l2_window *win = &f->fmt.win; memset (win, 0, sizeof (*win)); /* * The API has a bit of a problem here. * We're returning a v4l2_window * structure, but that structure * contains pointers to variable-sized * objects for clipping rectangles and * clipping bitmaps. We will just * return NULLs for those pointers. */ win->w = vout->win.w; win->field = vout->win.field; win->chromakey = vout->win.chromakey; return 0; } default: return -EINVAL; } } case VIDIOC_TRY_FMT: { struct v4l2_format *f = (struct v4l2_format *) arg; if (vout->streaming) return -EBUSY; /* We dont support RGB24-packed mode if vrfb rotation * is enabled*/ if(vout->rotation != -1 && f->fmt.pix.pixelformat == V4L2_PIX_FMT_RGB24) return -EINVAL; switch (f->type) { case V4L2_BUF_TYPE_VIDEO_OVERLAY: { struct v4l2_window *win = &f->fmt.win; err = omap24xxvout_try_window ( &vout->fbuf, win); return err; } case V4L2_BUF_TYPE_VIDEO_OUTPUT: { /* don't allow to change img for the * linked layer */ if (vout->vid == vout_linked) return -EINVAL; try_format (&f->fmt.pix); return 0; } default: return -EINVAL; } } case VIDIOC_S_FMT: { struct v4l2_format *f = (struct v4l2_format *) arg; if (vout->streaming) return -EBUSY; /* We dont support RGB24-packed mode if vrfb rotation * is enabled*/ if(vout->rotation != -1 && f->fmt.pix.pixelformat == V4L2_PIX_FMT_RGB24 ) return -EINVAL; omap2_disp_get_dss(); /* get the framebuffer parameters */ if(vout->rotation == 90 || vout->rotation == 270){ omap2_disp_get_panel_size ( omap2_disp_get_output_dev (vout->vid), &(vout->fbuf.fmt.height), &(vout->fbuf.fmt.width)); } else { omap2_disp_get_panel_size ( omap2_disp_get_output_dev (vout->vid), &(vout->fbuf.fmt.width), &(vout->fbuf.fmt.height)); } omap2_disp_put_dss(); switch (f->type) { case V4L2_BUF_TYPE_VIDEO_OVERLAY: { struct v4l2_window *win = &f->fmt.win; err = omap24xxvout_new_window ( &vout->crop, &vout->win, &vout->fbuf, win); return err; } case V4L2_BUF_TYPE_VIDEO_OUTPUT: { int bpp; /* * don't allow to change img for * the linked layer */ if (vout->vid == vout_linked) return -EINVAL; /* change to samller size is OK */ bpp = try_format (&f->fmt.pix); f->fmt.pix.sizeimage = f->fmt.pix.width * f->fmt.pix.height *bpp; /* try & set the new output format */ vout->bpp = bpp; vout->pix = f->fmt.pix; vout->vrfb_bpp = 1; /* If YUYV then vrfb bpp is 2, for * others its 1*/ if (V4L2_PIX_FMT_YUYV == vout->pix.pixelformat || V4L2_PIX_FMT_UYVY == vout->pix.pixelformat) vout->vrfb_bpp = 2; /* set default crop and win */ omap24xxvout_new_format (&vout->pix, &vout->fbuf, &vout->crop, &vout->win); return 0; } default: return -EINVAL; } } case VIDIOC_CROPCAP: { struct v4l2_cropcap *cropcap = (struct v4l2_cropcap *) arg; enum v4l2_buf_type type = cropcap->type; memset (cropcap, 0, sizeof (*cropcap)); cropcap->type = type; switch (type) { case V4L2_BUF_TYPE_VIDEO_OUTPUT: { struct v4l2_pix_format *pix = &vout->pix; /* Width and height are always even */ cropcap->bounds.width = pix->width & ~1; cropcap->bounds.height = pix->height & ~1;
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?