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

📄 ivtv-yuv.c

📁 trident tm5600的linux驱动
💻 C
📖 第 1 页 / 共 3 页
字号:
	reg_2964_base = (src_minor_y * ((f->dst_h << 16) / f->src_h)) >> 14;	reg_2968_base = (src_minor_uv * ((f->dst_h << 16) / f->src_h)) >> 14;	if (f->dst_h / 2 >= f->src_h && !f->interlaced_y) {		master_height = (f->src_h * 0x00400000) / f->dst_h;		if ((f->src_h * 0x00400000) - (master_height * f->dst_h) >= f->dst_h / 2)			master_height++;		reg_2920 = master_height >> 2;		reg_2928 = master_height >> 3;		reg_2930 = master_height;		reg_2940 = master_height >> 1;		reg_2964_base >>= 3;		reg_2968_base >>= 3;		reg_296c = 0x00000000;	} else if (f->dst_h >= f->src_h) {		master_height = (f->src_h * 0x00400000) / f->dst_h;		master_height = (master_height >> 1) + (master_height & 1);		reg_2920 = master_height >> 2;		reg_2928 = master_height >> 2;		reg_2930 = master_height;		reg_2940 = master_height >> 1;		reg_296c = 0x00000000;		if (f->interlaced_y) {			reg_2964_base >>= 3;		} else {			reg_296c++;			reg_2964_base >>= 2;		}		if (f->interlaced_uv)			reg_2928 >>= 1;		reg_2968_base >>= 3;	} else if (f->dst_h >= f->src_h / 2) {		master_height = (f->src_h * 0x00200000) / f->dst_h;		master_height = (master_height >> 1) + (master_height & 1);		reg_2920 = master_height >> 2;		reg_2928 = master_height >> 2;		reg_2930 = master_height;		reg_2940 = master_height;		reg_296c = 0x00000101;		if (f->interlaced_y) {			reg_2964_base >>= 2;		} else {			reg_296c++;			reg_2964_base >>= 1;		}		if (f->interlaced_uv)			reg_2928 >>= 1;		reg_2968_base >>= 2;	} else {		master_height = (f->src_h * 0x00100000) / f->dst_h;		master_height = (master_height >> 1) + (master_height & 1);		reg_2920 = master_height >> 2;		reg_2928 = master_height >> 2;		reg_2930 = master_height;		reg_2940 = master_height;		reg_2964_base >>= 1;		reg_2968_base >>= 2;		reg_296c = 0x00000102;	}	/* FIXME These registers change depending on scaled / unscaled output	   We really need to work out what they should be */	if (f->src_h == f->dst_h) {		reg_2934 = 0x00020000;		reg_293c = 0x00100000;		reg_2944 = 0x00040000;		reg_294c = 0x000b0000;	} else {		reg_2934 = 0x00000FF0;		reg_293c = 0x00000FF0;		reg_2944 = 0x00000FF0;		reg_294c = 0x00000FF0;	}	/* The first line to be displayed */	reg_2950 = 0x00010000 + src_major_y;	if (f->interlaced_y)		reg_2950 += 0x00010000;	reg_2954 = reg_2950 + 1;	reg_2958 = 0x00010000 + (src_major_y >> 1);	if (f->interlaced_uv)		reg_2958 += 0x00010000;	reg_295c = reg_2958 + 1;	if (yi->decode_height == 480)		reg_289c = 0x011e0017;	else		reg_289c = 0x01500017;	if (f->dst_y < 0)		reg_289c = (reg_289c - ((f->dst_y & ~1)<<15))-(f->dst_y >>1);	else		reg_289c = (reg_289c + ((f->dst_y & ~1)<<15))+(f->dst_y >>1);	/* How much of the source to decode.	   Take into account the source offset */	reg_2960 = ((src_minor_y + f->src_h + src_major_y) - 1) |		(((src_minor_uv + f->src_h + src_major_uv - 1) & ~1) << 15);	/* Calculate correct value for register 2964 */	if (f->src_h == f->dst_h) {		reg_2964 = 1;	} else {		reg_2964 = 2 + ((f->dst_h << 1) / f->src_h);		reg_2964 = (reg_2964 >> 1) + (reg_2964 & 1);	}	reg_2968 = (reg_2964 << 16) + reg_2964 + (reg_2964 >> 1);	reg_2964 = (reg_2964 << 16) + reg_2964 + (reg_2964 * 46 / 94);	/* Okay, we've wasted time working out the correct value,	   but if we use it, it fouls the the window alignment.	   Fudge it to what we want... */	reg_2964 = 0x00010001 + ((reg_2964 & 0x0000FFFF) - (reg_2964 >> 16));	reg_2968 = 0x00010001 + ((reg_2968 & 0x0000FFFF) - (reg_2968 >> 16));	/* Deviate further from what it should be. I find the flicker headache	   inducing so try to reduce it slightly. Leave 2968 as-is otherwise	   colours foul. */	if ((reg_2964 != 0x00010001) && (f->dst_h / 2 <= f->src_h))		reg_2964 = (reg_2964 & 0xFFFF0000) + ((reg_2964 & 0x0000FFFF) / 2);	if (!f->interlaced_y)		reg_2964 -= 0x00010001;	if (!f->interlaced_uv)		reg_2968 -= 0x00010001;	reg_2964 += ((reg_2964_base << 16) | reg_2964_base);	reg_2968 += ((reg_2968_base << 16) | reg_2968_base);	/* Select the vertical filter */	if (f->src_h == f->dst_h) {		/* An exact size match uses filter 0/1 */		v_filter_1 = 0;		v_filter_2 = 1;	} else {		/* Figure out which filter to use */		v_filter_1 = ((f->src_h << 16) / f->dst_h) >> 15;		v_filter_1 = (v_filter_1 >> 1) + (v_filter_1 & 1);		/* Only an exact size match can use filter 0 */		v_filter_1 += !v_filter_1;		v_filter_2 = v_filter_1;	}	write_reg(reg_2934, 0x02934);	write_reg(reg_293c, 0x0293c);	IVTV_DEBUG_YUV("Update reg 0x2934 %08x->%08x 0x293c %08x->%08x\n",		       yi->reg_2934, reg_2934, yi->reg_293c, reg_293c);	write_reg(reg_2944, 0x02944);	write_reg(reg_294c, 0x0294c);	IVTV_DEBUG_YUV("Update reg 0x2944 %08x->%08x 0x294c %08x->%08x\n",		       yi->reg_2944, reg_2944, yi->reg_294c, reg_294c);	/* Ensure 2970 is 0 (does it ever change ?) *//*	write_reg(0,0x02970); *//*	IVTV_DEBUG_YUV("Update reg 0x2970 %08x->%08x\n", yi->reg_2970, 0); */	write_reg(reg_2930, 0x02938);	write_reg(reg_2930, 0x02930);	IVTV_DEBUG_YUV("Update reg 0x2930 %08x->%08x 0x2938 %08x->%08x\n",		       yi->reg_2930, reg_2930, yi->reg_2938, reg_2930);	write_reg(reg_2928, 0x02928);	write_reg(reg_2928 + 0x514, 0x0292C);	IVTV_DEBUG_YUV("Update reg 0x2928 %08x->%08x 0x292c %08x->%08x\n",		       yi->reg_2928, reg_2928, yi->reg_292c, reg_2928 + 0x514);	write_reg(reg_2920, 0x02920);	write_reg(reg_2920 + 0x514, 0x02924);	IVTV_DEBUG_YUV("Update reg 0x2920 %08x->%08x 0x2924 %08x->%08x\n",		       yi->reg_2920, reg_2920, yi->reg_2924, reg_2920 + 0x514);	write_reg(reg_2918, 0x02918);	write_reg(reg_291c, 0x0291C);	IVTV_DEBUG_YUV("Update reg 0x2918 %08x->%08x 0x291C %08x->%08x\n",		       yi->reg_2918, reg_2918, yi->reg_291c, reg_291c);	write_reg(reg_296c, 0x0296c);	IVTV_DEBUG_YUV("Update reg 0x296c %08x->%08x\n",		       yi->reg_296c, reg_296c);	write_reg(reg_2940, 0x02948);	write_reg(reg_2940, 0x02940);	IVTV_DEBUG_YUV("Update reg 0x2940 %08x->%08x 0x2948 %08x->%08x\n",		       yi->reg_2940, reg_2940, yi->reg_2948, reg_2940);	write_reg(reg_2950, 0x02950);	write_reg(reg_2954, 0x02954);	IVTV_DEBUG_YUV("Update reg 0x2950 %08x->%08x 0x2954 %08x->%08x\n",		       yi->reg_2950, reg_2950, yi->reg_2954, reg_2954);	write_reg(reg_2958, 0x02958);	write_reg(reg_295c, 0x0295C);	IVTV_DEBUG_YUV("Update reg 0x2958 %08x->%08x 0x295C %08x->%08x\n",		       yi->reg_2958, reg_2958, yi->reg_295c, reg_295c);	write_reg(reg_2960, 0x02960);	IVTV_DEBUG_YUV("Update reg 0x2960 %08x->%08x \n",		       yi->reg_2960, reg_2960);	write_reg(reg_2964, 0x02964);	write_reg(reg_2968, 0x02968);	IVTV_DEBUG_YUV("Update reg 0x2964 %08x->%08x 0x2968 %08x->%08x\n",		       yi->reg_2964, reg_2964, yi->reg_2968, reg_2968);	write_reg(reg_289c, 0x0289c);	IVTV_DEBUG_YUV("Update reg 0x289c %08x->%08x\n",		       yi->reg_289c, reg_289c);	/* Only update filter 1 if we really need to */	if (v_filter_1 != yi->v_filter_1) {		ivtv_yuv_filter(itv, -1, v_filter_1, -1);		yi->v_filter_1 = v_filter_1;	}	/* Only update filter 2 if we really need to */	if (v_filter_2 != yi->v_filter_2) {		ivtv_yuv_filter(itv, -1, -1, v_filter_2);		yi->v_filter_2 = v_filter_2;	}}/* Modify the supplied coordinate information to fit the visible osd area */static u32 ivtv_yuv_window_setup(struct ivtv *itv, struct yuv_frame_info *f){	struct yuv_frame_info *of = &itv->yuv_info.old_frame_info;	int osd_crop;	u32 osd_scale;	u32 yuv_update = 0;	/* Sorry, but no negative coords for src */	if (f->src_x < 0)		f->src_x = 0;	if (f->src_y < 0)		f->src_y = 0;	/* Can only reduce width down to 1/4 original size */	if ((osd_crop = f->src_w - 4 * f->dst_w) > 0) {		f->src_x += osd_crop / 2;		f->src_w = (f->src_w - osd_crop) & ~3;		f->dst_w = f->src_w / 4;		f->dst_w += f->dst_w & 1;	}	/* Can only reduce height down to 1/4 original size */	if (f->src_h / f->dst_h >= 2) {		/* Overflow may be because we're running progressive,		   so force mode switch */		f->interlaced_y = 1;		/* Make sure we're still within limits for interlace */		if ((osd_crop = f->src_h - 4 * f->dst_h) > 0) {			/* If we reach here we'll have to force the height. */			f->src_y += osd_crop / 2;			f->src_h = (f->src_h - osd_crop) & ~3;			f->dst_h = f->src_h / 4;			f->dst_h += f->dst_h & 1;		}	}	/* If there's nothing to safe to display, we may as well stop now */	if ((int)f->dst_w <= 2 || (int)f->dst_h <= 2 ||	    (int)f->src_w <= 2 || (int)f->src_h <= 2) {		return IVTV_YUV_UPDATE_INVALID;	}	/* Ensure video remains inside OSD area */	osd_scale = (f->src_h << 16) / f->dst_h;	if ((osd_crop = f->pan_y - f->dst_y) > 0) {		/* Falls off the upper edge - crop */		f->src_y += (osd_scale * osd_crop) >> 16;		f->src_h -= (osd_scale * osd_crop) >> 16;		f->dst_h -= osd_crop;		f->dst_y = 0;	} else {		f->dst_y -= f->pan_y;	}	if ((osd_crop = f->dst_h + f->dst_y - f->vis_h) > 0) {		/* Falls off the lower edge - crop */		f->dst_h -= osd_crop;		f->src_h -= (osd_scale * osd_crop) >> 16;	}	osd_scale = (f->src_w << 16) / f->dst_w;	if ((osd_crop = f->pan_x - f->dst_x) > 0) {		/* Fall off the left edge - crop */		f->src_x += (osd_scale * osd_crop) >> 16;		f->src_w -= (osd_scale * osd_crop) >> 16;		f->dst_w -= osd_crop;		f->dst_x = 0;	} else {		f->dst_x -= f->pan_x;	}	if ((osd_crop = f->dst_w + f->dst_x - f->vis_w) > 0) {		/* Falls off the right edge - crop */		f->dst_w -= osd_crop;		f->src_w -= (osd_scale * osd_crop) >> 16;	}	if (itv->yuv_info.track_osd) {		/* The OSD can be moved. Track to it */		f->dst_x += itv->yuv_info.osd_x_offset;		f->dst_y += itv->yuv_info.osd_y_offset;	}	/* Width & height for both src & dst must be even.	   Same for coordinates. */	f->dst_w &= ~1;	f->dst_x &= ~1;	f->src_w += f->src_x & 1;	f->src_x &= ~1;	f->src_w &= ~1;	f->dst_w &= ~1;	f->dst_h &= ~1;	f->dst_y &= ~1;	f->src_h += f->src_y & 1;	f->src_y &= ~1;	f->src_h &= ~1;	f->dst_h &= ~1;	/* Due to rounding, we may have reduced the output size to <1/4 of	   the source. Check again, but this time just resize. Don't change	   source coordinates */	if (f->dst_w < f->src_w / 4) {		f->src_w &= ~3;		f->dst_w = f->src_w / 4;		f->dst_w += f->dst_w & 1;	}	if (f->dst_h < f->src_h / 4) {		f->src_h &= ~3;		f->dst_h = f->src_h / 4;		f->dst_h += f->dst_h & 1;	}	/* Check again. If there's nothing to safe to display, stop now */	if ((int)f->dst_w <= 2 || (int)f->dst_h <= 2 ||	    (int)f->src_w <= 2 || (int)f->src_h <= 2) {		return IVTV_YUV_UPDATE_INVALID;	}	/* Both x offset & width are linked, so they have to be done together */	if ((of->dst_w != f->dst_w) || (of->src_w != f->src_w) ||	    (of->dst_x != f->dst_x) || (of->src_x != f->src_x) ||	    (of->pan_x != f->pan_x) || (of->vis_w != f->vis_w)) {		yuv_update |= IVTV_YUV_UPDATE_HORIZONTAL;	}	if ((of->src_h != f->src_h) || (of->dst_h != f->dst_h) ||	    (of->dst_y != f->dst_y) || (of->src_y != f->src_y) ||	    (of->pan_y != f->pan_y) || (of->vis_h != f->vis_h) ||	    (of->lace_mode != f->lace_mode) ||	    (of->interlaced_y != f->interlaced_y) ||	    (of->interlaced_uv != f->interlaced_uv)) {		yuv_update |= IVTV_YUV_UPDATE_VERTICAL;	}	return yuv_update;}/* Update the scaling register to the requested value */void ivtv_yuv_work_handler(struct ivtv *itv){	struct yuv_playback_info *yi = &itv->yuv_info;	struct yuv_frame_info f;	int frame = yi->update_frame;	u32 yuv_update;	IVTV_DEBUG_YUV("Update yuv registers for frame %d\n", frame);	f = yi->new_frame_info[frame];	if (yi->track_osd) {		/* Snapshot the osd pan info */		f.pan_x = yi->osd_x_pan;		f.pan_y = yi->osd_y_pan;		f.vis_w = yi->osd_vis_w;		f.vis_h = yi->osd_vis_h;	} else {		/* Not tracking the osd, so assume full screen */		f.pan_x = 0;		f.pan_y = 0;		f.vis_w = 720;		f.vis_h = yi->decode_height;	}	/* Calculate the display window coordinates. Exit if nothing left */	if (!(yuv_update = ivtv_yuv_window_setup(itv, &f)))		return;	if (yuv_update & IVTV_YUV_UPDATE_INVALID) {		write_reg(0x01008080, 0x2898);	} else if (yuv_update) {		write_reg(0x00108080, 0x2898);		if (yuv_update & IVTV_YUV_UPDATE_HORIZONTAL)			ivtv_yuv_handle_horizontal(itv, &f);		if (yuv_update & IVTV_YUV_UPDATE_VERTICAL)			ivtv_yuv_handle_vertical(itv, &f);	}	yi->old_frame_info = f;}static void ivtv_yuv_init(struct ivtv *itv){	struct yuv_playback_info *yi = &itv->yuv_info;	IVTV_DEBUG_YUV("ivtv_yuv_init\n");	/* Take a snapshot of the current register settings */	yi->reg_2834 = read_reg(0x02834);

⌨️ 快捷键说明

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