forked from luck/tmp_suning_uos_patched
[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>
This commit is contained in:
parent
6600cc301d
commit
c5874c9245
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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");
|
||||
|
||||
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;
|
||||
}
|
||||
/*
|
||||
* 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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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 */
|
||||
}
|
||||
|
|
|
@ -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) {
|
||||
|
|
Loading…
Reference in New Issue
Block a user