omap24xxvout.c

来自「omap3 linux 2.6 用nocc去除了冗余代码」· C语言 代码 · 共 2,498 行 · 第 1/5 页

C
2,498
字号
	},};static struct platform_device omap24xxv2out_dev = {	.name = V2OUT_NAME,	.id = 12,	//.devid = OMAP24xx_V2OUT_DEVID,	//.busid = OMAP_BUS_L3,	.dev = {		.release = omap35x_platform_release,	},};static struct platform_driver omap24xxv1out_driver = {	.driver = {		.name = V1OUT_NAME,	},	//.devid   = OMAP24xx_V1OUT_DEVID,	// .id   = 11,	//.busid   = OMAP_BUS_L3,	// .clocks  = 0,	.probe   = omap24xxvout_probe,	.suspend = omap24xxvout_suspend,	.resume  = omap24xxvout_resume,};static struct platform_driver omap24xxv2out_driver = {	.driver = {		.name = V2OUT_NAME,	},	//.id   = 12,	//.devid   = OMAP24xx_V2OUT_DEVID,	//.busid   = OMAP_BUS_L3,	//.clocks  = 0,	.probe   = omap24xxvout_probe,	.suspend = omap24xxvout_suspend,	.resume  = omap24xxvout_resume,};void omap24xxvout_isr(void *arg, struct pt_regs *regs, unsigned int irqstatus){	struct timeval timevalue;	unsigned int out_dev;	struct omap24xxvout_device *vout=(struct omap24xxvout_device *)arg;	u32 addr, fid;	if(!vout->streaming)		return;	spin_lock(&vout->vbq_lock);	do_gettimeofday(&timevalue);	out_dev = omap2_disp_get_output_dev(vout->vid);	if(out_dev == OMAP2_OUTPUT_LCD) {		if(list_empty(&vout->dma_queue)) {			spin_unlock(&vout->vbq_lock);			return;		}		if(!vout->first_int){			vout->curFrm->ts = timevalue;			vout->curFrm->state = VIDEOBUF_DONE;			if(&(vout->curFrm->done)) {				wake_up(&vout->curFrm->done);			}			vout->curFrm = vout->nextFrm;		}		vout->first_int = 0;		vout->nextFrm = list_entry(vout->dma_queue.next,				struct videobuf_buffer,				queue);		list_del(&vout->nextFrm->queue);		vout->nextFrm->state = VIDEOBUF_ACTIVE;		addr = (unsigned long)			vout->queued_buf_addr[vout->nextFrm->i] + 			vout->cropped_offset;		omap2_disp_set_addr(vout->vid, addr, addr,				addr + vout->tv_field1_offset);	} else {		if(vout->first_int) {			vout->first_int = 0;			spin_unlock(&vout->vbq_lock);			return ;		}		vout->field_id ^= 1;		fid = (irqstatus & DISPC_IRQSTATUS_EVSYNC_ODD)?0:1;		if(fid != vout->field_id) {			if(0 == fid)				vout->field_id = fid;			spin_unlock(&vout->vbq_lock);			return;		}		if(0 == fid) {			if(vout->curFrm == vout->nextFrm) {				spin_unlock(&vout->vbq_lock);				return;			}			vout->curFrm->ts = timevalue;			vout->curFrm->state = VIDEOBUF_DONE;			wake_up_interruptible(&vout->curFrm->done);			vout->curFrm = vout->nextFrm;		} else if(1 == fid){			if(list_empty(&vout->dma_queue) || 					(vout->curFrm != vout->nextFrm)) {				spin_unlock(&vout->vbq_lock);				return ;			}			vout->nextFrm = list_entry(vout->dma_queue.next, 					struct videobuf_buffer, queue);			list_del(&vout->nextFrm->queue);			vout->nextFrm->state = VIDEOBUF_ACTIVE;			addr = (unsigned long)				vout->queued_buf_addr[vout->nextFrm->i] + 				vout->cropped_offset;			omap2_disp_set_addr(vout->vid, addr, addr,					addr + vout->tv_field1_offset);		}	}	spin_unlock(&vout->vbq_lock);}static void cleanup_vout_device (int vid){	struct video_device *vfd;	struct omap24xxvout_device *vout;	int i, j, numbuffers;	vout = (vid == OMAP2_VIDEO1) ? saved_v1out : saved_v2out;	if (!vout)		return;	vfd = vout->vfd;	if (vfd) {		if (vfd->minor == -1) {			/* 			 * The device was never registered, so release the 			 * video_device struct directly. 			 */			video_device_release (vfd);		} else {			/* 			 * The unregister function will release the video_device			 * struct as well as unregistering it. 			 */			video_unregister_device (vfd);		}	}	for(i = 0 ; i < 4 ; i ++) {		for( j = 0 ; j < 4 ; j ++) {			release_mem_region (vout->sms_rot_phy[i][j], VRF_SIZE);		}	}	/* Allocate memory for the buffes */	numbuffers = (vid == OMAP2_VIDEO1) ? video1_numbuffers :		video2_numbuffers;	vout->buffer_size = (vid == OMAP2_VIDEO1) ? video1_bufsize :		video2_bufsize;	for(i = 0 ; i < numbuffers ; i ++) {		omap35xvout_free_buffer(vout->buf_virt_addr[i],				vout->buf_phy_addr[i],				vout->buffer_size);		vout->buf_phy_addr[i]=0;		vout->buf_virt_addr[i]=0;	}	if (vout->vrfb_dma_tx.req_status == DMA_CHAN_ALLOTED){		vout->vrfb_dma_tx.req_status = DMA_CHAN_NOT_ALLOTED;		omap_free_dma (vout->vrfb_dma_tx.dma_ch);		printk("Freed DMA channel\n");	}	platform_device_unregister ((vid == OMAP2_VIDEO1) ? 			&omap24xxv1out_dev : &omap24xxv2out_dev);	platform_driver_unregister ((vid == OMAP2_VIDEO1) ? 			&omap24xxv1out_driver : &omap24xxv2out_driver);	kfree (vout);	if (vid == OMAP2_VIDEO1)		saved_v1out = NULL;	else		saved_v2out = NULL;	omap2_disp_unregister_isr(omap24xxvout_isr);}static struct omap24xxvout_device * init_vout_device (int vid){	int r, i, j, mask;	struct omap24xxvout_device *vout;	struct video_device *vfd;	struct v4l2_pix_format *pix;	struct platform_driver *this_driver;	struct platform_device *this_dev;	u32 sms_start_addr, numbuffers;	int index_i, index_j, image_width, image_height;	vout = kmalloc (sizeof (struct omap24xxvout_device), GFP_KERNEL);	if (!vout){		printk (KERN_ERR VOUT_NAME ": could not allocate memory\n");		return NULL;	}	memset (vout, 0, sizeof (struct omap24xxvout_device));	vout->vid = vid;	vout->rotation = rotation_support;	/* set the default pix */	pix = &vout->pix;	pix->width = QQVGA_WIDTH;	pix->height = QQVGA_HEIGHT;	pix->pixelformat = V4L2_PIX_FMT_RGB565;	pix->field = V4L2_FIELD_ANY;	pix->bytesperline = pix->width * 2;	pix->sizeimage = pix->bytesperline * pix->height;	pix->priv = 0;	pix->colorspace = V4L2_COLORSPACE_JPEG;	vout->bpp = RGB565_BPP;	vout->vrfb_bpp = 1;	/* get the screen parameters */	omap2_disp_get_panel_size (omap2_disp_get_output_dev (vout->vid),			&(vout->fbuf.fmt.width),&(vout->fbuf.fmt.height));	/* set default crop and win */	omap24xxvout_new_format (pix, &vout->fbuf, &vout->crop, &vout->win);	/* initialize the video_device struct */	vfd = vout->vfd = video_device_alloc ();	if (!vfd){		printk (KERN_ERR VOUT_NAME": could not allocate video \				device struct\n");		kfree (vout);		return NULL;	}	vfd->release = video_device_release;	strncpy (vfd->name, VOUT_NAME, sizeof (vfd->name));	vfd->type = VID_TYPE_OVERLAY | VID_TYPE_CHROMAKEY;	/* need to register for a VID_HARDWARE_* ID in videodev.h */	vfd->fops = &omap24xxvout_fops;	video_set_drvdata (vfd, vout);	vfd->minor = -1;	sms_start_addr = (vid == OMAP2_VIDEO1)?OMAP35XVOUT_VIDEO1_SMS_START : 			OMAP35XVOUT_VIDEO2_SMS_START;	for(i = 0 ; i < 4 ; i ++) {		for(j = 0 ; j < 4 ; j ++) {			vout->sms_rot_phy[i][j] = sms_start_addr;			if (!request_mem_region (vout->sms_rot_phy[i][j], 						VRF_SIZE, vfd->name)) {				printk("Cannot reserve smsm IO %x\n", 						vout->sms_rot_phy[i][j]);				index_i = i;				index_j = j;				goto rotation_free;			}			sms_start_addr += 0x1000000; 		}	}	index_i = 4;	index_j = 4;	/* Allocate memory for the buffes */	numbuffers = (vid == OMAP2_VIDEO1) ? video1_numbuffers : 		video2_numbuffers;	vout->buffer_size = (vid == OMAP2_VIDEO1) ? video1_bufsize :		video2_bufsize;	for(i = 0 ; i < numbuffers ; i ++) {		vout->buf_virt_addr[i] = omap35xvout_alloc_buffer(				vout->buffer_size,				(u32*)&vout->buf_phy_addr[i]);		if(!vout->buf_virt_addr[i]) {			numbuffers = i - 1;			goto free_buffer_memory;		}	}	vout->suspended = 0;	init_waitqueue_head (&vout->suspend_wq);	if (video_register_device (vfd, VFL_TYPE_GRABBER, vid) < 0){		printk (KERN_ERR VOUT_NAME": could not register Video for \				Linux device\n");		vfd->minor = -1;		goto free_buffer_memory;	}	this_driver = (vid == OMAP2_VIDEO1) ? 		&omap24xxv1out_driver : &omap24xxv2out_driver;	this_dev = (vid == OMAP2_VIDEO1) ? 		&omap24xxv1out_dev : &omap24xxv2out_dev;	if (platform_driver_register (this_driver) != 0) {		printk (KERN_ERR VOUT_NAME ": could not register \				Video driver\n");		cleanup_vout_device (vid);		return NULL;	}	if (platform_device_register (this_dev) != 0) {		printk (KERN_ERR VOUT_NAME ": could not register \				Video device\n");		cleanup_vout_device (vid);		return NULL;	}	/* set driver specific data to use in power mgmt functions */	// omap_set_drvdata (this_dev, vout);	platform_set_drvdata (this_dev, vout);	if(vid == OMAP2_VIDEO1) {		vout->vrfb_context[0] = 4;		vout->vrfb_context[1] = 5;		vout->vrfb_context[2] = 6;		vout->vrfb_context[3] = 7;	} else {		vout->vrfb_context[0] = 8;		vout->vrfb_context[1] = 9;		vout->vrfb_context[2] = 10;		vout->vrfb_context[3] = 11;	}	vout->cropped_offset = 0;	/* Calculate VRFB memory size */	/* allocate for worst case size */	image_width = VID_MAX_WIDTH / TILE_SIZE;	if (VID_MAX_WIDTH % TILE_SIZE)		image_width++;	image_width = image_width * TILE_SIZE;	image_height = VID_MAX_HEIGHT / TILE_SIZE;	if (VID_MAX_HEIGHT % TILE_SIZE)		image_height++;	image_height = image_height * TILE_SIZE;	vout->smsshado_size = PAGE_ALIGN(image_width * image_height * 2 * 2);	/*	 * Request and Initialize DMA, for DMA based VRFB transfer	 */	vout->vrfb_dma_tx.dev_id = OMAP_DMA_NO_DEVICE;	vout->vrfb_dma_tx.dma_ch = -1;	vout->vrfb_dma_tx.req_status = DMA_CHAN_ALLOTED;	r = omap_request_dma (vout->vrfb_dma_tx.dev_id,			"VRFB DMA TX", vrfb_dma_tx_callback,			(void *) &vout->vrfb_dma_tx,			&vout->vrfb_dma_tx.dma_ch);	if (r < 0)		vout->vrfb_dma_tx.req_status = DMA_CHAN_NOT_ALLOTED;	init_waitqueue_head (&vout->vrfb_dma_tx.wait);	/* Register ISR handler */	mask = (DISPC_IRQSTATUS_EVSYNC_ODD | DISPC_IRQSTATUS_EVSYNC_EVEN			| DISPC_IRQSTATUS_VSYNC);	r = omap2_disp_register_isr(omap24xxvout_isr, vout, mask);	if(r < 0)  {		cleanup_vout_device (vid);		return NULL;	}	/*if rotation support */	printk (KERN_INFO VOUT_NAME ": registered device video%d [v4l2]\n",			vfd->minor);	return vout;free_buffer_memory:	for(i = 0 ; i < numbuffers ; 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;	}rotation_free:	for(j = 0 ; j < index_j ; j ++){		release_mem_region (vout->sms_rot_phy[index_i][j], VRF_SIZE);	}	for(i = 0 ; i < (index_i - 1) ; i ++){		for( j = 0 ;j < 4 ; j ++) {			release_mem_region (vout->sms_rot_phy[i][j], 					VRF_SIZE);		}	}	video_device_release (vfd);	kfree (vout);	return NULL;}static int __init omap24xxvout_init (void){	omap2_disp_get_dss();	saved_v1out = init_vout_device (OMAP2_VIDEO1);	if (saved_v1out == NULL) {		omap2_disp_put_dss();		return -ENODEV;	}	omap2_disp_save_initstate(OMAP_DSS_DISPC_GENERIC);	omap2_disp_save_initstate(OMAP2_VIDEO1);	saved_v2out = init_vout_device (OMAP2_VIDEO2);	if (saved_v2out == NULL){		cleanup_vout_device (OMAP2_VIDEO1);		omap2_disp_put_dss();		return -ENODEV;	}	omap2_disp_save_initstate(OMAP_DSS_DISPC_GENERIC);	omap2_disp_save_initstate(OMAP2_VIDEO2);	omap2_disp_put_dss();	vout_linked = -1;	spin_lock_init (&vout_link_lock);	return 0;}static void omap24xxvout_cleanup (void){	omap2_disp_get_dss();	cleanup_vout_device (OMAP2_VIDEO1);	cleanup_vout_device (OMAP2_VIDEO2);	omap2_disp_put_dss();}/* *	omap24xxvout_setup - process command line options *	@options: string of options * *	NOTE: This function is a __setup and __init function. * *	Returns zero. */int __init omap24xxvout_setup (char *options){	char *this_opt;	int i;	if (!options || !*options)return 0;	DPRINTK ("Options \"%s\"\n", options);	i = strlen (VOUT_NAME);	if (!strncmp (options, VOUT_NAME, i) && options[i] == ':'){		this_opt = options + i + 1;		if (!this_opt || !*this_opt)			return 0;		if (!strncmp (this_opt, "rotation=", 9)){			int deg = simple_strtoul (this_opt + 9, NULL, 0);			switch (deg){				case 0:				case 90:				case 180:				case 270:					rotation_support = (deg == 90) ? 						270 : (deg == 270) ? 90 : deg;					break;				default:					rotation_support = -1;					break;			}			printk (KERN_INFO VOUT_NAME ": Rotation %s\n",					(rotation_support == -1) ? 					"none (supported: \"rotation=\				[-1|0|90|180|270]\")" :					this_opt + 9);		} else			printk (KERN_INFO VOUT_NAME ": Invalid parameter \					\"%s\" "					"(supported: \				\"rotation=[-1|0|90|180|270]\")\n", 					this_opt);		return 0;	}	/*	 * If we get here no fb was specified.	 * We consider the argument to be a global video mode option.	 */	/* TODO - remove when FB is configured */	return 0;}__setup ("videoout=", omap24xxvout_setup);MODULE_AUTHOR ("Texas Instruments.");MODULE_DESCRIPTION ("OMAP24xx Video for Linux Video out driver");MODULE_LICENSE ("GPL");/* TODO -- Enabling it results in build erros, why?? */module_init (omap24xxvout_init);module_exit (omap24xxvout_cleanup);

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?