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 + -
显示快捷键?