[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:
committed by
Mauro Carvalho Chehab
parent
6600cc301d
commit
c5874c9245
@@ -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);
|
||||||
}
|
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)
|
|||||||
{
|
{
|
||||||
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);
|
||||||
|
@@ -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) {
|
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 */
|
||||||
* The next firmware call is time sensitive. Time it to
|
itv->std_out = *std;
|
||||||
* avoid risk of a hard lock, by trying to ensure the call
|
itv->is_out_60hz = (*std & V4L2_STD_525_60) ? 1 : 0;
|
||||||
* happens within the first 100 lines of the top field.
|
itv->is_out_50hz = !itv->is_out_60hz;
|
||||||
* Make 4 attempts to sync to the decoder before giving up.
|
ivtv_call_all(itv, video, s_std_output, itv->std_out);
|
||||||
*/
|
|
||||||
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");
|
* The next firmware call is time sensitive. Time it to
|
||||||
|
* avoid risk of a hard lock, by trying to ensure the call
|
||||||
ivtv_vapi(itv, CX2341X_DEC_SET_STANDARD, 1, itv->is_out_50hz);
|
* happens within the first 100 lines of the top field.
|
||||||
itv->main_rect.left = itv->main_rect.top = 0;
|
* Make 4 attempts to sync to the decoder before giving up.
|
||||||
itv->main_rect.width = 720;
|
*/
|
||||||
itv->main_rect.height = itv->cxhdl.height;
|
for (f = 0; f < 4; f++) {
|
||||||
ivtv_vapi(itv, CX2341X_OSD_SET_FRAMEBUFFER_WINDOW, 4,
|
prepare_to_wait(&itv->vsync_waitq, &wait,
|
||||||
720, itv->main_rect.height, 0, 0);
|
TASK_UNINTERRUPTIBLE);
|
||||||
yi->main_rect = itv->main_rect;
|
if ((read_reg(IVTV_REG_DEC_LINE_FIELD) >> 16) < 100)
|
||||||
if (!itv->osd_info) {
|
break;
|
||||||
yi->osd_full_w = 720;
|
schedule_timeout(msecs_to_jiffies(25));
|
||||||
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);
|
|||||||
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)
|
|||||||
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
|
|||||||
|
|
||||||
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)) {
|
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)
|
|||||||
/* 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) {
|
||||||
|
Reference in New Issue
Block a user