⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 cx23885-video.c

📁 trident tm5600的linux驱动
💻 C
📖 第 1 页 / 共 4 页
字号:
/* *  Driver for the Conexant CX23885 PCIe bridge * *  Copyright (c) 2007 Steven Toth <stoth@linuxtv.org> * *  This program is free software; you can redistribute it and/or modify *  it under the terms of the GNU General Public License as published by *  the Free Software Foundation; either version 2 of the License, or *  (at your option) any later version. * *  This program is distributed in the hope that it will be useful, *  but WITHOUT ANY WARRANTY; without even the implied warranty of *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the * *  GNU General Public License for more details. * *  You should have received a copy of the GNU General Public License *  along with this program; if not, write to the Free Software *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */#include <linux/init.h>#include <linux/list.h>#include <linux/module.h>#include <linux/moduleparam.h>#include <linux/kmod.h>#include <linux/kernel.h>#include <linux/slab.h>#include <linux/interrupt.h>#include <linux/delay.h>#include "compat.h"#include <linux/kthread.h>#include <asm/div64.h>#include "cx23885.h"#include <media/v4l2-common.h>#include <media/v4l2-ioctl.h>#ifdef CONFIG_VIDEO_V4L1_COMPAT/* Include V4L1 specific functions. Should be removed soon */#include <linux/videodev.h>#endifMODULE_DESCRIPTION("v4l2 driver module for cx23885 based TV cards");MODULE_AUTHOR("Steven Toth <stoth@linuxtv.org>");MODULE_LICENSE("GPL");/* ------------------------------------------------------------------ */static unsigned int video_nr[] = {[0 ... (CX23885_MAXBOARDS - 1)] = UNSET };static unsigned int vbi_nr[]   = {[0 ... (CX23885_MAXBOARDS - 1)] = UNSET };static unsigned int radio_nr[] = {[0 ... (CX23885_MAXBOARDS - 1)] = UNSET };module_param_array(video_nr, int, NULL, 0444);module_param_array(vbi_nr,   int, NULL, 0444);module_param_array(radio_nr, int, NULL, 0444);MODULE_PARM_DESC(video_nr, "video device numbers");MODULE_PARM_DESC(vbi_nr, "vbi device numbers");MODULE_PARM_DESC(radio_nr, "radio device numbers");static unsigned int video_debug;module_param(video_debug, int, 0644);MODULE_PARM_DESC(video_debug, "enable debug messages [video]");static unsigned int irq_debug;module_param(irq_debug, int, 0644);MODULE_PARM_DESC(irq_debug, "enable debug messages [IRQ handler]");static unsigned int vid_limit = 16;module_param(vid_limit, int, 0644);MODULE_PARM_DESC(vid_limit, "capture memory limit in megabytes");#define dprintk(level, fmt, arg...)\	do { if (video_debug >= level)\		printk(KERN_DEBUG "%s/0: " fmt, dev->name, ## arg);\	} while (0)/* ------------------------------------------------------------------- *//* static data                                                         */#define FORMAT_FLAGS_PACKED       0x01static struct cx23885_fmt formats[] = {	{		.name     = "8 bpp, gray",		.fourcc   = V4L2_PIX_FMT_GREY,#if 0		.cxformat = ColorFormatY8,#endif		.depth    = 8,		.flags    = FORMAT_FLAGS_PACKED,	}, {		.name     = "15 bpp RGB, le",		.fourcc   = V4L2_PIX_FMT_RGB555,#if 0		.cxformat = ColorFormatRGB15,#endif		.depth    = 16,		.flags    = FORMAT_FLAGS_PACKED,	}, {		.name     = "15 bpp RGB, be",		.fourcc   = V4L2_PIX_FMT_RGB555X,#if 0		.cxformat = ColorFormatRGB15 | ColorFormatBSWAP,#endif		.depth    = 16,		.flags    = FORMAT_FLAGS_PACKED,	}, {		.name     = "16 bpp RGB, le",		.fourcc   = V4L2_PIX_FMT_RGB565,#if 0		.cxformat = ColorFormatRGB16,#endif		.depth    = 16,		.flags    = FORMAT_FLAGS_PACKED,	}, {		.name     = "16 bpp RGB, be",		.fourcc   = V4L2_PIX_FMT_RGB565X,#if 0		.cxformat = ColorFormatRGB16 | ColorFormatBSWAP,#endif		.depth    = 16,		.flags    = FORMAT_FLAGS_PACKED,	}, {		.name     = "24 bpp RGB, le",		.fourcc   = V4L2_PIX_FMT_BGR24,#if 0		.cxformat = ColorFormatRGB24,#endif		.depth    = 24,		.flags    = FORMAT_FLAGS_PACKED,	}, {		.name     = "32 bpp RGB, le",		.fourcc   = V4L2_PIX_FMT_BGR32,#if 0		.cxformat = ColorFormatRGB32,#endif		.depth    = 32,		.flags    = FORMAT_FLAGS_PACKED,	}, {		.name     = "32 bpp RGB, be",		.fourcc   = V4L2_PIX_FMT_RGB32,#if 0		.cxformat = ColorFormatRGB32 | ColorFormatBSWAP |			ColorFormatWSWAP,#endif		.depth    = 32,		.flags    = FORMAT_FLAGS_PACKED,	}, {		.name     = "4:2:2, packed, YUYV",		.fourcc   = V4L2_PIX_FMT_YUYV,#if 0		.cxformat = ColorFormatYUY2,#endif		.depth    = 16,		.flags    = FORMAT_FLAGS_PACKED,	}, {		.name     = "4:2:2, packed, UYVY",		.fourcc   = V4L2_PIX_FMT_UYVY,#if 0		.cxformat = ColorFormatYUY2 | ColorFormatBSWAP,#endif		.depth    = 16,		.flags    = FORMAT_FLAGS_PACKED,	},};static struct cx23885_fmt *format_by_fourcc(unsigned int fourcc){	unsigned int i;	for (i = 0; i < ARRAY_SIZE(formats); i++)		if (formats[i].fourcc == fourcc)			return formats+i;	printk(KERN_ERR "%s(0x%08x) NOT FOUND\n", __func__, fourcc);	return NULL;}/* ------------------------------------------------------------------- */static const struct v4l2_queryctrl no_ctl = {	.name  = "42",	.flags = V4L2_CTRL_FLAG_DISABLED,};static struct cx23885_ctrl cx23885_ctls[] = {	/* --- video --- */	{		.v = {			.id            = V4L2_CID_BRIGHTNESS,			.name          = "Brightness",			.minimum       = 0x00,			.maximum       = 0xff,			.step          = 1,			.default_value = 0x7f,			.type          = V4L2_CTRL_TYPE_INTEGER,		},		.off                   = 128,		.reg                   = LUMA_CTRL,		.mask                  = 0x00ff,		.shift                 = 0,	}, {		.v = {			.id            = V4L2_CID_CONTRAST,			.name          = "Contrast",			.minimum       = 0,			.maximum       = 0xff,			.step          = 1,			.default_value = 0x3f,			.type          = V4L2_CTRL_TYPE_INTEGER,		},		.off                   = 0,		.reg                   = LUMA_CTRL,		.mask                  = 0xff00,		.shift                 = 8,	}, {		.v = {			.id            = V4L2_CID_HUE,			.name          = "Hue",			.minimum       = 0,			.maximum       = 0xff,			.step          = 1,			.default_value = 0x7f,			.type          = V4L2_CTRL_TYPE_INTEGER,		},		.off                   = 128,		.reg                   = CHROMA_CTRL,		.mask                  = 0xff0000,		.shift                 = 16,	}, {		/* strictly, this only describes only U saturation.		 * V saturation is handled specially through code.		 */		.v = {			.id            = V4L2_CID_SATURATION,			.name          = "Saturation",			.minimum       = 0,			.maximum       = 0xff,			.step          = 1,			.default_value = 0x7f,			.type          = V4L2_CTRL_TYPE_INTEGER,		},		.off                   = 0,		.reg                   = CHROMA_CTRL,		.mask                  = 0x00ff,		.shift                 = 0,	}, {	/* --- audio --- */		.v = {			.id            = V4L2_CID_AUDIO_MUTE,			.name          = "Mute",			.minimum       = 0,			.maximum       = 1,			.default_value = 1,			.type          = V4L2_CTRL_TYPE_BOOLEAN,		},		.reg                   = PATH1_CTL1,		.mask                  = (0x1f << 24),		.shift                 = 24,	}, {		.v = {			.id            = V4L2_CID_AUDIO_VOLUME,			.name          = "Volume",			.minimum       = 0,			.maximum       = 0x3f,			.step          = 1,			.default_value = 0x3f,			.type          = V4L2_CTRL_TYPE_INTEGER,		},		.reg                   = PATH1_VOL_CTL,		.mask                  = 0xff,		.shift                 = 0,	}};static const int CX23885_CTLS = ARRAY_SIZE(cx23885_ctls);static const u32 cx23885_user_ctrls[] = {	V4L2_CID_USER_CLASS,	V4L2_CID_BRIGHTNESS,	V4L2_CID_CONTRAST,	V4L2_CID_SATURATION,	V4L2_CID_HUE,	V4L2_CID_AUDIO_VOLUME,#if 0	V4L2_CID_AUDIO_BALANCE,#endif	V4L2_CID_AUDIO_MUTE,	0};static const u32 *ctrl_classes[] = {	cx23885_user_ctrls,	NULL};static void cx23885_video_wakeup(struct cx23885_dev *dev,		 struct cx23885_dmaqueue *q, u32 count){	struct cx23885_buffer *buf;	int bc;	for (bc = 0;; bc++) {		if (list_empty(&q->active))			break;		buf = list_entry(q->active.next,				 struct cx23885_buffer, vb.queue);		/* count comes from the hw and is is 16bit wide --		 * this trick handles wrap-arounds correctly for		 * up to 32767 buffers in flight... */		if ((s16) (count - buf->count) < 0)			break;		do_gettimeofday(&buf->vb.ts);		dprintk(2, "[%p/%d] wakeup reg=%d buf=%d\n", buf, buf->vb.i,			count, buf->count);		buf->vb.state = VIDEOBUF_DONE;		list_del(&buf->vb.queue);		wake_up(&buf->vb.done);	}	if (list_empty(&q->active))		del_timer(&q->timeout);	else		mod_timer(&q->timeout, jiffies+BUFFER_TIMEOUT);	if (bc != 1)		printk(KERN_ERR "%s: %d buffers handled (should be 1)\n",			__func__, bc);}static int cx23885_set_tvnorm(struct cx23885_dev *dev, v4l2_std_id norm){	dprintk(1, "%s(norm = 0x%08x) name: [%s]\n",		__func__,		(unsigned int)norm,		v4l2_norm_to_name(norm));	dev->tvnorm = norm;	/* Tell the analog tuner/demods */	cx23885_call_i2c_clients(&dev->i2c_bus[1], VIDIOC_S_STD, &norm);	/* Tell the internal A/V decoder */	cx23885_call_i2c_clients(&dev->i2c_bus[2], VIDIOC_S_STD, &norm);	return 0;}static struct video_device *cx23885_vdev_init(struct cx23885_dev *dev,				    struct pci_dev *pci,				    struct video_device *template,				    char *type){	struct video_device *vfd;	dprintk(1, "%s()\n", __func__);	vfd = video_device_alloc();	if (NULL == vfd)		return NULL;	*vfd = *template;	vfd->minor   = -1;	vfd->parent  = &pci->dev;	vfd->release = video_device_release;	snprintf(vfd->name, sizeof(vfd->name), "%s %s (%s)",		 dev->name, type, cx23885_boards[dev->board].name);	return vfd;}static int cx23885_ctrl_query(struct v4l2_queryctrl *qctrl){	int i;	if (qctrl->id < V4L2_CID_BASE ||	    qctrl->id >= V4L2_CID_LASTP1)		return -EINVAL;	for (i = 0; i < CX23885_CTLS; i++)		if (cx23885_ctls[i].v.id == qctrl->id)			break;	if (i == CX23885_CTLS) {		*qctrl = no_ctl;		return 0;	}	*qctrl = cx23885_ctls[i].v;	return 0;}/* ------------------------------------------------------------------- *//* resource management                                                 */static int res_get(struct cx23885_dev *dev, struct cx23885_fh *fh,	unsigned int bit){	dprintk(1, "%s()\n", __func__);	if (fh->resources & bit)		/* have it already allocated */		return 1;	/* is it free? */	mutex_lock(&dev->lock);	if (dev->resources & bit) {		/* no, someone else uses it */		mutex_unlock(&dev->lock);		return 0;	}	/* it's free, grab it */	fh->resources  |= bit;	dev->resources |= bit;	dprintk(1, "res: get %d\n", bit);	mutex_unlock(&dev->lock);	return 1;}static int res_check(struct cx23885_fh *fh, unsigned int bit){	return fh->resources & bit;}static int res_locked(struct cx23885_dev *dev, unsigned int bit){	return dev->resources & bit;}static void res_free(struct cx23885_dev *dev, struct cx23885_fh *fh,	unsigned int bits){	BUG_ON((fh->resources & bits) != bits);	dprintk(1, "%s()\n", __func__);	mutex_lock(&dev->lock);	fh->resources  &= ~bits;	dev->resources &= ~bits;	dprintk(1, "res: put %d\n", bits);	mutex_unlock(&dev->lock);}static int cx23885_video_mux(struct cx23885_dev *dev, unsigned int input){	struct v4l2_routing route;	memset(&route, 0, sizeof(route));	dprintk(1, "%s() video_mux: %d [vmux=%d, gpio=0x%x,0x%x,0x%x,0x%x]\n",		__func__,		input, INPUT(input)->vmux,		INPUT(input)->gpio0, INPUT(input)->gpio1,		INPUT(input)->gpio2, INPUT(input)->gpio3);	dev->input = input;	route.input = INPUT(input)->vmux;	/* Tell the internal A/V decoder */	cx23885_call_i2c_clients(&dev->i2c_bus[2],		VIDIOC_INT_S_VIDEO_ROUTING, &route);#if 0	route.input = 0; /* Let the AVCore default */	cx23885_call_i2c_clients(&dev->i2c_bus[2],		VIDIOC_INT_S_AUDIO_ROUTING, &route);#endif	return 0;}/* ------------------------------------------------------------------ */static int cx23885_set_scale(struct cx23885_dev *dev, unsigned int width,

⌨️ 快捷键说明

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