[media] ivtv: Internally separate encoder & decoder standard setting
Ian Armstrong [Mon, 30 May 2011 00:33:17 +0000 (21:33 -0300)]
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>

drivers/media/video/ivtv/ivtv-driver.c
drivers/media/video/ivtv/ivtv-firmware.c
drivers/media/video/ivtv/ivtv-ioctl.c
drivers/media/video/ivtv/ivtv-ioctl.h
drivers/media/video/ivtv/ivtv-vbi.c
drivers/media/video/ivtv/ivtvfb.c

index a4e4dfd..0fb7552 100644 (file)
@@ -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);
index 14a1cea..02c5ade 100644 (file)
@@ -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);
index 1689783..f9e347d 100644 (file)
@@ -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);
-
-               /*
-                * 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;
 }
 
index 58f0034..89185ca 100644 (file)
@@ -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);
index b6eb51c..293db80 100644 (file)
@@ -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 */
        }
index 5dec2e4..6b7c9c8 100644 (file)
@@ -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) {