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

📄 bttv-driver.c

📁 V4l driver for DVB HD
💻 C
📖 第 1 页 / 共 5 页
字号:
	}	c = btv->i2c_tvaudio_client;	if (c) {		struct v4l2_routing route;		route.input = input;		route.output = 0;		c->driver->command(c, VIDIOC_INT_S_AUDIO_ROUTING, &route);	}	return 0;}static inline intaudio_mute(struct bttv *btv, int mute){	return audio_mux(btv, btv->audio, mute);}static inline intaudio_input(struct bttv *btv, int input){	return audio_mux(btv, input, btv->mute);}static voidi2c_vidiocschan(struct bttv *btv){	v4l2_std_id std = bttv_tvnorms[btv->tvnorm].v4l2_id;	bttv_call_i2c_clients(btv, VIDIOC_S_STD, &std);	if (btv->c.type == BTTV_BOARD_VOODOOTV_FM)		bttv_tda9880_setnorm(btv,btv->tvnorm);}static intset_tvnorm(struct bttv *btv, unsigned int norm){	const struct bttv_tvnorm *tvnorm;	if (norm < 0 || norm >= BTTV_TVNORMS)		return -EINVAL;	btv->tvnorm = norm;	tvnorm = &bttv_tvnorms[norm];	btwrite(tvnorm->adelay, BT848_ADELAY);	btwrite(tvnorm->bdelay, BT848_BDELAY);	btaor(tvnorm->iform,~(BT848_IFORM_NORM|BT848_IFORM_XTBOTH),	      BT848_IFORM);	btwrite(tvnorm->vbipack, BT848_VBI_PACK_SIZE);	btwrite(1, BT848_VBI_PACK_DEL);	bt848A_set_timing(btv);	switch (btv->c.type) {	case BTTV_BOARD_VOODOOTV_FM:		bttv_tda9880_setnorm(btv,norm);		break;#if 0	case BTTV_BOARD_OSPREY540:		osprey_540_set_norm(btv,norm);		break;#endif	}	return 0;}static voidset_input(struct bttv *btv, unsigned int input){	unsigned long flags;	btv->input = input;	if (irq_iswitch) {		spin_lock_irqsave(&btv->s_lock,flags);		if (btv->curr.frame_irq) {			/* active capture -> delayed input switch */			btv->new_input = input;		} else {			video_mux(btv,input);		}		spin_unlock_irqrestore(&btv->s_lock,flags);	} else {		video_mux(btv,input);	}	audio_input(btv,(input == bttv_tvcards[btv->c.type].tuner ?		       TVAUDIO_INPUT_TUNER : TVAUDIO_INPUT_EXTERN));	set_tvnorm(btv,btv->tvnorm);	i2c_vidiocschan(btv);}static void init_irqreg(struct bttv *btv){	/* clear status */	btwrite(0xfffffUL, BT848_INT_STAT);	if (bttv_tvcards[btv->c.type].no_video) {		/* i2c only */		btwrite(BT848_INT_I2CDONE,			BT848_INT_MASK);	} else {		/* full video */		btwrite((btv->triton1)  |			(btv->gpioirq ? BT848_INT_GPINT : 0) |			BT848_INT_SCERR |			(fdsr ? BT848_INT_FDSR : 0) |			BT848_INT_RISCI|BT848_INT_OCERR|BT848_INT_VPRES|			BT848_INT_FMTCHG|BT848_INT_HLOCK|			BT848_INT_I2CDONE,			BT848_INT_MASK);	}}static void init_bt848(struct bttv *btv){	int val;	if (bttv_tvcards[btv->c.type].no_video) {		/* very basic init only */		init_irqreg(btv);		return;	}	btwrite(0x00, BT848_CAP_CTL);	btwrite(BT848_COLOR_CTL_GAMMA, BT848_COLOR_CTL);	btwrite(BT848_IFORM_XTAUTO | BT848_IFORM_AUTO, BT848_IFORM);	/* set planar and packed mode trigger points and         */	/* set rising edge of inverted GPINTR pin as irq trigger */	btwrite(BT848_GPIO_DMA_CTL_PKTP_32|		BT848_GPIO_DMA_CTL_PLTP1_16|		BT848_GPIO_DMA_CTL_PLTP23_16|		BT848_GPIO_DMA_CTL_GPINTC|		BT848_GPIO_DMA_CTL_GPINTI,		BT848_GPIO_DMA_CTL);	val = btv->opt_chroma_agc ? BT848_SCLOOP_CAGC : 0;	btwrite(val, BT848_E_SCLOOP);	btwrite(val, BT848_O_SCLOOP);	btwrite(0x20, BT848_E_VSCALE_HI);	btwrite(0x20, BT848_O_VSCALE_HI);	btwrite(BT848_ADC_RESERVED | (btv->opt_adc_crush ? BT848_ADC_CRUSH : 0),		BT848_ADC);	btwrite(whitecrush_upper, BT848_WC_UP);	btwrite(whitecrush_lower, BT848_WC_DOWN);	if (btv->opt_lumafilter) {		btwrite(0, BT848_E_CONTROL);		btwrite(0, BT848_O_CONTROL);	} else {		btwrite(BT848_CONTROL_LDEC, BT848_E_CONTROL);		btwrite(BT848_CONTROL_LDEC, BT848_O_CONTROL);	}	bt848_bright(btv,   btv->bright);	bt848_hue(btv,      btv->hue);	bt848_contrast(btv, btv->contrast);	bt848_sat(btv,      btv->saturation);	/* interrupt */	init_irqreg(btv);}static void bttv_reinit_bt848(struct bttv *btv){	unsigned long flags;	if (bttv_verbose)		printk(KERN_INFO "bttv%d: reset, reinitialize\n",btv->c.nr);	spin_lock_irqsave(&btv->s_lock,flags);	btv->errors=0;	bttv_set_dma(btv,0);	spin_unlock_irqrestore(&btv->s_lock,flags);	init_bt848(btv);	btv->pll.pll_current = -1;	set_input(btv,btv->input);}static int get_control(struct bttv *btv, struct v4l2_control *c){	struct video_audio va;	int i;	for (i = 0; i < BTTV_CTLS; i++)		if (bttv_ctls[i].id == c->id)			break;	if (i == BTTV_CTLS)		return -EINVAL;	if (btv->audio_hook && i >= 4 && i <= 8) {		memset(&va,0,sizeof(va));		btv->audio_hook(btv,&va,0);		switch (c->id) {		case V4L2_CID_AUDIO_MUTE:			c->value = (VIDEO_AUDIO_MUTE & va.flags) ? 1 : 0;			break;		case V4L2_CID_AUDIO_VOLUME:			c->value = va.volume;			break;		case V4L2_CID_AUDIO_BALANCE:			c->value = va.balance;			break;		case V4L2_CID_AUDIO_BASS:			c->value = va.bass;			break;		case V4L2_CID_AUDIO_TREBLE:			c->value = va.treble;			break;		}		return 0;	}	switch (c->id) {	case V4L2_CID_BRIGHTNESS:		c->value = btv->bright;		break;	case V4L2_CID_HUE:		c->value = btv->hue;		break;	case V4L2_CID_CONTRAST:		c->value = btv->contrast;		break;	case V4L2_CID_SATURATION:		c->value = btv->saturation;		break;	case V4L2_CID_AUDIO_MUTE:	case V4L2_CID_AUDIO_VOLUME:	case V4L2_CID_AUDIO_BALANCE:	case V4L2_CID_AUDIO_BASS:	case V4L2_CID_AUDIO_TREBLE:		bttv_call_i2c_clients(btv,VIDIOC_G_CTRL,c);		break;	case V4L2_CID_PRIVATE_CHROMA_AGC:		c->value = btv->opt_chroma_agc;		break;	case V4L2_CID_PRIVATE_COMBFILTER:		c->value = btv->opt_combfilter;		break;	case V4L2_CID_PRIVATE_LUMAFILTER:		c->value = btv->opt_lumafilter;		break;	case V4L2_CID_PRIVATE_AUTOMUTE:		c->value = btv->opt_automute;		break;	case V4L2_CID_PRIVATE_AGC_CRUSH:		c->value = btv->opt_adc_crush;		break;	case V4L2_CID_PRIVATE_VCR_HACK:		c->value = btv->opt_vcr_hack;		break;	case V4L2_CID_PRIVATE_WHITECRUSH_UPPER:		c->value = btv->opt_whitecrush_upper;		break;	case V4L2_CID_PRIVATE_WHITECRUSH_LOWER:		c->value = btv->opt_whitecrush_lower;		break;	case V4L2_CID_PRIVATE_UV_RATIO:		c->value = btv->opt_uv_ratio;		break;	case V4L2_CID_PRIVATE_FULL_LUMA_RANGE:		c->value = btv->opt_full_luma_range;		break;	case V4L2_CID_PRIVATE_CORING:		c->value = btv->opt_coring;		break;	default:		return -EINVAL;	}	return 0;}static int set_control(struct bttv *btv, struct v4l2_control *c){	struct video_audio va;	int i,val;	for (i = 0; i < BTTV_CTLS; i++)		if (bttv_ctls[i].id == c->id)			break;	if (i == BTTV_CTLS)		return -EINVAL;	if (btv->audio_hook && i >= 4 && i <= 8) {		memset(&va,0,sizeof(va));		btv->audio_hook(btv,&va,0);		switch (c->id) {		case V4L2_CID_AUDIO_MUTE:			if (c->value) {				va.flags |= VIDEO_AUDIO_MUTE;				audio_mute(btv, 1);			} else {				va.flags &= ~VIDEO_AUDIO_MUTE;				audio_mute(btv, 0);			}			break;		case V4L2_CID_AUDIO_VOLUME:			va.volume = c->value;			break;		case V4L2_CID_AUDIO_BALANCE:			va.balance = c->value;			break;		case V4L2_CID_AUDIO_BASS:			va.bass = c->value;			break;		case V4L2_CID_AUDIO_TREBLE:			va.treble = c->value;			break;		}		btv->audio_hook(btv,&va,1);		return 0;	}	switch (c->id) {	case V4L2_CID_BRIGHTNESS:		bt848_bright(btv,c->value);		break;	case V4L2_CID_HUE:		bt848_hue(btv,c->value);		break;	case V4L2_CID_CONTRAST:		bt848_contrast(btv,c->value);		break;	case V4L2_CID_SATURATION:		bt848_sat(btv,c->value);		break;	case V4L2_CID_AUDIO_MUTE:		audio_mute(btv, c->value);		/* fall through */	case V4L2_CID_AUDIO_VOLUME:	case V4L2_CID_AUDIO_BALANCE:	case V4L2_CID_AUDIO_BASS:	case V4L2_CID_AUDIO_TREBLE:		bttv_call_i2c_clients(btv,VIDIOC_S_CTRL,c);		break;	case V4L2_CID_PRIVATE_CHROMA_AGC:		btv->opt_chroma_agc = c->value;		val = btv->opt_chroma_agc ? BT848_SCLOOP_CAGC : 0;		btwrite(val, BT848_E_SCLOOP);		btwrite(val, BT848_O_SCLOOP);		break;	case V4L2_CID_PRIVATE_COMBFILTER:		btv->opt_combfilter = c->value;		break;	case V4L2_CID_PRIVATE_LUMAFILTER:		btv->opt_lumafilter = c->value;		if (btv->opt_lumafilter) {			btand(~BT848_CONTROL_LDEC, BT848_E_CONTROL);			btand(~BT848_CONTROL_LDEC, BT848_O_CONTROL);		} else {			btor(BT848_CONTROL_LDEC, BT848_E_CONTROL);			btor(BT848_CONTROL_LDEC, BT848_O_CONTROL);		}		break;	case V4L2_CID_PRIVATE_AUTOMUTE:		btv->opt_automute = c->value;		break;	case V4L2_CID_PRIVATE_AGC_CRUSH:		btv->opt_adc_crush = c->value;		btwrite(BT848_ADC_RESERVED | (btv->opt_adc_crush ? BT848_ADC_CRUSH : 0),			BT848_ADC);		break;	case V4L2_CID_PRIVATE_VCR_HACK:		btv->opt_vcr_hack = c->value;		break;	case V4L2_CID_PRIVATE_WHITECRUSH_UPPER:		btv->opt_whitecrush_upper = c->value;		btwrite(c->value, BT848_WC_UP);		break;	case V4L2_CID_PRIVATE_WHITECRUSH_LOWER:		btv->opt_whitecrush_lower = c->value;		btwrite(c->value, BT848_WC_DOWN);		break;	case V4L2_CID_PRIVATE_UV_RATIO:		btv->opt_uv_ratio = c->value;		bt848_sat(btv, btv->saturation);		break;	case V4L2_CID_PRIVATE_FULL_LUMA_RANGE:		btv->opt_full_luma_range = c->value;		btaor((c->value<<7), ~BT848_OFORM_RANGE, BT848_OFORM);		break;	case V4L2_CID_PRIVATE_CORING:		btv->opt_coring = c->value;		btaor((c->value<<5), ~BT848_OFORM_CORE32, BT848_OFORM);		break;	default:		return -EINVAL;	}	return 0;}/* ----------------------------------------------------------------------- */void bttv_gpio_tracking(struct bttv *btv, char *comment){	unsigned int outbits, data;	outbits = btread(BT848_GPIO_OUT_EN);	data    = btread(BT848_GPIO_DATA);	printk(KERN_DEBUG "bttv%d: gpio: en=%08x, out=%08x in=%08x [%s]\n",	       btv->c.nr,outbits,data & outbits, data & ~outbits, comment);}static void bttv_field_count(struct bttv *btv){	int need_count = 0;	if (btv->users)		need_count++;	if (need_count) {		/* start field counter */		btor(BT848_INT_VSYNC,BT848_INT_MASK);	} else {		/* stop field counter */		btand(~BT848_INT_VSYNC,BT848_INT_MASK);		btv->field_count = 0;	}}static const struct bttv_format*format_by_palette(int palette){	unsigned int i;	for (i = 0; i < BTTV_FORMATS; i++) {		if (-1 == bttv_formats[i].palette)			continue;		if (bttv_formats[i].palette == palette)			return bttv_formats+i;	}	return NULL;}static const struct bttv_format*format_by_fourcc(int fourcc){	unsigned int i;	for (i = 0; i < BTTV_FORMATS; i++) {		if (-1 == bttv_formats[i].fourcc)			continue;		if (bttv_formats[i].fourcc == fourcc)			return bttv_formats+i;	}	return NULL;}/* ----------------------------------------------------------------------- *//* misc helpers                                                            */static intbttv_switch_overlay(struct bttv *btv, struct bttv_fh *fh,		    struct bttv_buffer *new){	struct bttv_buffer *old;	unsigned long flags;	int retval = 0;	dprintk("switch_overlay: enter [new=%p]\n",new);	if (new)		new->vb.state = STATE_DONE;	spin_lock_irqsave(&btv->s_lock,flags);	old = btv->screen;	btv->screen = new;	btv->loop_irq |= 1;	bttv_set_dma(btv, 0x03);	spin_unlock_irqrestore(&btv->s_lock,flags);	if (NULL == new)		free_btres(btv,fh,RESOURCE_OVERLAY);	if (NULL != old) {		dprintk("switch_overlay: old=%p state is %d\n",old,old->vb.state);		bttv_dma_free(&fh->cap,btv, old);		kfree(old);	}	dprintk("switch_overlay: done\n");	return retval;}/* ----------------------------------------------------------------------- *//* video4linux (1) interface                                               */static int bttv_prepare_buffer(struct videobuf_queue *q,struct bttv *btv,			       struct bttv_buffer *buf,			       const struct bttv_format *fmt,			       unsigned int width, unsigned int height,			       enum v4l2_field field){	int redo_dma_risc = 0;	int rc;	/* check settings */	if (NULL == fmt)		return -EINVAL;	if (fmt->btformat == BT848_COLOR_FMT_RAW) {		width  = RAW_BPL;		height = RAW_LINES*2;		if (width*height > buf->vb.bsize)			return -EINVAL;		buf->vb.size = buf->vb.bsize;	} else {		if (width  < 48 ||		    height < 32 ||		    width  > bttv_tvnorms[btv->tvnorm].swidth ||		    height > bttv_tvnorms[btv->tvnorm].sheight)			return -EINVAL;		buf->vb.size = (width * height * fmt->depth) >> 3;		if (0 != buf->vb.baddr  &&  buf->vb.bsize < buf->vb.size)			return -EINVAL;

⌨️ 快捷键说明

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