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

📄 cx88-video.c

📁 trident tm5600的linux驱动
💻 C
📖 第 1 页 / 共 5 页
字号:
	/* We should remember that this driver also supports teletext,  */	/* so we have to test if the v4l2_buf_type is VBI capture data. */	if (unlikely((fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) &&		     (fh->type != V4L2_BUF_TYPE_VBI_CAPTURE)))		return -EINVAL;	if (unlikely(i != fh->type))		return -EINVAL;	if (unlikely(!res_get(dev,fh,get_ressource(fh))))		return -EBUSY;	return videobuf_streamon(get_queue(fh));}static int vidioc_streamoff(struct file *file, void *priv, enum v4l2_buf_type i){	struct cx8800_fh  *fh   = priv;	struct cx8800_dev *dev  = fh->dev;	int               err, res;	if ((fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) &&	    (fh->type != V4L2_BUF_TYPE_VBI_CAPTURE))		return -EINVAL;	if (i != fh->type)		return -EINVAL;	res = get_ressource(fh);	err = videobuf_streamoff(get_queue(fh));	if (err < 0)		return err;	res_free(dev,fh,res);	return 0;}static int vidioc_s_std (struct file *file, void *priv, v4l2_std_id *tvnorms){	struct cx88_core  *core = ((struct cx8800_fh *)priv)->dev->core;	mutex_lock(&core->lock);	cx88_set_tvnorm(core,*tvnorms);	mutex_unlock(&core->lock);	return 0;}/* only one input in this sample driver */int cx88_enum_input (struct cx88_core  *core,struct v4l2_input *i){	static const char *iname[] = {		[ CX88_VMUX_COMPOSITE1 ] = "Composite1",		[ CX88_VMUX_COMPOSITE2 ] = "Composite2",		[ CX88_VMUX_COMPOSITE3 ] = "Composite3",		[ CX88_VMUX_COMPOSITE4 ] = "Composite4",		[ CX88_VMUX_SVIDEO     ] = "S-Video",		[ CX88_VMUX_TELEVISION ] = "Television",		[ CX88_VMUX_CABLE      ] = "Cable TV",		[ CX88_VMUX_DVB        ] = "DVB",		[ CX88_VMUX_DEBUG      ] = "for debug only",	};	unsigned int n;	n = i->index;	if (n >= 4)		return -EINVAL;	if (0 == INPUT(n).type)		return -EINVAL;	memset(i,0,sizeof(*i));	i->index = n;	i->type  = V4L2_INPUT_TYPE_CAMERA;	strcpy(i->name,iname[INPUT(n).type]);	if ((CX88_VMUX_TELEVISION == INPUT(n).type) ||	    (CX88_VMUX_CABLE      == INPUT(n).type))		i->type = V4L2_INPUT_TYPE_TUNER;		i->std = CX88_NORMS;	return 0;}EXPORT_SYMBOL(cx88_enum_input);static int vidioc_enum_input (struct file *file, void *priv,				struct v4l2_input *i){	struct cx88_core  *core = ((struct cx8800_fh *)priv)->dev->core;	return cx88_enum_input (core,i);}static int vidioc_g_input (struct file *file, void *priv, unsigned int *i){	struct cx88_core  *core = ((struct cx8800_fh *)priv)->dev->core;	*i = core->input;	return 0;}static int vidioc_s_input (struct file *file, void *priv, unsigned int i){	struct cx88_core  *core = ((struct cx8800_fh *)priv)->dev->core;	if (i >= 4)		return -EINVAL;	mutex_lock(&core->lock);	cx88_newstation(core);	cx88_video_mux(core,i);	mutex_unlock(&core->lock);	return 0;}#if 0static int vidioc_g_audio (struct file *file, void *priv, unsigned int i){	struct v4l2_audio *a = arg;	unsigned int n = a->index;	memset(a,0,sizeof(*a));	a->index = n;	switch (n) {	case 0:		if ((CX88_VMUX_TELEVISION == INPUT(n).type) ||		    (CX88_VMUX_CABLE == INPUT(n).type)) {			strcpy(a->name,"Television");			/* FIXME figure out if stereo received and set V4L2_AUDCAP_STEREO. */			return 0;		}		break;	case 1:		if (CX88_BOARD_DVICO_FUSIONHDTV_3_GOLD_Q == core->boardnr) {			strcpy(a->name,"Line In");			a->capability = V4L2_AUDCAP_STEREO;			return 0;		}		break;	}	/* Audio input not available. */	return -EINVAL;}#endifstatic int vidioc_queryctrl (struct file *file, void *priv,				struct v4l2_queryctrl *qctrl){	struct cx88_core *core = ((struct cx8800_fh *)priv)->dev->core;	qctrl->id = v4l2_ctrl_next(ctrl_classes, qctrl->id);	if (unlikely(qctrl->id == 0))		return -EINVAL;	return cx8800_ctrl_query(core, qctrl);}static int vidioc_g_ctrl (struct file *file, void *priv,				struct v4l2_control *ctl){	struct cx88_core  *core = ((struct cx8800_fh *)priv)->dev->core;	return		cx88_get_control(core,ctl);}static int vidioc_s_ctrl (struct file *file, void *priv,				struct v4l2_control *ctl){	struct cx88_core  *core = ((struct cx8800_fh *)priv)->dev->core;	return		cx88_set_control(core,ctl);}static int vidioc_g_tuner (struct file *file, void *priv,				struct v4l2_tuner *t){	struct cx88_core  *core = ((struct cx8800_fh *)priv)->dev->core;	u32 reg;	if (unlikely(UNSET == core->board.tuner_type))		return -EINVAL;	if (0 != t->index)		return -EINVAL;	strcpy(t->name, "Television");	t->type       = V4L2_TUNER_ANALOG_TV;	t->capability = V4L2_TUNER_CAP_NORM;	t->rangehigh  = 0xffffffffUL;	cx88_get_stereo(core ,t);	reg = cx_read(MO_DEVICE_STATUS);	t->signal = (reg & (1<<5)) ? 0xffff : 0x0000;	return 0;}static int vidioc_s_tuner (struct file *file, void *priv,				struct v4l2_tuner *t){	struct cx88_core  *core = ((struct cx8800_fh *)priv)->dev->core;	if (UNSET == core->board.tuner_type)		return -EINVAL;	if (0 != t->index)		return -EINVAL;	cx88_set_stereo(core, t->audmode, 1);	return 0;}static int vidioc_g_frequency (struct file *file, void *priv,				struct v4l2_frequency *f){	struct cx8800_fh  *fh   = priv;	struct cx88_core  *core = fh->dev->core;	if (unlikely(UNSET == core->board.tuner_type))		return -EINVAL;	/* f->type = fh->radio ? V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV; */	f->type = fh->radio ? V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV;	f->frequency = core->freq;	cx88_call_i2c_clients(core,VIDIOC_G_FREQUENCY,f);	return 0;}int cx88_set_freq (struct cx88_core  *core,				struct v4l2_frequency *f){	if (unlikely(UNSET == core->board.tuner_type))		return -EINVAL;	if (unlikely(f->tuner != 0))		return -EINVAL;	mutex_lock(&core->lock);	core->freq = f->frequency;	cx88_newstation(core);	cx88_call_i2c_clients(core,VIDIOC_S_FREQUENCY,f);	/* When changing channels it is required to reset TVAUDIO */	msleep (10);	cx88_set_tvaudio(core);	mutex_unlock(&core->lock);	return 0;}EXPORT_SYMBOL(cx88_set_freq);static int vidioc_s_frequency (struct file *file, void *priv,				struct v4l2_frequency *f){	struct cx8800_fh  *fh   = priv;	struct cx88_core  *core = fh->dev->core;	if (unlikely(0 == fh->radio && f->type != V4L2_TUNER_ANALOG_TV))		return -EINVAL;	if (unlikely(1 == fh->radio && f->type != V4L2_TUNER_RADIO))		return -EINVAL;	return		cx88_set_freq (core,f);}#ifdef CONFIG_VIDEO_ADV_DEBUGstatic int vidioc_g_register (struct file *file, void *fh,				struct v4l2_register *reg){	struct cx88_core *core = ((struct cx8800_fh*)fh)->dev->core;	if (!v4l2_chip_match_host(reg->match_type, reg->match_chip))		return -EINVAL;	/* cx2388x has a 24-bit register space */	reg->val = cx_read(reg->reg&0xffffff);	return 0;}static int vidioc_s_register (struct file *file, void *fh,				struct v4l2_register *reg){	struct cx88_core *core = ((struct cx8800_fh*)fh)->dev->core;	if (!v4l2_chip_match_host(reg->match_type, reg->match_chip))		return -EINVAL;	cx_write(reg->reg&0xffffff, reg->val);	return 0;}#endif/* ----------------------------------------------------------- *//* RADIO ESPECIFIC IOCTLS                                      *//* ----------------------------------------------------------- */static int radio_querycap (struct file *file, void  *priv,					struct v4l2_capability *cap){	struct cx8800_dev *dev  = ((struct cx8800_fh *)priv)->dev;	struct cx88_core  *core = dev->core;	strcpy(cap->driver, "cx8800");	strlcpy(cap->card, core->board.name, sizeof(cap->card));	sprintf(cap->bus_info,"PCI:%s", pci_name(dev->pci));	cap->version = CX88_VERSION_CODE;	cap->capabilities = V4L2_CAP_TUNER;	return 0;}static int radio_g_tuner (struct file *file, void *priv,				struct v4l2_tuner *t){	struct cx88_core  *core = ((struct cx8800_fh *)priv)->dev->core;	if (unlikely(t->index > 0))		return -EINVAL;	strcpy(t->name, "Radio");	t->type = V4L2_TUNER_RADIO;	cx88_call_i2c_clients(core,VIDIOC_G_TUNER,t);	return 0;}static int radio_enum_input (struct file *file, void *priv,				struct v4l2_input *i){	if (i->index != 0)		return -EINVAL;	strcpy(i->name,"Radio");	i->type = V4L2_INPUT_TYPE_TUNER;	return 0;}static int radio_g_audio (struct file *file, void *priv, struct v4l2_audio *a){	if (unlikely(a->index))		return -EINVAL;	memset(a,0,sizeof(*a));	strcpy(a->name,"Radio");	return 0;}/* FIXME: Should add a standard for radio */static int radio_s_tuner (struct file *file, void *priv,				struct v4l2_tuner *t){	struct cx88_core  *core = ((struct cx8800_fh *)priv)->dev->core;	if (0 != t->index)		return -EINVAL;	cx88_call_i2c_clients(core,VIDIOC_S_TUNER,t);	return 0;}static int radio_s_audio (struct file *file, void *fh,			  struct v4l2_audio *a){	return 0;}static int radio_s_input (struct file *file, void *fh, unsigned int i){	return 0;}static int radio_queryctrl (struct file *file, void *priv,			    struct v4l2_queryctrl *c){	int i;	if (c->id <  V4L2_CID_BASE ||		c->id >= V4L2_CID_LASTP1)		return -EINVAL;	if (c->id == V4L2_CID_AUDIO_MUTE) {		for (i = 0; i < CX8800_CTLS; i++)			if (cx8800_ctls[i].v.id == c->id)				break;		*c = cx8800_ctls[i].v;	} else		*c = no_ctl;	return 0;}/* ----------------------------------------------------------- */static void cx8800_vid_timeout(unsigned long data){	struct cx8800_dev *dev = (struct cx8800_dev*)data;	struct cx88_core *core = dev->core;	struct cx88_dmaqueue *q = &dev->vidq;	struct cx88_buffer *buf;	unsigned long flags;	cx88_sram_channel_dump(core, &cx88_sram_channels[SRAM_CH21]);	cx_clear(MO_VID_DMACNTRL, 0x11);	cx_clear(VID_CAPTURE_CONTROL, 0x06);	spin_lock_irqsave(&dev->slock,flags);	while (!list_empty(&q->active)) {		buf = list_entry(q->active.next, struct cx88_buffer, vb.queue);		list_del(&buf->vb.queue);		buf->vb.state = VIDEOBUF_ERROR;		wake_up(&buf->vb.done);		printk("%s/0: [%p/%d] timeout - dma=0x%08lx\n", core->name,		       buf, buf->vb.i, (unsigned long)buf->risc.dma);	}	restart_video_queue(dev,q);	spin_unlock_irqrestore(&dev->slock,flags);}static char *cx88_vid_irqs[32] = {	"y_risci1", "u_risci1", "v_risci1", "vbi_risc1",	"y_risci2", "u_risci2", "v_risci2", "vbi_risc2",	"y_oflow",  "u_oflow",  "v_oflow",  "vbi_oflow",	"y_sync",   "u_sync",   "v_sync",   "vbi_sync",	"opc_err",  "par_err",  "rip_err",  "pci_abort",};static void cx8800_vid_irq(struct cx8800_dev *dev){	struct cx88_core *core = dev->core;	u32 status, mask, count;	status = cx_read(MO_VID_INTSTAT);	mask   = cx_read(MO_VID_INTMSK);	if (0 == (status & mask))		return;	cx_write(MO_VID_INTSTAT, status);	if (irq_debug  ||  (status & mask & ~0xff))		cx88_print_irqbits(core->name, "irq vid",				   cx88_vid_irqs, ARRAY_SIZE(cx88_vid_irqs),				   status, mask);	/* risc op code error */	if (status & (1 << 16)) {		printk(KERN_WARNING "%s/0: video risc op code error\n",core->name);		cx_clear(MO_VID_DMACNTRL, 0x11);		cx_clear(VID_CAPTURE_CONTROL, 0x06);		cx88_sram_channel_dump(core, &cx88_sram_channels[SRAM_CH21]);	}	/* risc1 y */	if (status & 0x01) {		spin_lock(&dev->slock);		count = cx_read(MO_VIDY_GPCNT);		cx88_wakeup(core, &dev->vidq, count);		spin_unlock(&dev->slock);	}	/* risc1 vbi */	if (status & 0x08) {		spin_lock(&dev->slock);		count = cx_read(MO_VBI_GPCNT);		cx88_wakeup(core, &dev->vbiq, count);		spin_unlock(&dev->slock);	}	/* risc2 y */	if (status & 0x10) {		dprintk(2,"stopper video\n");		spin_lock(&dev->slock);		restart_video_queue(dev,&dev->vidq);		spin_unlock(&dev->slock);	}	/* risc2 vbi */	if (status & 0x80) {		dprintk(2,"stopper vbi\n");		spin_lock(&dev->slock);		cx8800_restart_vbi_queue(dev,&dev->vbiq);		spin_unlock(&dev->slock);	}}#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19)static irqreturn_t cx8800_irq(int irq, void *dev_id, struct pt_regs *regs)#elsestatic irqreturn_t cx8800_irq(int irq, void *dev_id)#endif{	struct cx8800_dev *dev = dev_id;	struct cx88_core *core = dev->core;	u32 status;	int loop, handled = 0;	for (loop = 0; loop < 10; loop++) {

⌨️ 快捷键说明

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