diff options
| author | Ian Armstrong <ian@iarmst.demon.co.uk> | 2011-05-29 21:33:17 -0300 | 
|---|---|---|
| committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2011-06-01 08:46:38 -0300 | 
| commit | c5874c9245d298c65f81c2f91f89e1da8ea66409 (patch) | |
| tree | 4f4ee4a1a9967b0fb0f0e30e976ad3e2668074aa | |
| parent | 6600cc301d0762e3db8bd2b44d2d5fef36a4fd68 (diff) | |
| download | olio-linux-3.10-c5874c9245d298c65f81c2f91f89e1da8ea66409.tar.xz olio-linux-3.10-c5874c9245d298c65f81c2f91f89e1da8ea66409.zip  | |
[media] ivtv: Internally separate encoder & decoder standard setting
Internally separates the setting of the broadcast standard for the encoder &
decoder. Externally there's no change in functionality.
[awalls@md.metrocast.net: Edited to fix a checkpatch gripe about multiple
assignment and to remove a now unused DEFINE_WAIT() due to this patch]
Signed-off-by: Ian Armstrong <ian@iarmst.demon.co.uk>
Signed-off-by: Andy Walls <awalls@md.metrocast.net>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
| -rw-r--r-- | drivers/media/video/ivtv/ivtv-driver.c | 10 | ||||
| -rw-r--r-- | drivers/media/video/ivtv/ivtv-firmware.c | 11 | ||||
| -rw-r--r-- | drivers/media/video/ivtv/ivtv-ioctl.c | 123 | ||||
| -rw-r--r-- | drivers/media/video/ivtv/ivtv-ioctl.h | 3 | ||||
| -rw-r--r-- | drivers/media/video/ivtv/ivtv-vbi.c | 2 | ||||
| -rw-r--r-- | drivers/media/video/ivtv/ivtvfb.c | 26 | 
6 files changed, 96 insertions, 79 deletions
diff --git a/drivers/media/video/ivtv/ivtv-driver.c b/drivers/media/video/ivtv/ivtv-driver.c index a4e4dfdbc2f..0fb75524484 100644 --- a/drivers/media/video/ivtv/ivtv-driver.c +++ b/drivers/media/video/ivtv/ivtv-driver.c @@ -1328,6 +1328,8 @@ int ivtv_init_on_first_open(struct ivtv *itv)  	if (!itv->has_cx23415)  		write_reg_sync(0x03, IVTV_REG_DMACONTROL); +	ivtv_s_std_enc(itv, &itv->tuner_std); +  	/* Default interrupts enabled. For the PVR350 this includes the  	   decoder VSYNC interrupt, which is always on. It is not only used  	   during decoding but also by the OSD. @@ -1336,12 +1338,10 @@ int ivtv_init_on_first_open(struct ivtv *itv)  	if (itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT) {  		ivtv_clear_irq_mask(itv, IVTV_IRQ_MASK_INIT | IVTV_IRQ_DEC_VSYNC);  		ivtv_set_osd_alpha(itv); -	} -	else +		ivtv_s_std_dec(itv, &itv->tuner_std); +	} else {  		ivtv_clear_irq_mask(itv, IVTV_IRQ_MASK_INIT); - -	/* For cards with video out, this call needs interrupts enabled */ -	ivtv_s_std(NULL, &fh, &itv->tuner_std); +	}  	/* Setup initial controls */  	cx2341x_handler_setup(&itv->cxhdl); diff --git a/drivers/media/video/ivtv/ivtv-firmware.c b/drivers/media/video/ivtv/ivtv-firmware.c index 14a1cea1d70..02c5adebf51 100644 --- a/drivers/media/video/ivtv/ivtv-firmware.c +++ b/drivers/media/video/ivtv/ivtv-firmware.c @@ -280,8 +280,6 @@ int ivtv_firmware_restart(struct ivtv *itv)  {  	int rc = 0;  	v4l2_std_id std; -	struct ivtv_open_id fh; -	fh.itv = itv;  	if (itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT)  		/* Display test image during restart */ @@ -301,14 +299,19 @@ int ivtv_firmware_restart(struct ivtv *itv)  	/* Allow settings to reload */  	ivtv_mailbox_cache_invalidate(itv); -	/* Restore video standard */ +	/* Restore encoder video standard */  	std = itv->std;  	itv->std = 0; -	ivtv_s_std(NULL, &fh, &std); +	ivtv_s_std_enc(itv, &std);  	if (itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT) {  		ivtv_init_mpeg_decoder(itv); +		/* Restore decoder video standard */ +		std = itv->std_out; +		itv->std_out = 0; +		ivtv_s_std_dec(itv, &std); +  		/* Restore framebuffer if active */  		if (itv->ivtvfb_restore)  			itv->ivtvfb_restore(itv); diff --git a/drivers/media/video/ivtv/ivtv-ioctl.c b/drivers/media/video/ivtv/ivtv-ioctl.c index 1689783cd19..f9e347dae73 100644 --- a/drivers/media/video/ivtv/ivtv-ioctl.c +++ b/drivers/media/video/ivtv/ivtv-ioctl.c @@ -1071,28 +1071,8 @@ static int ivtv_g_std(struct file *file, void *fh, v4l2_std_id *std)  	return 0;  } -int ivtv_s_std(struct file *file, void *fh, v4l2_std_id *std) +void ivtv_s_std_enc(struct ivtv *itv, v4l2_std_id *std)  { -	DEFINE_WAIT(wait); -	struct ivtv *itv = fh2id(fh)->itv; -	struct yuv_playback_info *yi = &itv->yuv_info; -	int f; - -	if ((*std & V4L2_STD_ALL) == 0) -		return -EINVAL; - -	if (*std == itv->std) -		return 0; - -	if (test_bit(IVTV_F_I_RADIO_USER, &itv->i_flags) || -	    atomic_read(&itv->capturing) > 0 || -	    atomic_read(&itv->decoding) > 0) { -		/* Switching standard would turn off the radio or mess -		   with already running streams, prevent that by -		   returning EBUSY. */ -		return -EBUSY; -	} -  	itv->std = *std;  	itv->is_60hz = (*std & V4L2_STD_525_60) ? 1 : 0;  	itv->is_50hz = !itv->is_60hz; @@ -1106,48 +1086,79 @@ int ivtv_s_std(struct file *file, void *fh, v4l2_std_id *std)  	if (itv->hw_flags & IVTV_HW_CX25840)  		itv->vbi.sliced_decoder_line_size = itv->is_60hz ? 272 : 284; -	IVTV_DEBUG_INFO("Switching standard to %llx.\n", (unsigned long long)itv->std); -  	/* Tuner */  	ivtv_call_all(itv, core, s_std, itv->std); +} -	if (itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT) { -		/* set display standard */ -		itv->std_out = *std; -		itv->is_out_60hz = itv->is_60hz; -		itv->is_out_50hz = itv->is_50hz; -		ivtv_call_all(itv, video, s_std_output, itv->std_out); +void ivtv_s_std_dec(struct ivtv *itv, v4l2_std_id *std) +{ +	struct yuv_playback_info *yi = &itv->yuv_info; +	DEFINE_WAIT(wait); +	int f; -		/* -		 * The next firmware call is time sensitive. Time it to -		 * avoid risk of a hard lock, by trying to ensure the call -		 * happens within the first 100 lines of the top field. -		 * Make 4 attempts to sync to the decoder before giving up. -		 */ -		for (f = 0; f < 4; f++) { -			prepare_to_wait(&itv->vsync_waitq, &wait, -					TASK_UNINTERRUPTIBLE); -			if ((read_reg(IVTV_REG_DEC_LINE_FIELD) >> 16) < 100) -				break; -			schedule_timeout(msecs_to_jiffies(25)); -		} -		finish_wait(&itv->vsync_waitq, &wait); +	/* set display standard */ +	itv->std_out = *std; +	itv->is_out_60hz = (*std & V4L2_STD_525_60) ? 1 : 0; +	itv->is_out_50hz = !itv->is_out_60hz; +	ivtv_call_all(itv, video, s_std_output, itv->std_out); -		if (f == 4) -			IVTV_WARN("Mode change failed to sync to decoder\n"); +	/* +	 * The next firmware call is time sensitive. Time it to +	 * avoid risk of a hard lock, by trying to ensure the call +	 * happens within the first 100 lines of the top field. +	 * Make 4 attempts to sync to the decoder before giving up. +	 */ +	for (f = 0; f < 4; f++) { +		prepare_to_wait(&itv->vsync_waitq, &wait, +				TASK_UNINTERRUPTIBLE); +		if ((read_reg(IVTV_REG_DEC_LINE_FIELD) >> 16) < 100) +			break; +		schedule_timeout(msecs_to_jiffies(25)); +	} +	finish_wait(&itv->vsync_waitq, &wait); -		ivtv_vapi(itv, CX2341X_DEC_SET_STANDARD, 1, itv->is_out_50hz); -		itv->main_rect.left = itv->main_rect.top = 0; -		itv->main_rect.width = 720; -		itv->main_rect.height = itv->cxhdl.height; -		ivtv_vapi(itv, CX2341X_OSD_SET_FRAMEBUFFER_WINDOW, 4, -			720, itv->main_rect.height, 0, 0); -		yi->main_rect = itv->main_rect; -		if (!itv->osd_info) { -			yi->osd_full_w = 720; -			yi->osd_full_h = itv->is_out_50hz ? 576 : 480; -		} +	if (f == 4) +		IVTV_WARN("Mode change failed to sync to decoder\n"); + +	ivtv_vapi(itv, CX2341X_DEC_SET_STANDARD, 1, itv->is_out_50hz); +	itv->main_rect.left = 0; +	itv->main_rect.top = 0; +	itv->main_rect.width = 720; +	itv->main_rect.height = itv->is_out_50hz ? 576 : 480; +	ivtv_vapi(itv, CX2341X_OSD_SET_FRAMEBUFFER_WINDOW, 4, +		720, itv->main_rect.height, 0, 0); +	yi->main_rect = itv->main_rect; +	if (!itv->osd_info) { +		yi->osd_full_w = 720; +		yi->osd_full_h = itv->is_out_50hz ? 576 : 480;  	} +} + +int ivtv_s_std(struct file *file, void *fh, v4l2_std_id *std) +{ +	struct ivtv *itv = fh2id(fh)->itv; + +	if ((*std & V4L2_STD_ALL) == 0) +		return -EINVAL; + +	if (*std == itv->std) +		return 0; + +	if (test_bit(IVTV_F_I_RADIO_USER, &itv->i_flags) || +	    atomic_read(&itv->capturing) > 0 || +	    atomic_read(&itv->decoding) > 0) { +		/* Switching standard would mess with already running +		   streams, prevent that by returning EBUSY. */ +		return -EBUSY; +	} + +	IVTV_DEBUG_INFO("Switching standard to %llx.\n", +		(unsigned long long)itv->std); + +	ivtv_s_std_enc(itv, std); +	if (itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT) +		ivtv_s_std_dec(itv, std); +  	return 0;  } diff --git a/drivers/media/video/ivtv/ivtv-ioctl.h b/drivers/media/video/ivtv/ivtv-ioctl.h index 58f003412af..89185caeafa 100644 --- a/drivers/media/video/ivtv/ivtv-ioctl.h +++ b/drivers/media/video/ivtv/ivtv-ioctl.h @@ -27,7 +27,8 @@ u16 ivtv_get_service_set(struct v4l2_sliced_vbi_format *fmt);  void ivtv_set_osd_alpha(struct ivtv *itv);  int ivtv_set_speed(struct ivtv *itv, int speed);  void ivtv_set_funcs(struct video_device *vdev); -int ivtv_s_std(struct file *file, void *fh, v4l2_std_id *std); +void ivtv_s_std_enc(struct ivtv *itv, v4l2_std_id *std); +void ivtv_s_std_dec(struct ivtv *itv, v4l2_std_id *std);  int ivtv_s_frequency(struct file *file, void *fh, struct v4l2_frequency *vf);  int ivtv_s_input(struct file *file, void *fh, unsigned int inp);  long ivtv_v4l2_ioctl(struct file *filp, unsigned int cmd, unsigned long arg); diff --git a/drivers/media/video/ivtv/ivtv-vbi.c b/drivers/media/video/ivtv/ivtv-vbi.c index b6eb51ce773..293db806d93 100644 --- a/drivers/media/video/ivtv/ivtv-vbi.c +++ b/drivers/media/video/ivtv/ivtv-vbi.c @@ -71,7 +71,7 @@ static void ivtv_set_wss(struct ivtv *itv, int enabled, int mode)  	   Turning this signal on and off can confuse certain  	   TVs. As far as I can tell there is no reason not to  	   transmit this signal. */ -	if ((itv->std & V4L2_STD_625_50) && !enabled) { +	if ((itv->std_out & V4L2_STD_625_50) && !enabled) {  		enabled = 1;  		mode = 0x08;  /* 4x3 full format */  	} diff --git a/drivers/media/video/ivtv/ivtvfb.c b/drivers/media/video/ivtv/ivtvfb.c index 5dec2e4012b..6b7c9c82333 100644 --- a/drivers/media/video/ivtv/ivtvfb.c +++ b/drivers/media/video/ivtv/ivtvfb.c @@ -247,7 +247,7 @@ static int ivtvfb_set_osd_coords(struct ivtv *itv, const struct ivtv_osd_coords  static int ivtvfb_set_display_window(struct ivtv *itv, struct v4l2_rect *ivtv_window)  { -	int osd_height_limit = itv->is_50hz ? 576 : 480; +	int osd_height_limit = itv->is_out_50hz ? 576 : 480;  	/* Only fail if resolution too high, otherwise fudge the start coords. */  	if ((ivtv_window->height > osd_height_limit) || (ivtv_window->width > IVTV_OSD_MAX_WIDTH)) @@ -471,9 +471,9 @@ static int ivtvfb_ioctl(struct fb_info *info, unsigned int cmd, unsigned long ar  			vblank.flags = FB_VBLANK_HAVE_COUNT |FB_VBLANK_HAVE_VCOUNT |  					FB_VBLANK_HAVE_VSYNC;  			trace = read_reg(IVTV_REG_DEC_LINE_FIELD) >> 16; -			if (itv->is_50hz && trace > 312) +			if (itv->is_out_50hz && trace > 312)  				trace -= 312; -			else if (itv->is_60hz && trace > 262) +			else if (itv->is_out_60hz && trace > 262)  				trace -= 262;  			if (trace == 1)  				vblank.flags |= FB_VBLANK_VSYNCING; @@ -656,7 +656,7 @@ static int _ivtvfb_check_var(struct fb_var_screeninfo *var, struct ivtv *itv)  	IVTVFB_DEBUG_INFO("ivtvfb_check_var\n");  	/* Set base references for mode calcs. */ -	if (itv->is_50hz) { +	if (itv->is_out_50hz) {  		pixclock = 84316;  		hlimit = 776;  		vlimit = 591; @@ -784,12 +784,12 @@ static int _ivtvfb_check_var(struct fb_var_screeninfo *var, struct ivtv *itv)  	   If the margins are too large, just center the screen  	   (enforcing margins causes too many problems) */ -	if (var->left_margin + var->xres > IVTV_OSD_MAX_WIDTH + 1) { +	if (var->left_margin + var->xres > IVTV_OSD_MAX_WIDTH + 1)  		var->left_margin = 1 + ((IVTV_OSD_MAX_WIDTH - var->xres) / 2); -	} -	if (var->upper_margin + var->yres > (itv->is_50hz ? 577 : 481)) { -		var->upper_margin = 1 + (((itv->is_50hz ? 576 : 480) - var->yres) / 2); -	} + +	if (var->upper_margin + var->yres > (itv->is_out_50hz ? 577 : 481)) +		var->upper_margin = 1 + (((itv->is_out_50hz ? 576 : 480) - +			var->yres) / 2);  	/* Maintain overall 'size' for a constant refresh rate */  	var->right_margin = hlimit - var->left_margin - var->xres; @@ -1008,19 +1008,21 @@ static int ivtvfb_init_vidmode(struct ivtv *itv)  	/* Hardware coords start at 0, user coords start at 1. */  	osd_left--; -	start_window.left = osd_left >= 0 ? osd_left : ((IVTV_OSD_MAX_WIDTH - start_window.width) / 2); +	start_window.left = osd_left >= 0 ? +		 osd_left : ((IVTV_OSD_MAX_WIDTH - start_window.width) / 2);  	oi->display_byte_stride =  			start_window.width * oi->bytes_per_pixel;  	/* Vertical size & position */ -	max_height = itv->is_50hz ? 576 : 480; +	max_height = itv->is_out_50hz ? 576 : 480;  	if (osd_yres > max_height)  		osd_yres = max_height; -	start_window.height = osd_yres ? osd_yres : itv->is_50hz ? 480 : 400; +	start_window.height = osd_yres ? +		osd_yres : itv->is_out_50hz ? 480 : 400;  	/* Check vertical start (osd_upper). */  	if (osd_upper + start_window.height > max_height + 1) {  |