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

📄 saa7134-video.c

📁 trident tm5600的linux驱动
💻 C
📖 第 1 页 / 共 5 页
字号:
		/* no, someone else uses it */		mutex_unlock(&dev->lock);		return 0;	}	/* it's free, grab it */	fh->resources  |= bit;	dev->resources |= bit;	dprintk("res: get %d\n",bit);	mutex_unlock(&dev->lock);	return 1;}static int res_check(struct saa7134_fh *fh, unsigned int bit){	return (fh->resources & bit);}static int res_locked(struct saa7134_dev *dev, unsigned int bit){	return (dev->resources & bit);}staticvoid res_free(struct saa7134_dev *dev, struct saa7134_fh *fh, unsigned int bits){	BUG_ON((fh->resources & bits) != bits);	mutex_lock(&dev->lock);	fh->resources  &= ~bits;	dev->resources &= ~bits;	dprintk("res: put %d\n",bits);	mutex_unlock(&dev->lock);}/* ------------------------------------------------------------------ */static void set_tvnorm(struct saa7134_dev *dev, struct saa7134_tvnorm *norm){	dprintk("set tv norm = %s\n",norm->name);	dev->tvnorm = norm;	/* setup cropping */	dev->crop_bounds.left    = norm->h_start;	dev->crop_defrect.left   = norm->h_start;	dev->crop_bounds.width   = norm->h_stop - norm->h_start +1;	dev->crop_defrect.width  = norm->h_stop - norm->h_start +1;	dev->crop_bounds.top     = (norm->vbi_v_stop_0+1)*2;	dev->crop_defrect.top    = norm->video_v_start*2;	dev->crop_bounds.height  = ((norm->id & V4L2_STD_525_60) ? 524 : 624)		- dev->crop_bounds.top;	dev->crop_defrect.height = (norm->video_v_stop - norm->video_v_start +1)*2;	dev->crop_current = dev->crop_defrect;	saa7134_set_tvnorm_hw(dev);}static void video_mux(struct saa7134_dev *dev, int input){	dprintk("video input = %d [%s]\n", input, card_in(dev, input).name);	dev->ctl_input = input;	set_tvnorm(dev, dev->tvnorm);	saa7134_tvaudio_setinput(dev, &card_in(dev, input));}static void saa7134_set_decoder(struct saa7134_dev *dev){	int luma_control, sync_control, mux;	struct saa7134_tvnorm *norm = dev->tvnorm;	mux = card_in(dev, dev->ctl_input).vmux;	luma_control = norm->luma_control;	sync_control = norm->sync_control;	if (mux > 5)		luma_control |= 0x80; /* svideo */	if (noninterlaced || dev->nosignal)		sync_control |= 0x20;	/* setup video decoder */	saa_writeb(SAA7134_INCR_DELAY,            0x08);	saa_writeb(SAA7134_ANALOG_IN_CTRL1,       0xc0 | mux);	saa_writeb(SAA7134_ANALOG_IN_CTRL2,       0x00);	saa_writeb(SAA7134_ANALOG_IN_CTRL3,       0x90);	saa_writeb(SAA7134_ANALOG_IN_CTRL4,       0x90);	saa_writeb(SAA7134_HSYNC_START,           0xeb);	saa_writeb(SAA7134_HSYNC_STOP,            0xe0);	saa_writeb(SAA7134_SOURCE_TIMING1,        norm->src_timing);	saa_writeb(SAA7134_SYNC_CTRL,             sync_control);	saa_writeb(SAA7134_LUMA_CTRL,             luma_control);	saa_writeb(SAA7134_DEC_LUMA_BRIGHT,       dev->ctl_bright);	saa_writeb(SAA7134_DEC_LUMA_CONTRAST,		dev->ctl_invert ? -dev->ctl_contrast : dev->ctl_contrast);	saa_writeb(SAA7134_DEC_CHROMA_SATURATION,		dev->ctl_invert ? -dev->ctl_saturation : dev->ctl_saturation);	saa_writeb(SAA7134_DEC_CHROMA_HUE,        dev->ctl_hue);	saa_writeb(SAA7134_CHROMA_CTRL1,          norm->chroma_ctrl1);	saa_writeb(SAA7134_CHROMA_GAIN,           norm->chroma_gain);	saa_writeb(SAA7134_CHROMA_CTRL2,          norm->chroma_ctrl2);	saa_writeb(SAA7134_MODE_DELAY_CTRL,       0x00);	saa_writeb(SAA7134_ANALOG_ADC,            0x01);	saa_writeb(SAA7134_VGATE_START,           0x11);	saa_writeb(SAA7134_VGATE_STOP,            0xfe);	saa_writeb(SAA7134_MISC_VGATE_MSB,        norm->vgate_misc);	saa_writeb(SAA7134_RAW_DATA_GAIN,         0x40);	saa_writeb(SAA7134_RAW_DATA_OFFSET,       0x80);}void saa7134_set_tvnorm_hw(struct saa7134_dev *dev){	saa7134_set_decoder(dev);	if (card_in(dev, dev->ctl_input).tv)		saa7134_i2c_call_clients(dev, VIDIOC_S_STD, &dev->tvnorm->id);	/* Set the correct norm for the saa6752hs. This function	   does nothing if there is no saa6752hs. */	saa7134_i2c_call_saa6752(dev, VIDIOC_S_STD, &dev->tvnorm->id);}static void set_h_prescale(struct saa7134_dev *dev, int task, int prescale){	static const struct {		int xpsc;		int xacl;		int xc2_1;		int xdcg;		int vpfy;	} vals[] = {		/* XPSC XACL XC2_1 XDCG VPFY */		{    1,   0,    0,    0,   0 },		{    2,   2,    1,    2,   2 },		{    3,   4,    1,    3,   2 },		{    4,   8,    1,    4,   2 },		{    5,   8,    1,    4,   2 },		{    6,   8,    1,    4,   3 },		{    7,   8,    1,    4,   3 },		{    8,  15,    0,    4,   3 },		{    9,  15,    0,    4,   3 },		{   10,  16,    1,    5,   3 },	};	static const int count = ARRAY_SIZE(vals);	int i;	for (i = 0; i < count; i++)		if (vals[i].xpsc == prescale)			break;	if (i == count)		return;	saa_writeb(SAA7134_H_PRESCALE(task), vals[i].xpsc);	saa_writeb(SAA7134_ACC_LENGTH(task), vals[i].xacl);	saa_writeb(SAA7134_LEVEL_CTRL(task),		   (vals[i].xc2_1 << 3) | (vals[i].xdcg));	saa_andorb(SAA7134_FIR_PREFILTER_CTRL(task), 0x0f,		   (vals[i].vpfy << 2) | vals[i].vpfy);}static void set_v_scale(struct saa7134_dev *dev, int task, int yscale){	int val,mirror;	saa_writeb(SAA7134_V_SCALE_RATIO1(task), yscale &  0xff);	saa_writeb(SAA7134_V_SCALE_RATIO2(task), yscale >> 8);	mirror = (dev->ctl_mirror) ? 0x02 : 0x00;	if (yscale < 2048) {		/* LPI */		dprintk("yscale LPI yscale=%d\n",yscale);		saa_writeb(SAA7134_V_FILTER(task), 0x00 | mirror);		saa_writeb(SAA7134_LUMA_CONTRAST(task), 0x40);		saa_writeb(SAA7134_CHROMA_SATURATION(task), 0x40);	} else {		/* ACM */		val = 0x40 * 1024 / yscale;		dprintk("yscale ACM yscale=%d val=0x%x\n",yscale,val);		saa_writeb(SAA7134_V_FILTER(task), 0x01 | mirror);		saa_writeb(SAA7134_LUMA_CONTRAST(task), val);		saa_writeb(SAA7134_CHROMA_SATURATION(task), val);	}	saa_writeb(SAA7134_LUMA_BRIGHT(task),       0x80);}static void set_size(struct saa7134_dev *dev, int task,		     int width, int height, int interlace){	int prescale,xscale,yscale,y_even,y_odd;	int h_start, h_stop, v_start, v_stop;	int div = interlace ? 2 : 1;	/* setup video scaler */	h_start = dev->crop_current.left;	v_start = dev->crop_current.top/2;	h_stop  = (dev->crop_current.left + dev->crop_current.width -1);	v_stop  = (dev->crop_current.top + dev->crop_current.height -1)/2;	saa_writeb(SAA7134_VIDEO_H_START1(task), h_start &  0xff);	saa_writeb(SAA7134_VIDEO_H_START2(task), h_start >> 8);	saa_writeb(SAA7134_VIDEO_H_STOP1(task),  h_stop  &  0xff);	saa_writeb(SAA7134_VIDEO_H_STOP2(task),  h_stop  >> 8);	saa_writeb(SAA7134_VIDEO_V_START1(task), v_start &  0xff);	saa_writeb(SAA7134_VIDEO_V_START2(task), v_start >> 8);	saa_writeb(SAA7134_VIDEO_V_STOP1(task),  v_stop  &  0xff);	saa_writeb(SAA7134_VIDEO_V_STOP2(task),  v_stop  >> 8);	prescale = dev->crop_current.width / width;	if (0 == prescale)		prescale = 1;	xscale = 1024 * dev->crop_current.width / prescale / width;	yscale = 512 * div * dev->crop_current.height / height;	dprintk("prescale=%d xscale=%d yscale=%d\n",prescale,xscale,yscale);	set_h_prescale(dev,task,prescale);	saa_writeb(SAA7134_H_SCALE_INC1(task),      xscale &  0xff);	saa_writeb(SAA7134_H_SCALE_INC2(task),      xscale >> 8);	set_v_scale(dev,task,yscale);	saa_writeb(SAA7134_VIDEO_PIXELS1(task),     width  & 0xff);	saa_writeb(SAA7134_VIDEO_PIXELS2(task),     width  >> 8);	saa_writeb(SAA7134_VIDEO_LINES1(task),      height/div & 0xff);	saa_writeb(SAA7134_VIDEO_LINES2(task),      height/div >> 8);	/* deinterlace y offsets */	y_odd  = dev->ctl_y_odd;	y_even = dev->ctl_y_even;	saa_writeb(SAA7134_V_PHASE_OFFSET0(task), y_odd);	saa_writeb(SAA7134_V_PHASE_OFFSET1(task), y_even);	saa_writeb(SAA7134_V_PHASE_OFFSET2(task), y_odd);	saa_writeb(SAA7134_V_PHASE_OFFSET3(task), y_even);}/* ------------------------------------------------------------------ */struct cliplist {	__u16 position;	__u8  enable;	__u8  disable;};static void set_cliplist(struct saa7134_dev *dev, int reg,			struct cliplist *cl, int entries, char *name){	__u8 winbits = 0;	int i;	for (i = 0; i < entries; i++) {		winbits |= cl[i].enable;		winbits &= ~cl[i].disable;		if (i < 15 && cl[i].position == cl[i+1].position)			continue;		saa_writeb(reg + 0, winbits);		saa_writeb(reg + 2, cl[i].position & 0xff);		saa_writeb(reg + 3, cl[i].position >> 8);		dprintk("clip: %s winbits=%02x pos=%d\n",			name,winbits,cl[i].position);		reg += 8;	}	for (; reg < 0x400; reg += 8) {		saa_writeb(reg+ 0, 0);		saa_writeb(reg + 1, 0);		saa_writeb(reg + 2, 0);		saa_writeb(reg + 3, 0);	}}static int clip_range(int val){	if (val < 0)		val = 0;	return val;}/* Sort into smallest position first order */static int cliplist_cmp(const void *a, const void *b){	const struct cliplist *cla = a;	const struct cliplist *clb = b;	if (cla->position < clb->position)		return -1;	if (cla->position > clb->position)		return 1;	return 0;}static int setup_clipping(struct saa7134_dev *dev, struct v4l2_clip *clips,			  int nclips, int interlace){	struct cliplist col[16], row[16];	int cols = 0, rows = 0, i;	int div = interlace ? 2 : 1;	memset(col, 0, sizeof(col));	memset(row, 0, sizeof(row));	for (i = 0; i < nclips && i < 8; i++) {		col[cols].position = clip_range(clips[i].c.left);		col[cols].enable   = (1 << i);		cols++;		col[cols].position = clip_range(clips[i].c.left+clips[i].c.width);		col[cols].disable  = (1 << i);		cols++;		row[rows].position = clip_range(clips[i].c.top / div);		row[rows].enable   = (1 << i);		rows++;		row[rows].position = clip_range((clips[i].c.top + clips[i].c.height)						/ div);		row[rows].disable  = (1 << i);		rows++;	}	sort(col, cols, sizeof col[0], cliplist_cmp, NULL);	sort(row, rows, sizeof row[0], cliplist_cmp, NULL);	set_cliplist(dev,0x380,col,cols,"cols");	set_cliplist(dev,0x384,row,rows,"rows");	return 0;}static int verify_preview(struct saa7134_dev *dev, struct v4l2_window *win){	enum v4l2_field field;	int maxw, maxh;	if (NULL == dev->ovbuf.base)		return -EINVAL;	if (NULL == dev->ovfmt)		return -EINVAL;	if (win->w.width < 48 || win->w.height <  32)		return -EINVAL;	if (win->clipcount > 2048)		return -EINVAL;	field = win->field;	maxw  = dev->crop_current.width;	maxh  = dev->crop_current.height;	if (V4L2_FIELD_ANY == field) {		field = (win->w.height > maxh/2)			? V4L2_FIELD_INTERLACED			: V4L2_FIELD_TOP;	}	switch (field) {	case V4L2_FIELD_TOP:	case V4L2_FIELD_BOTTOM:		maxh = maxh / 2;		break;	case V4L2_FIELD_INTERLACED:		break;	default:		return -EINVAL;	}	win->field = field;	if (win->w.width > maxw)		win->w.width = maxw;	if (win->w.height > maxh)		win->w.height = maxh;	return 0;}static int start_preview(struct saa7134_dev *dev, struct saa7134_fh *fh){	unsigned long base,control,bpl;	int err;	err = verify_preview(dev,&fh->win);	if (0 != err)		return err;	dev->ovfield = fh->win.field;	dprintk("start_preview %dx%d+%d+%d %s field=%s\n",		fh->win.w.width,fh->win.w.height,		fh->win.w.left,fh->win.w.top,		dev->ovfmt->name,v4l2_field_names[dev->ovfield]);	/* setup window + clipping */	set_size(dev,TASK_B,fh->win.w.width,fh->win.w.height,		 V4L2_FIELD_HAS_BOTH(dev->ovfield));	setup_clipping(dev,fh->clips,fh->nclips,		       V4L2_FIELD_HAS_BOTH(dev->ovfield));	if (dev->ovfmt->yuv)		saa_andorb(SAA7134_DATA_PATH(TASK_B), 0x3f, 0x03);	else		saa_andorb(SAA7134_DATA_PATH(TASK_B), 0x3f, 0x01);	saa_writeb(SAA7134_OFMT_VIDEO_B, dev->ovfmt->pm | 0x20);	/* dma: setup channel 1 (= Video Task B) */	base  = (unsigned long)dev->ovbuf.base;	base += dev->ovbuf.fmt.bytesperline * fh->win.w.top;	base += dev->ovfmt->depth/8         * fh->win.w.left;	bpl   = dev->ovbuf.fmt.bytesperline;	control = SAA7134_RS_CONTROL_BURST_16;	if (dev->ovfmt->bswap)		control |= SAA7134_RS_CONTROL_BSWAP;	if (dev->ovfmt->wswap)		control |= SAA7134_RS_CONTROL_WSWAP;	if (V4L2_FIELD_HAS_BOTH(dev->ovfield)) {		saa_writel(SAA7134_RS_BA1(1),base);		saa_writel(SAA7134_RS_BA2(1),base+bpl);		saa_writel(SAA7134_RS_PITCH(1),bpl*2);		saa_writel(SAA7134_RS_CONTROL(1),control);	} else {		saa_writel(SAA7134_RS_BA1(1),base);		saa_writel(SAA7134_RS_BA2(1),base);		saa_writel(SAA7134_RS_PITCH(1),bpl);		saa_writel(SAA7134_RS_CONTROL(1),control);	}	/* start dma */	dev->ovenable = 1;	saa7134_set_dmabits(dev);	return 0;}static int stop_preview(struct saa7134_dev *dev, struct saa7134_fh *fh){	dev->ovenable = 0;	saa7134_set_dmabits(dev);	return 0;}/* ------------------------------------------------------------------ */static int buffer_activate(struct saa7134_dev *dev,			   struct saa7134_buf *buf,			   struct saa7134_buf *next){	unsigned long base,control,bpl;	unsigned long bpl_uv,lines_uv,base2,base3,tmp; /* planar */	dprintk("buffer_activate buf=%p\n",buf);	buf->vb.state = VIDEOBUF_ACTIVE;	buf->top_seen = 0;	set_size(dev,TASK_A,buf->vb.width,buf->vb.height,		 V4L2_FIELD_HAS_BOTH(buf->vb.field));	if (buf->fmt->yuv)		saa_andorb(SAA7134_DATA_PATH(TASK_A), 0x3f, 0x03);	else		saa_andorb(SAA7134_DATA_PATH(TASK_A), 0x3f, 0x01);	saa_writeb(SAA7134_OFMT_VIDEO_A, buf->fmt->pm);	/* DMA: setup channel 0 (= Video Task A0) */	base  = saa7134_buffer_base(buf);	if (buf->fmt->planar)		bpl = buf->vb.width;	else		bpl = (buf->vb.width * buf->fmt->depth) / 8;	control = SAA7134_RS_CONTROL_BURST_16 |		SAA7134_RS_CONTROL_ME |		(buf->pt->dma >> 12);	if (buf->fmt->bswap)		control |= SAA7134_RS_CONTROL_BSWAP;	if (buf->fmt->wswap)		control |= SAA7134_RS_CONTROL_WSWAP;	if (V4L2_FIELD_HAS_BOTH(buf->vb.field)) {		/* interlaced */		saa_writel(SAA7134_RS_BA1(0),base);		saa_writel(SAA7134_RS_BA2(0),base+bpl);		saa_writel(SAA7134_RS_PITCH(0),bpl*2);	} else {		/* non-interlaced */		saa_writel(SAA7134_RS_BA1(0),base);		saa_writel(SAA7134_RS_BA2(0),base);		saa_writel(SAA7134_RS_PITCH(0),bpl);	}	saa_writel(SAA7134_RS_CONTROL(0),control);	if (buf->fmt->planar) {		/* DMA: setup channel 4+5 (= planar task A) */		bpl_uv   = bpl >> buf->fmt->hshift;		lines_uv = buf->vb.height >> buf->fmt->vshift;		base2    = base + bpl * buf->vb.height;		base3    = base2 + bpl_uv * lines_uv;		if (buf->fmt->uvswap)			tmp = base2, base2 = base3, base3 = tmp;		dprintk("uv: bpl=%ld lines=%ld base2/3=%ld/%ld\n",			bpl_uv,lines_uv,base2,base3);		if (V4L2_FIELD_HAS_BOTH(buf->vb.field)) {			/* interlaced */			saa_writel(SAA7134_RS_BA1(4),base2);			saa_writel(SAA7134_RS_BA2(4),base2+bpl_uv);			saa_writel(SAA7134_RS_PITCH(4),bpl_uv*2);			saa_writel(SAA7134_RS_BA1(5),base3);			saa_writel(SAA7134_RS_BA2(5),base3+bpl_uv);			saa_writel(SAA7134_RS_PITCH(5),bpl_uv*2);		} else {			/* non-interlaced */			saa_writel(SAA7134_RS_BA1(4),base2);			saa_writel(SAA7134_RS_BA2(4),base2);			saa_writel(SAA7134_RS_PITCH(4),bpl_uv);			saa_writel(SAA7134_RS_BA1(5),base3);			saa_writel(SAA7134_RS_BA2(5),base3);			saa_writel(SAA7134_RS_PITCH(5),bpl_uv);		}		saa_writel(SAA7134_RS_CONTROL(4),control);		saa_writel(SAA7134_RS_CONTROL(5),control);	}	/* start DMA */

⌨️ 快捷键说明

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