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

📄 av7110_v4l.c

📁 trident tm5600的linux驱动
💻 C
📖 第 1 页 / 共 2 页
字号:
				return -EINVAL;		}		memcpy(i, &inputs[i->index], sizeof(struct v4l2_input));		return 0;	}	case VIDIOC_G_INPUT:	{		int *input = (int *)arg;		*input = av7110->current_input;		dprintk(2, "VIDIOC_G_INPUT: %d\n", *input);		return 0;	}	case VIDIOC_S_INPUT:	{		int input = *(int *)arg;		dprintk(2, "VIDIOC_S_INPUT: %d\n", input);		if (!av7110->analog_tuner_flags)			return 0;		if (input < 0 || input >= 4)			return -EINVAL;		av7110->current_input = input;		return av7110_dvb_c_switch(fh);	}	case VIDIOC_G_AUDIO:	{		struct v4l2_audio *a = arg;		dprintk(2, "VIDIOC_G_AUDIO: %d\n", a->index);		if (a->index != 0)			return -EINVAL;		memcpy(a, &msp3400_v4l2_audio, sizeof(struct v4l2_audio));		break;	}	case VIDIOC_S_AUDIO:	{		struct v4l2_audio *a = arg;		dprintk(2, "VIDIOC_S_AUDIO: %d\n", a->index);		break;	}	case VIDIOC_G_SLICED_VBI_CAP:	{		struct v4l2_sliced_vbi_cap *cap = arg;		dprintk(2, "VIDIOC_G_SLICED_VBI_CAP\n");		memset(cap, 0, sizeof *cap);		if (FW_VERSION(av7110->arm_app) >= 0x2623) {			cap->service_set = V4L2_SLICED_WSS_625;			cap->service_lines[0][23] = V4L2_SLICED_WSS_625;		}		break;	}	case VIDIOC_G_FMT:	{		struct v4l2_format *f = arg;		dprintk(2, "VIDIOC_G_FMT:\n");		if (f->type != V4L2_BUF_TYPE_SLICED_VBI_OUTPUT ||		    FW_VERSION(av7110->arm_app) < 0x2623)			return -EAGAIN; /* handled by core driver */		memset(&f->fmt.sliced, 0, sizeof f->fmt.sliced);		if (av7110->wssMode) {			f->fmt.sliced.service_set = V4L2_SLICED_WSS_625;			f->fmt.sliced.service_lines[0][23] = V4L2_SLICED_WSS_625;			f->fmt.sliced.io_size = sizeof (struct v4l2_sliced_vbi_data);		}		break;	}	case VIDIOC_S_FMT:	{		struct v4l2_format *f = arg;		dprintk(2, "VIDIOC_S_FMT\n");		if (f->type != V4L2_BUF_TYPE_SLICED_VBI_OUTPUT ||		    FW_VERSION(av7110->arm_app) < 0x2623)			return -EAGAIN; /* handled by core driver */		if (f->fmt.sliced.service_set != V4L2_SLICED_WSS_625 &&		    f->fmt.sliced.service_lines[0][23] != V4L2_SLICED_WSS_625) {			memset(&f->fmt.sliced, 0, sizeof f->fmt.sliced);			/* WSS controlled by firmware */			av7110->wssMode = 0;			av7110->wssData = 0;			return av7110_fw_cmd(av7110, COMTYPE_ENCODER,					     SetWSSConfig, 1, 0);		} else {			memset(&f->fmt.sliced, 0, sizeof f->fmt.sliced);			f->fmt.sliced.service_set = V4L2_SLICED_WSS_625;			f->fmt.sliced.service_lines[0][23] = V4L2_SLICED_WSS_625;			f->fmt.sliced.io_size = sizeof (struct v4l2_sliced_vbi_data);			/* WSS controlled by userspace */			av7110->wssMode = 1;			av7110->wssData = 0;		}		break;	}	default:		printk("no such ioctl\n");		return -ENOIOCTLCMD;	}	return 0;}static int av7110_vbi_reset(struct inode *inode, struct file *file){	struct saa7146_fh *fh = file->private_data;	struct saa7146_dev *dev = fh->dev;	struct av7110 *av7110 = (struct av7110*) dev->ext_priv;	dprintk(2, "%s\n", __func__);	av7110->wssMode = 0;	av7110->wssData = 0;	if (FW_VERSION(av7110->arm_app) < 0x2623)		return 0;	else		return av7110_fw_cmd(av7110, COMTYPE_ENCODER, SetWSSConfig, 1, 0);}static ssize_t av7110_vbi_write(struct file *file, const char __user *data, size_t count, loff_t *ppos){	struct saa7146_fh *fh = file->private_data;	struct saa7146_dev *dev = fh->dev;	struct av7110 *av7110 = (struct av7110*) dev->ext_priv;	struct v4l2_sliced_vbi_data d;	int rc;	dprintk(2, "%s\n", __func__);	if (FW_VERSION(av7110->arm_app) < 0x2623 || !av7110->wssMode || count != sizeof d)		return -EINVAL;	if (copy_from_user(&d, data, count))		return -EFAULT;	if ((d.id != 0 && d.id != V4L2_SLICED_WSS_625) || d.field != 0 || d.line != 23)		return -EINVAL;	if (d.id)		av7110->wssData = ((d.data[1] << 8) & 0x3f00) | d.data[0];	else		av7110->wssData = 0x8000;	rc = av7110_fw_cmd(av7110, COMTYPE_ENCODER, SetWSSConfig, 2, 1, av7110->wssData);	return (rc < 0) ? rc : count;}/**************************************************************************** * INITIALIZATION ****************************************************************************/static struct saa7146_extension_ioctls ioctls[] = {	{ VIDIOC_ENUMINPUT,	SAA7146_EXCLUSIVE },	{ VIDIOC_G_INPUT,	SAA7146_EXCLUSIVE },	{ VIDIOC_S_INPUT,	SAA7146_EXCLUSIVE },	{ VIDIOC_G_FREQUENCY,	SAA7146_EXCLUSIVE },	{ VIDIOC_S_FREQUENCY,	SAA7146_EXCLUSIVE },	{ VIDIOC_G_TUNER,	SAA7146_EXCLUSIVE },	{ VIDIOC_S_TUNER,	SAA7146_EXCLUSIVE },	{ VIDIOC_G_AUDIO,	SAA7146_EXCLUSIVE },	{ VIDIOC_S_AUDIO,	SAA7146_EXCLUSIVE },	{ VIDIOC_G_SLICED_VBI_CAP, SAA7146_EXCLUSIVE },	{ VIDIOC_G_FMT,		SAA7146_BEFORE },	{ VIDIOC_S_FMT,		SAA7146_BEFORE },	{ 0, 0 }};static u8 saa7113_init_regs[] = {	0x02, 0xd0,	0x03, 0x23,	0x04, 0x00,	0x05, 0x00,	0x06, 0xe9,	0x07, 0x0d,	0x08, 0x98,	0x09, 0x02,	0x0a, 0x80,	0x0b, 0x40,	0x0c, 0x40,	0x0d, 0x00,	0x0e, 0x01,	0x0f, 0x7c,	0x10, 0x48,	0x11, 0x0c,	0x12, 0x8b,	0x13, 0x1a,	0x14, 0x00,	0x15, 0x00,	0x16, 0x00,	0x17, 0x00,	0x18, 0x00,	0x19, 0x00,	0x1a, 0x00,	0x1b, 0x00,	0x1c, 0x00,	0x1d, 0x00,	0x1e, 0x00,	0x41, 0x77,	0x42, 0x77,	0x43, 0x77,	0x44, 0x77,	0x45, 0x77,	0x46, 0x77,	0x47, 0x77,	0x48, 0x77,	0x49, 0x77,	0x4a, 0x77,	0x4b, 0x77,	0x4c, 0x77,	0x4d, 0x77,	0x4e, 0x77,	0x4f, 0x77,	0x50, 0x77,	0x51, 0x77,	0x52, 0x77,	0x53, 0x77,	0x54, 0x77,	0x55, 0x77,	0x56, 0x77,	0x57, 0xff,	0xff};static struct saa7146_ext_vv av7110_vv_data_st;static struct saa7146_ext_vv av7110_vv_data_c;int av7110_init_analog_module(struct av7110 *av7110){	u16 version1, version2;	if (i2c_writereg(av7110, 0x80, 0x0, 0x80) == 1 &&	    i2c_writereg(av7110, 0x80, 0x0, 0) == 1) {		printk("dvb-ttpci: DVB-C analog module @ card %d detected, initializing MSP3400\n",			av7110->dvb_adapter.num);		av7110->adac_type = DVB_ADAC_MSP34x0;	} else if (i2c_writereg(av7110, 0x84, 0x0, 0x80) == 1 &&		   i2c_writereg(av7110, 0x84, 0x0, 0) == 1) {		printk("dvb-ttpci: DVB-C analog module @ card %d detected, initializing MSP3415\n",			av7110->dvb_adapter.num);		av7110->adac_type = DVB_ADAC_MSP34x5;	} else		return -ENODEV;	msleep(100); // the probing above resets the msp...	msp_readreg(av7110, MSP_RD_DSP, 0x001e, &version1);	msp_readreg(av7110, MSP_RD_DSP, 0x001f, &version2);	dprintk(1, "dvb-ttpci: @ card %d MSP34xx version 0x%04x 0x%04x\n",		av7110->dvb_adapter.num, version1, version2);	msp_writereg(av7110, MSP_WR_DSP, 0x0013, 0x0c00);	msp_writereg(av7110, MSP_WR_DSP, 0x0000, 0x7f00); // loudspeaker + headphone	msp_writereg(av7110, MSP_WR_DSP, 0x0008, 0x0220); // loudspeaker source	msp_writereg(av7110, MSP_WR_DSP, 0x0009, 0x0220); // headphone source	msp_writereg(av7110, MSP_WR_DSP, 0x0004, 0x7f00); // loudspeaker volume	msp_writereg(av7110, MSP_WR_DSP, 0x000a, 0x0220); // SCART 1 source	msp_writereg(av7110, MSP_WR_DSP, 0x0007, 0x7f00); // SCART 1 volume	msp_writereg(av7110, MSP_WR_DSP, 0x000d, 0x1900); // prescale SCART	if (i2c_writereg(av7110, 0x48, 0x01, 0x00)!=1) {		INFO(("saa7113 not accessible.\n"));	} else {		u8 *i = saa7113_init_regs;		if ((av7110->dev->pci->subsystem_vendor == 0x110a) && (av7110->dev->pci->subsystem_device == 0x0000)) {			/* Fujitsu/Siemens DVB-Cable */			av7110->analog_tuner_flags |= ANALOG_TUNER_VES1820;		} else if ((av7110->dev->pci->subsystem_vendor == 0x13c2) && (av7110->dev->pci->subsystem_device == 0x0002)) {			/* Hauppauge/TT DVB-C premium */			av7110->analog_tuner_flags |= ANALOG_TUNER_VES1820;		} else if ((av7110->dev->pci->subsystem_vendor == 0x13c2) && (av7110->dev->pci->subsystem_device == 0x000A)) {			/* Hauppauge/TT DVB-C premium */			av7110->analog_tuner_flags |= ANALOG_TUNER_STV0297;		}		/* setup for DVB by default */		if (av7110->analog_tuner_flags & ANALOG_TUNER_VES1820) {			if (ves1820_writereg(av7110->dev, 0x09, 0x0f, 0x20))				dprintk(1, "setting band in demodulator failed.\n");		} else if (av7110->analog_tuner_flags & ANALOG_TUNER_STV0297) {			saa7146_setgpio(av7110->dev, 1, SAA7146_GPIO_OUTLO); // TDA9819 pin9(STD)			saa7146_setgpio(av7110->dev, 3, SAA7146_GPIO_OUTLO); // TDA9819 pin30(VIF)		}		/* init the saa7113 */		while (*i != 0xff) {			if (i2c_writereg(av7110, 0x48, i[0], i[1]) != 1) {				dprintk(1, "saa7113 initialization failed @ card %d", av7110->dvb_adapter.num);				break;			}			i += 2;		}		/* setup msp for analog sound: B/G Dual-FM */		msp_writereg(av7110, MSP_WR_DEM, 0x00bb, 0x02d0); // AD_CV		msp_writereg(av7110, MSP_WR_DEM, 0x0001,  3); // FIR1		msp_writereg(av7110, MSP_WR_DEM, 0x0001, 18); // FIR1		msp_writereg(av7110, MSP_WR_DEM, 0x0001, 27); // FIR1		msp_writereg(av7110, MSP_WR_DEM, 0x0001, 48); // FIR1		msp_writereg(av7110, MSP_WR_DEM, 0x0001, 66); // FIR1		msp_writereg(av7110, MSP_WR_DEM, 0x0001, 72); // FIR1		msp_writereg(av7110, MSP_WR_DEM, 0x0005,  4); // FIR2		msp_writereg(av7110, MSP_WR_DEM, 0x0005, 64); // FIR2		msp_writereg(av7110, MSP_WR_DEM, 0x0005,  0); // FIR2		msp_writereg(av7110, MSP_WR_DEM, 0x0005,  3); // FIR2		msp_writereg(av7110, MSP_WR_DEM, 0x0005, 18); // FIR2		msp_writereg(av7110, MSP_WR_DEM, 0x0005, 27); // FIR2		msp_writereg(av7110, MSP_WR_DEM, 0x0005, 48); // FIR2		msp_writereg(av7110, MSP_WR_DEM, 0x0005, 66); // FIR2		msp_writereg(av7110, MSP_WR_DEM, 0x0005, 72); // FIR2		msp_writereg(av7110, MSP_WR_DEM, 0x0083, 0xa000); // MODE_REG		msp_writereg(av7110, MSP_WR_DEM, 0x0093, 0x00aa); // DCO1_LO 5.74MHz		msp_writereg(av7110, MSP_WR_DEM, 0x009b, 0x04fc); // DCO1_HI		msp_writereg(av7110, MSP_WR_DEM, 0x00a3, 0x038e); // DCO2_LO 5.5MHz		msp_writereg(av7110, MSP_WR_DEM, 0x00ab, 0x04c6); // DCO2_HI		msp_writereg(av7110, MSP_WR_DEM, 0x0056, 0); // LOAD_REG 1/2	}	memcpy(standard, dvb_standard, sizeof(struct saa7146_standard) * 2);	/* set dd1 stream a & b */	saa7146_write(av7110->dev, DD1_STREAM_B, 0x00000000);	saa7146_write(av7110->dev, DD1_INIT, 0x03000700);	saa7146_write(av7110->dev, MC2, (MASK_09 | MASK_25 | MASK_10 | MASK_26));	return 0;}int av7110_init_v4l(struct av7110 *av7110){	struct saa7146_dev* dev = av7110->dev;	int ret;	/* special case DVB-C: these cards have an analog tuner	   plus need some special handling, so we have separate	   saa7146_ext_vv data for these... */	if (av7110->analog_tuner_flags)		ret = saa7146_vv_init(dev, &av7110_vv_data_c);	else		ret = saa7146_vv_init(dev, &av7110_vv_data_st);	if (ret) {		ERR(("cannot init capture device. skipping.\n"));		return -ENODEV;	}	if (saa7146_register_device(&av7110->v4l_dev, dev, "av7110", VFL_TYPE_GRABBER)) {		ERR(("cannot register capture device. skipping.\n"));		saa7146_vv_release(dev);		return -ENODEV;	}	if (saa7146_register_device(&av7110->vbi_dev, dev, "av7110", VFL_TYPE_VBI))		ERR(("cannot register vbi v4l2 device. skipping.\n"));	return 0;}int av7110_exit_v4l(struct av7110 *av7110){	struct saa7146_dev* dev = av7110->dev;	saa7146_unregister_device(&av7110->v4l_dev, av7110->dev);	saa7146_unregister_device(&av7110->vbi_dev, av7110->dev);	saa7146_vv_release(dev);	return 0;}/* FIXME: these values are experimental values that look better than the   values from the latest "official" driver -- at least for me... (MiHu) */static struct saa7146_standard standard[] = {	{		.name	= "PAL",	.id		= V4L2_STD_PAL_BG,		.v_offset	= 0x15,	.v_field	= 288,		.h_offset	= 0x48,	.h_pixels	= 708,		.v_max_out	= 576,	.h_max_out	= 768,	}, {		.name	= "NTSC",	.id		= V4L2_STD_NTSC,		.v_offset	= 0x10,	.v_field	= 244,		.h_offset	= 0x40,	.h_pixels	= 708,		.v_max_out	= 480,	.h_max_out	= 640,	}};static struct saa7146_standard analog_standard[] = {	{		.name	= "PAL",	.id		= V4L2_STD_PAL_BG,		.v_offset	= 0x1b,	.v_field	= 288,		.h_offset	= 0x08,	.h_pixels	= 708,		.v_max_out	= 576,	.h_max_out	= 768,	}, {		.name	= "NTSC",	.id		= V4L2_STD_NTSC,		.v_offset	= 0x10,	.v_field	= 244,		.h_offset	= 0x40,	.h_pixels	= 708,		.v_max_out	= 480,	.h_max_out	= 640,	}};static struct saa7146_standard dvb_standard[] = {	{		.name	= "PAL",	.id		= V4L2_STD_PAL_BG,		.v_offset	= 0x14,	.v_field	= 288,		.h_offset	= 0x48,	.h_pixels	= 708,		.v_max_out	= 576,	.h_max_out	= 768,	}, {		.name	= "NTSC",	.id		= V4L2_STD_NTSC,		.v_offset	= 0x10,	.v_field	= 244,		.h_offset	= 0x40,	.h_pixels	= 708,		.v_max_out	= 480,	.h_max_out	= 640,	}};static int std_callback(struct saa7146_dev* dev, struct saa7146_standard *std){	struct av7110 *av7110 = (struct av7110*) dev->ext_priv;	if (std->id & V4L2_STD_PAL) {		av7110->vidmode = AV7110_VIDEO_MODE_PAL;		av7110_set_vidmode(av7110, av7110->vidmode);	}	else if (std->id & V4L2_STD_NTSC) {		av7110->vidmode = AV7110_VIDEO_MODE_NTSC;		av7110_set_vidmode(av7110, av7110->vidmode);	}	else		return -1;	return 0;}static struct saa7146_ext_vv av7110_vv_data_st = {	.inputs		= 1,	.audios		= 1,	.capabilities	= V4L2_CAP_SLICED_VBI_OUTPUT,	.flags		= 0,	.stds		= &standard[0],	.num_stds	= ARRAY_SIZE(standard),	.std_callback	= &std_callback,	.ioctls		= &ioctls[0],	.ioctl		= av7110_ioctl,	.vbi_fops.open	= av7110_vbi_reset,	.vbi_fops.release = av7110_vbi_reset,	.vbi_fops.write	= av7110_vbi_write,};static struct saa7146_ext_vv av7110_vv_data_c = {	.inputs		= 1,	.audios		= 1,	.capabilities	= V4L2_CAP_TUNER | V4L2_CAP_SLICED_VBI_OUTPUT,	.flags		= SAA7146_USE_PORT_B_FOR_VBI,	.stds		= &standard[0],	.num_stds	= ARRAY_SIZE(standard),	.std_callback	= &std_callback,	.ioctls		= &ioctls[0],	.ioctl		= av7110_ioctl,	.vbi_fops.open	= av7110_vbi_reset,	.vbi_fops.release = av7110_vbi_reset,	.vbi_fops.write	= av7110_vbi_write,};

⌨️ 快捷键说明

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