Commit c5874c92 authored by Ian Armstrong's avatar Ian Armstrong Committed by Mauro Carvalho Chehab

[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: default avatarIan Armstrong <ian@iarmst.demon.co.uk>
Signed-off-by: default avatarAndy Walls <awalls@md.metrocast.net>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab@redhat.com>
parent 6600cc30
...@@ -1328,6 +1328,8 @@ int ivtv_init_on_first_open(struct ivtv *itv) ...@@ -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) ...@@ -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);
} ivtv_s_std_dec(itv, &itv->tuner_std);
else } 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);
......
...@@ -280,8 +280,6 @@ int ivtv_firmware_restart(struct ivtv *itv) ...@@ -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) ...@@ -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);
......
...@@ -1071,28 +1071,8 @@ static int ivtv_g_std(struct file *file, void *fh, v4l2_std_id *std) ...@@ -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) ...@@ -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) { void ivtv_s_std_dec(struct ivtv *itv, v4l2_std_id *std)
/* set display standard */ {
itv->std_out = *std; struct yuv_playback_info *yi = &itv->yuv_info;
itv->is_out_60hz = itv->is_60hz; DEFINE_WAIT(wait);
itv->is_out_50hz = itv->is_50hz; int f;
ivtv_call_all(itv, video, s_std_output, itv->std_out);
/* set display standard */
/* itv->std_out = *std;
* The next firmware call is time sensitive. Time it to itv->is_out_60hz = (*std & V4L2_STD_525_60) ? 1 : 0;
* avoid risk of a hard lock, by trying to ensure the call itv->is_out_50hz = !itv->is_out_60hz;
* happens within the first 100 lines of the top field. ivtv_call_all(itv, video, s_std_output, itv->std_out);
* Make 4 attempts to sync to the decoder before giving up.
*/ /*
for (f = 0; f < 4; f++) { * The next firmware call is time sensitive. Time it to
prepare_to_wait(&itv->vsync_waitq, &wait, * avoid risk of a hard lock, by trying to ensure the call
TASK_UNINTERRUPTIBLE); * happens within the first 100 lines of the top field.
if ((read_reg(IVTV_REG_DEC_LINE_FIELD) >> 16) < 100) * Make 4 attempts to sync to the decoder before giving up.
break; */
schedule_timeout(msecs_to_jiffies(25)); for (f = 0; f < 4; f++) {
} prepare_to_wait(&itv->vsync_waitq, &wait,
finish_wait(&itv->vsync_waitq, &wait); TASK_UNINTERRUPTIBLE);
if ((read_reg(IVTV_REG_DEC_LINE_FIELD) >> 16) < 100)
if (f == 4) break;
IVTV_WARN("Mode change failed to sync to decoder\n"); schedule_timeout(msecs_to_jiffies(25));
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;
}
} }
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;
} }
......
...@@ -27,7 +27,8 @@ u16 ivtv_get_service_set(struct v4l2_sliced_vbi_format *fmt); ...@@ -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);
......
...@@ -71,7 +71,7 @@ static void ivtv_set_wss(struct ivtv *itv, int enabled, int mode) ...@@ -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 */
} }
......
...@@ -247,7 +247,7 @@ static int ivtvfb_set_osd_coords(struct ivtv *itv, const struct ivtv_osd_coords ...@@ -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 ...@@ -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) ...@@ -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) ...@@ -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)) { if (var->upper_margin + var->yres > (itv->is_out_50hz ? 577 : 481))
var->upper_margin = 1 + (((itv->is_50hz ? 576 : 480) - var->yres) / 2); 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) ...@@ -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) {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment