aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/video/ivtv
diff options
context:
space:
mode:
authorIan Armstrong <ian@iarmst.demon.co.uk>2011-05-29 20:33:17 -0400
committerMauro Carvalho Chehab <mchehab@redhat.com>2011-06-01 07:46:38 -0400
commitc5874c9245d298c65f81c2f91f89e1da8ea66409 (patch)
tree4f4ee4a1a9967b0fb0f0e30e976ad3e2668074aa /drivers/media/video/ivtv
parent6600cc301d0762e3db8bd2b44d2d5fef36a4fd68 (diff)
[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>
Diffstat (limited to 'drivers/media/video/ivtv')
-rw-r--r--drivers/media/video/ivtv/ivtv-driver.c10
-rw-r--r--drivers/media/video/ivtv/ivtv-firmware.c11
-rw-r--r--drivers/media/video/ivtv/ivtv-ioctl.c129
-rw-r--r--drivers/media/video/ivtv/ivtv-ioctl.h3
-rw-r--r--drivers/media/video/ivtv/ivtv-vbi.c2
-rw-r--r--drivers/media/video/ivtv/ivtvfb.c26
6 files changed, 99 insertions, 82 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)
1328 if (!itv->has_cx23415) 1328 if (!itv->has_cx23415)
1329 write_reg_sync(0x03, IVTV_REG_DMACONTROL); 1329 write_reg_sync(0x03, IVTV_REG_DMACONTROL);
1330 1330
1331 ivtv_s_std_enc(itv, &itv->tuner_std);
1332
1331 /* Default interrupts enabled. For the PVR350 this includes the 1333 /* Default interrupts enabled. For the PVR350 this includes the
1332 decoder VSYNC interrupt, which is always on. It is not only used 1334 decoder VSYNC interrupt, which is always on. It is not only used
1333 during decoding but also by the OSD. 1335 during decoding but also by the OSD.
@@ -1336,12 +1338,10 @@ int ivtv_init_on_first_open(struct ivtv *itv)
1336 if (itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT) { 1338 if (itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT) {
1337 ivtv_clear_irq_mask(itv, IVTV_IRQ_MASK_INIT | IVTV_IRQ_DEC_VSYNC); 1339 ivtv_clear_irq_mask(itv, IVTV_IRQ_MASK_INIT | IVTV_IRQ_DEC_VSYNC);
1338 ivtv_set_osd_alpha(itv); 1340 ivtv_set_osd_alpha(itv);
1339 } 1341 ivtv_s_std_dec(itv, &itv->tuner_std);
1340 else 1342 } else {
1341 ivtv_clear_irq_mask(itv, IVTV_IRQ_MASK_INIT); 1343 ivtv_clear_irq_mask(itv, IVTV_IRQ_MASK_INIT);
1342 1344 }
1343 /* For cards with video out, this call needs interrupts enabled */
1344 ivtv_s_std(NULL, &fh, &itv->tuner_std);
1345 1345
1346 /* Setup initial controls */ 1346 /* Setup initial controls */
1347 cx2341x_handler_setup(&itv->cxhdl); 1347 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)
280{ 280{
281 int rc = 0; 281 int rc = 0;
282 v4l2_std_id std; 282 v4l2_std_id std;
283 struct ivtv_open_id fh;
284 fh.itv = itv;
285 283
286 if (itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT) 284 if (itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT)
287 /* Display test image during restart */ 285 /* Display test image during restart */
@@ -301,14 +299,19 @@ int ivtv_firmware_restart(struct ivtv *itv)
301 /* Allow settings to reload */ 299 /* Allow settings to reload */
302 ivtv_mailbox_cache_invalidate(itv); 300 ivtv_mailbox_cache_invalidate(itv);
303 301
304 /* Restore video standard */ 302 /* Restore encoder video standard */
305 std = itv->std; 303 std = itv->std;
306 itv->std = 0; 304 itv->std = 0;
307 ivtv_s_std(NULL, &fh, &std); 305 ivtv_s_std_enc(itv, &std);
308 306
309 if (itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT) { 307 if (itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT) {
310 ivtv_init_mpeg_decoder(itv); 308 ivtv_init_mpeg_decoder(itv);
311 309
310 /* Restore decoder video standard */
311 std = itv->std_out;
312 itv->std_out = 0;
313 ivtv_s_std_dec(itv, &std);
314
312 /* Restore framebuffer if active */ 315 /* Restore framebuffer if active */
313 if (itv->ivtvfb_restore) 316 if (itv->ivtvfb_restore)
314 itv->ivtvfb_restore(itv); 317 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)
1071 return 0; 1071 return 0;
1072} 1072}
1073 1073
1074int ivtv_s_std(struct file *file, void *fh, v4l2_std_id *std) 1074void ivtv_s_std_enc(struct ivtv *itv, v4l2_std_id *std)
1075{ 1075{
1076 DEFINE_WAIT(wait);
1077 struct ivtv *itv = fh2id(fh)->itv;
1078 struct yuv_playback_info *yi = &itv->yuv_info;
1079 int f;
1080
1081 if ((*std & V4L2_STD_ALL) == 0)
1082 return -EINVAL;
1083
1084 if (*std == itv->std)
1085 return 0;
1086
1087 if (test_bit(IVTV_F_I_RADIO_USER, &itv->i_flags) ||
1088 atomic_read(&itv->capturing) > 0 ||
1089 atomic_read(&itv->decoding) > 0) {
1090 /* Switching standard would turn off the radio or mess
1091 with already running streams, prevent that by
1092 returning EBUSY. */
1093 return -EBUSY;
1094 }
1095
1096 itv->std = *std; 1076 itv->std = *std;
1097 itv->is_60hz = (*std & V4L2_STD_525_60) ? 1 : 0; 1077 itv->is_60hz = (*std & V4L2_STD_525_60) ? 1 : 0;
1098 itv->is_50hz = !itv->is_60hz; 1078 itv->is_50hz = !itv->is_60hz;
@@ -1106,48 +1086,79 @@ int ivtv_s_std(struct file *file, void *fh, v4l2_std_id *std)
1106 if (itv->hw_flags & IVTV_HW_CX25840) 1086 if (itv->hw_flags & IVTV_HW_CX25840)
1107 itv->vbi.sliced_decoder_line_size = itv->is_60hz ? 272 : 284; 1087 itv->vbi.sliced_decoder_line_size = itv->is_60hz ? 272 : 284;
1108 1088
1109 IVTV_DEBUG_INFO("Switching standard to %llx.\n", (unsigned long long)itv->std);
1110
1111 /* Tuner */ 1089 /* Tuner */
1112 ivtv_call_all(itv, core, s_std, itv->std); 1090 ivtv_call_all(itv, core, s_std, itv->std);
1091}
1113 1092
1114 if (itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT) { 1093void ivtv_s_std_dec(struct ivtv *itv, v4l2_std_id *std)
1115 /* set display standard */ 1094{
1116 itv->std_out = *std; 1095 struct yuv_playback_info *yi = &itv->yuv_info;
1117 itv->is_out_60hz = itv->is_60hz; 1096 DEFINE_WAIT(wait);
1118 itv->is_out_50hz = itv->is_50hz; 1097 int f;
1119 ivtv_call_all(itv, video, s_std_output, itv->std_out); 1098
1120 1099 /* set display standard */
1121 /* 1100 itv->std_out = *std;
1122 * The next firmware call is time sensitive. Time it to 1101 itv->is_out_60hz = (*std & V4L2_STD_525_60) ? 1 : 0;
1123 * avoid risk of a hard lock, by trying to ensure the call 1102 itv->is_out_50hz = !itv->is_out_60hz;
1124 * happens within the first 100 lines of the top field. 1103 ivtv_call_all(itv, video, s_std_output, itv->std_out);
1125 * Make 4 attempts to sync to the decoder before giving up. 1104
1126 */ 1105 /*
1127 for (f = 0; f < 4; f++) { 1106 * The next firmware call is time sensitive. Time it to
1128 prepare_to_wait(&itv->vsync_waitq, &wait, 1107 * avoid risk of a hard lock, by trying to ensure the call
1129 TASK_UNINTERRUPTIBLE); 1108 * happens within the first 100 lines of the top field.
1130 if ((read_reg(IVTV_REG_DEC_LINE_FIELD) >> 16) < 100) 1109 * Make 4 attempts to sync to the decoder before giving up.
1131 break; 1110 */
1132 schedule_timeout(msecs_to_jiffies(25)); 1111 for (f = 0; f < 4; f++) {
1133 } 1112 prepare_to_wait(&itv->vsync_waitq, &wait,
1134 finish_wait(&itv->vsync_waitq, &wait); 1113 TASK_UNINTERRUPTIBLE);
1135 1114 if ((read_reg(IVTV_REG_DEC_LINE_FIELD) >> 16) < 100)
1136 if (f == 4) 1115 break;
1137 IVTV_WARN("Mode change failed to sync to decoder\n"); 1116 schedule_timeout(msecs_to_jiffies(25));
1138
1139 ivtv_vapi(itv, CX2341X_DEC_SET_STANDARD, 1, itv->is_out_50hz);
1140 itv->main_rect.left = itv->main_rect.top = 0;
1141 itv->main_rect.width = 720;
1142 itv->main_rect.height = itv->cxhdl.height;
1143 ivtv_vapi(itv, CX2341X_OSD_SET_FRAMEBUFFER_WINDOW, 4,
1144 720, itv->main_rect.height, 0, 0);
1145 yi->main_rect = itv->main_rect;
1146 if (!itv->osd_info) {
1147 yi->osd_full_w = 720;
1148 yi->osd_full_h = itv->is_out_50hz ? 576 : 480;
1149 }
1150 } 1117 }
1118 finish_wait(&itv->vsync_waitq, &wait);
1119
1120 if (f == 4)
1121 IVTV_WARN("Mode change failed to sync to decoder\n");
1122
1123 ivtv_vapi(itv, CX2341X_DEC_SET_STANDARD, 1, itv->is_out_50hz);
1124 itv->main_rect.left = 0;
1125 itv->main_rect.top = 0;
1126 itv->main_rect.width = 720;
1127 itv->main_rect.height = itv->is_out_50hz ? 576 : 480;
1128 ivtv_vapi(itv, CX2341X_OSD_SET_FRAMEBUFFER_WINDOW, 4,
1129 720, itv->main_rect.height, 0, 0);
1130 yi->main_rect = itv->main_rect;
1131 if (!itv->osd_info) {
1132 yi->osd_full_w = 720;
1133 yi->osd_full_h = itv->is_out_50hz ? 576 : 480;
1134 }
1135}
1136
1137int ivtv_s_std(struct file *file, void *fh, v4l2_std_id *std)
1138{
1139 struct ivtv *itv = fh2id(fh)->itv;
1140
1141 if ((*std & V4L2_STD_ALL) == 0)
1142 return -EINVAL;
1143
1144 if (*std == itv->std)
1145 return 0;
1146
1147 if (test_bit(IVTV_F_I_RADIO_USER, &itv->i_flags) ||
1148 atomic_read(&itv->capturing) > 0 ||
1149 atomic_read(&itv->decoding) > 0) {
1150 /* Switching standard would mess with already running
1151 streams, prevent that by returning EBUSY. */
1152 return -EBUSY;
1153 }
1154
1155 IVTV_DEBUG_INFO("Switching standard to %llx.\n",
1156 (unsigned long long)itv->std);
1157
1158 ivtv_s_std_enc(itv, std);
1159 if (itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT)
1160 ivtv_s_std_dec(itv, std);
1161
1151 return 0; 1162 return 0;
1152} 1163}
1153 1164
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);
27void ivtv_set_osd_alpha(struct ivtv *itv); 27void ivtv_set_osd_alpha(struct ivtv *itv);
28int ivtv_set_speed(struct ivtv *itv, int speed); 28int ivtv_set_speed(struct ivtv *itv, int speed);
29void ivtv_set_funcs(struct video_device *vdev); 29void ivtv_set_funcs(struct video_device *vdev);
30int ivtv_s_std(struct file *file, void *fh, v4l2_std_id *std); 30void ivtv_s_std_enc(struct ivtv *itv, v4l2_std_id *std);
31void ivtv_s_std_dec(struct ivtv *itv, v4l2_std_id *std);
31int ivtv_s_frequency(struct file *file, void *fh, struct v4l2_frequency *vf); 32int ivtv_s_frequency(struct file *file, void *fh, struct v4l2_frequency *vf);
32int ivtv_s_input(struct file *file, void *fh, unsigned int inp); 33int ivtv_s_input(struct file *file, void *fh, unsigned int inp);
33long ivtv_v4l2_ioctl(struct file *filp, unsigned int cmd, unsigned long arg); 34long 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)
71 Turning this signal on and off can confuse certain 71 Turning this signal on and off can confuse certain
72 TVs. As far as I can tell there is no reason not to 72 TVs. As far as I can tell there is no reason not to
73 transmit this signal. */ 73 transmit this signal. */
74 if ((itv->std & V4L2_STD_625_50) && !enabled) { 74 if ((itv->std_out & V4L2_STD_625_50) && !enabled) {
75 enabled = 1; 75 enabled = 1;
76 mode = 0x08; /* 4x3 full format */ 76 mode = 0x08; /* 4x3 full format */
77 } 77 }
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
247 247
248static int ivtvfb_set_display_window(struct ivtv *itv, struct v4l2_rect *ivtv_window) 248static int ivtvfb_set_display_window(struct ivtv *itv, struct v4l2_rect *ivtv_window)
249{ 249{
250 int osd_height_limit = itv->is_50hz ? 576 : 480; 250 int osd_height_limit = itv->is_out_50hz ? 576 : 480;
251 251
252 /* Only fail if resolution too high, otherwise fudge the start coords. */ 252 /* Only fail if resolution too high, otherwise fudge the start coords. */
253 if ((ivtv_window->height > osd_height_limit) || (ivtv_window->width > IVTV_OSD_MAX_WIDTH)) 253 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
471 vblank.flags = FB_VBLANK_HAVE_COUNT |FB_VBLANK_HAVE_VCOUNT | 471 vblank.flags = FB_VBLANK_HAVE_COUNT |FB_VBLANK_HAVE_VCOUNT |
472 FB_VBLANK_HAVE_VSYNC; 472 FB_VBLANK_HAVE_VSYNC;
473 trace = read_reg(IVTV_REG_DEC_LINE_FIELD) >> 16; 473 trace = read_reg(IVTV_REG_DEC_LINE_FIELD) >> 16;
474 if (itv->is_50hz && trace > 312) 474 if (itv->is_out_50hz && trace > 312)
475 trace -= 312; 475 trace -= 312;
476 else if (itv->is_60hz && trace > 262) 476 else if (itv->is_out_60hz && trace > 262)
477 trace -= 262; 477 trace -= 262;
478 if (trace == 1) 478 if (trace == 1)
479 vblank.flags |= FB_VBLANK_VSYNCING; 479 vblank.flags |= FB_VBLANK_VSYNCING;
@@ -656,7 +656,7 @@ static int _ivtvfb_check_var(struct fb_var_screeninfo *var, struct ivtv *itv)
656 IVTVFB_DEBUG_INFO("ivtvfb_check_var\n"); 656 IVTVFB_DEBUG_INFO("ivtvfb_check_var\n");
657 657
658 /* Set base references for mode calcs. */ 658 /* Set base references for mode calcs. */
659 if (itv->is_50hz) { 659 if (itv->is_out_50hz) {
660 pixclock = 84316; 660 pixclock = 84316;
661 hlimit = 776; 661 hlimit = 776;
662 vlimit = 591; 662 vlimit = 591;
@@ -784,12 +784,12 @@ static int _ivtvfb_check_var(struct fb_var_screeninfo *var, struct ivtv *itv)
784 If the margins are too large, just center the screen 784 If the margins are too large, just center the screen
785 (enforcing margins causes too many problems) */ 785 (enforcing margins causes too many problems) */
786 786
787 if (var->left_margin + var->xres > IVTV_OSD_MAX_WIDTH + 1) { 787 if (var->left_margin + var->xres > IVTV_OSD_MAX_WIDTH + 1)
788 var->left_margin = 1 + ((IVTV_OSD_MAX_WIDTH - var->xres) / 2); 788 var->left_margin = 1 + ((IVTV_OSD_MAX_WIDTH - var->xres) / 2);
789 } 789
790 if (var->upper_margin + var->yres > (itv->is_50hz ? 577 : 481)) { 790 if (var->upper_margin + var->yres > (itv->is_out_50hz ? 577 : 481))
791 var->upper_margin = 1 + (((itv->is_50hz ? 576 : 480) - var->yres) / 2); 791 var->upper_margin = 1 + (((itv->is_out_50hz ? 576 : 480) -
792 } 792 var->yres) / 2);
793 793
794 /* Maintain overall 'size' for a constant refresh rate */ 794 /* Maintain overall 'size' for a constant refresh rate */
795 var->right_margin = hlimit - var->left_margin - var->xres; 795 var->right_margin = hlimit - var->left_margin - var->xres;
@@ -1008,19 +1008,21 @@ static int ivtvfb_init_vidmode(struct ivtv *itv)
1008 /* Hardware coords start at 0, user coords start at 1. */ 1008 /* Hardware coords start at 0, user coords start at 1. */
1009 osd_left--; 1009 osd_left--;
1010 1010
1011 start_window.left = osd_left >= 0 ? osd_left : ((IVTV_OSD_MAX_WIDTH - start_window.width) / 2); 1011 start_window.left = osd_left >= 0 ?
1012 osd_left : ((IVTV_OSD_MAX_WIDTH - start_window.width) / 2);
1012 1013
1013 oi->display_byte_stride = 1014 oi->display_byte_stride =
1014 start_window.width * oi->bytes_per_pixel; 1015 start_window.width * oi->bytes_per_pixel;
1015 1016
1016 /* Vertical size & position */ 1017 /* Vertical size & position */
1017 1018
1018 max_height = itv->is_50hz ? 576 : 480; 1019 max_height = itv->is_out_50hz ? 576 : 480;
1019 1020
1020 if (osd_yres > max_height) 1021 if (osd_yres > max_height)
1021 osd_yres = max_height; 1022 osd_yres = max_height;
1022 1023
1023 start_window.height = osd_yres ? osd_yres : itv->is_50hz ? 480 : 400; 1024 start_window.height = osd_yres ?
1025 osd_yres : itv->is_out_50hz ? 480 : 400;
1024 1026
1025 /* Check vertical start (osd_upper). */ 1027 /* Check vertical start (osd_upper). */
1026 if (osd_upper + start_window.height > max_height + 1) { 1028 if (osd_upper + start_window.height > max_height + 1) {