Browse Source

[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>
Ian Armstrong 14 years ago
parent
commit
c5874c9245

+ 5 - 5
drivers/media/video/ivtv/ivtv-driver.c

@@ -1328,6 +1328,8 @@ int ivtv_init_on_first_open(struct ivtv *itv)
 	if (!itv->has_cx23415)
 	if (!itv->has_cx23415)
 		write_reg_sync(0x03, IVTV_REG_DMACONTROL);
 		write_reg_sync(0x03, IVTV_REG_DMACONTROL);
 
 
+	ivtv_s_std_enc(itv, &itv->tuner_std);
+
 	/* Default interrupts enabled. For the PVR350 this includes the
 	/* Default interrupts enabled. For the PVR350 this includes the
 	   decoder VSYNC interrupt, which is always on. It is not only used
 	   decoder VSYNC interrupt, which is always on. It is not only used
 	   during decoding but also by the OSD.
 	   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) {
 	if (itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT) {
 		ivtv_clear_irq_mask(itv, IVTV_IRQ_MASK_INIT | IVTV_IRQ_DEC_VSYNC);
 		ivtv_clear_irq_mask(itv, IVTV_IRQ_MASK_INIT | IVTV_IRQ_DEC_VSYNC);
 		ivtv_set_osd_alpha(itv);
 		ivtv_set_osd_alpha(itv);
-	}
-	else
+		ivtv_s_std_dec(itv, &itv->tuner_std);
+	} else {
 		ivtv_clear_irq_mask(itv, IVTV_IRQ_MASK_INIT);
 		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 */
 	/* Setup initial controls */
 	cx2341x_handler_setup(&itv->cxhdl);
 	cx2341x_handler_setup(&itv->cxhdl);

+ 7 - 4
drivers/media/video/ivtv/ivtv-firmware.c

@@ -280,8 +280,6 @@ int ivtv_firmware_restart(struct ivtv *itv)
 {
 {
 	int rc = 0;
 	int rc = 0;
 	v4l2_std_id std;
 	v4l2_std_id std;
-	struct ivtv_open_id fh;
-	fh.itv = itv;
 
 
 	if (itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT)
 	if (itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT)
 		/* Display test image during restart */
 		/* Display test image during restart */
@@ -301,14 +299,19 @@ int ivtv_firmware_restart(struct ivtv *itv)
 	/* Allow settings to reload */
 	/* Allow settings to reload */
 	ivtv_mailbox_cache_invalidate(itv);
 	ivtv_mailbox_cache_invalidate(itv);
 
 
-	/* Restore video standard */
+	/* Restore encoder video standard */
 	std = itv->std;
 	std = itv->std;
 	itv->std = 0;
 	itv->std = 0;
-	ivtv_s_std(NULL, &fh, &std);
+	ivtv_s_std_enc(itv, &std);
 
 
 	if (itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT) {
 	if (itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT) {
 		ivtv_init_mpeg_decoder(itv);
 		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 */
 		/* Restore framebuffer if active */
 		if (itv->ivtvfb_restore)
 		if (itv->ivtvfb_restore)
 			itv->ivtvfb_restore(itv);
 			itv->ivtvfb_restore(itv);

+ 70 - 59
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;
 	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->std = *std;
 	itv->is_60hz = (*std & V4L2_STD_525_60) ? 1 : 0;
 	itv->is_60hz = (*std & V4L2_STD_525_60) ? 1 : 0;
 	itv->is_50hz = !itv->is_60hz;
 	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)
 	if (itv->hw_flags & IVTV_HW_CX25840)
 		itv->vbi.sliced_decoder_line_size = itv->is_60hz ? 272 : 284;
 		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 */
 	/* Tuner */
 	ivtv_call_all(itv, core, s_std, itv->std);
 	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);
-
-		/*
-		 * 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);
-
-		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 = 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;
-		}
+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;
+
+	/* 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);
+
+	/*
+	 * 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);
+
+	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;
 	return 0;
 }
 }
 
 

+ 2 - 1
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);
 void ivtv_set_osd_alpha(struct ivtv *itv);
 int ivtv_set_speed(struct ivtv *itv, int speed);
 int ivtv_set_speed(struct ivtv *itv, int speed);
 void ivtv_set_funcs(struct video_device *vdev);
 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_frequency(struct file *file, void *fh, struct v4l2_frequency *vf);
 int ivtv_s_input(struct file *file, void *fh, unsigned int inp);
 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);
 long ivtv_v4l2_ioctl(struct file *filp, unsigned int cmd, unsigned long arg);

+ 1 - 1
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
 	   Turning this signal on and off can confuse certain
 	   TVs. As far as I can tell there is no reason not to
 	   TVs. As far as I can tell there is no reason not to
 	   transmit this signal. */
 	   transmit this signal. */
-	if ((itv->std & V4L2_STD_625_50) && !enabled) {
+	if ((itv->std_out & V4L2_STD_625_50) && !enabled) {
 		enabled = 1;
 		enabled = 1;
 		mode = 0x08;  /* 4x3 full format */
 		mode = 0x08;  /* 4x3 full format */
 	}
 	}

+ 14 - 12
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)
 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. */
 	/* 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))
 	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 |
 			vblank.flags = FB_VBLANK_HAVE_COUNT |FB_VBLANK_HAVE_VCOUNT |
 					FB_VBLANK_HAVE_VSYNC;
 					FB_VBLANK_HAVE_VSYNC;
 			trace = read_reg(IVTV_REG_DEC_LINE_FIELD) >> 16;
 			trace = read_reg(IVTV_REG_DEC_LINE_FIELD) >> 16;
-			if (itv->is_50hz && trace > 312)
+			if (itv->is_out_50hz && trace > 312)
 				trace -= 312;
 				trace -= 312;
-			else if (itv->is_60hz && trace > 262)
+			else if (itv->is_out_60hz && trace > 262)
 				trace -= 262;
 				trace -= 262;
 			if (trace == 1)
 			if (trace == 1)
 				vblank.flags |= FB_VBLANK_VSYNCING;
 				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");
 	IVTVFB_DEBUG_INFO("ivtvfb_check_var\n");
 
 
 	/* Set base references for mode calcs. */
 	/* Set base references for mode calcs. */
-	if (itv->is_50hz) {
+	if (itv->is_out_50hz) {
 		pixclock = 84316;
 		pixclock = 84316;
 		hlimit = 776;
 		hlimit = 776;
 		vlimit = 591;
 		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
 	   If the margins are too large, just center the screen
 	   (enforcing margins causes too many problems) */
 	   (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);
 		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 */
 	/* Maintain overall 'size' for a constant refresh rate */
 	var->right_margin = hlimit - var->left_margin - var->xres;
 	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. */
 	/* Hardware coords start at 0, user coords start at 1. */
 	osd_left--;
 	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 =
 	oi->display_byte_stride =
 			start_window.width * oi->bytes_per_pixel;
 			start_window.width * oi->bytes_per_pixel;
 
 
 	/* Vertical size & position */
 	/* Vertical size & position */
 
 
-	max_height = itv->is_50hz ? 576 : 480;
+	max_height = itv->is_out_50hz ? 576 : 480;
 
 
 	if (osd_yres > max_height)
 	if (osd_yres > max_height)
 		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). */
 	/* Check vertical start (osd_upper). */
 	if (osd_upper + start_window.height > max_height + 1) {
 	if (osd_upper + start_window.height > max_height + 1) {