Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 201979
b: refs/heads/master
c: 215659d
h: refs/heads/master
i:
  201977: d570f69
  201975: 93ef485
v: v3
  • Loading branch information
Ian Armstrong authored and Mauro Carvalho Chehab committed Aug 2, 2010
1 parent 954a298 commit bc7d1dd
Show file tree
Hide file tree
Showing 9 changed files with 143 additions and 16 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 914610e8c508224a6fb9fb501ed4bda25b340ba6
refs/heads/master: 215659d14f9dbc849ccda1655c94d710f8cc6384
1 change: 1 addition & 0 deletions trunk/drivers/media/video/ivtv/ivtv-driver.c
Original file line number Diff line number Diff line change
Expand Up @@ -1444,6 +1444,7 @@ EXPORT_SYMBOL(ivtv_udma_unmap);
EXPORT_SYMBOL(ivtv_udma_alloc);
EXPORT_SYMBOL(ivtv_udma_prepare);
EXPORT_SYMBOL(ivtv_init_on_first_open);
EXPORT_SYMBOL(ivtv_firmware_check);

module_init(module_start);
module_exit(module_cleanup);
1 change: 1 addition & 0 deletions trunk/drivers/media/video/ivtv/ivtv-driver.h
Original file line number Diff line number Diff line change
Expand Up @@ -737,6 +737,7 @@ struct ivtv {
struct v4l2_rect osd_rect; /* current OSD position and size */
struct v4l2_rect main_rect; /* current Main window position and size */
struct osd_info *osd_info; /* ivtvfb private OSD info */
void (*ivtvfb_restore)(struct ivtv *itv); /* Used for a warm start */
};

static inline struct ivtv *to_ivtv(struct v4l2_device *v4l2_dev)
Expand Down
24 changes: 15 additions & 9 deletions trunk/drivers/media/video/ivtv/ivtv-fileops.c
Original file line number Diff line number Diff line change
Expand Up @@ -536,8 +536,12 @@ int ivtv_start_decoding(struct ivtv_open_id *id, int speed)
return -EBUSY;
}
rc = ivtv_start_v4l2_decode_stream(s, 0);
if (rc < 0)
return rc;
if (rc < 0) {
if (rc == -EAGAIN)
rc = ivtv_start_v4l2_decode_stream(s, 0);
if (rc < 0)
return rc;
}
}
if (s->type == IVTV_DEC_STREAM_TYPE_MPG)
return ivtv_set_speed(itv, speed);
Expand Down Expand Up @@ -926,19 +930,21 @@ static int ivtv_serialized_open(struct ivtv_stream *s, struct file *filp)
IVTV_DEBUG_FILE("open %s\n", s->name);

#ifdef CONFIG_VIDEO_ADV_DEBUG
/* Unless ivtv_fw_debug is set, error out if firmware dead. */
if (ivtv_fw_debug) {
IVTV_WARN("Opening %s with dead firmware lockout disabled\n",
video_device_node_name(vdev));
IVTV_WARN("Selected firmware errors will be ignored\n");
}

/* Unless ivtv_fw_debug is set, error out if firmware dead. */
if (ivtv_firmware_check(itv, "ivtv_serialized_open") && !ivtv_fw_debug)
return -EIO;
} else {
#else
if (ivtv_firmware_check(itv, "ivtv_serialized_open"))
return -EIO;
if (1) {
#endif
res = ivtv_firmware_check(itv, "ivtv_serialized_open");
if (res == -EAGAIN)
res = ivtv_firmware_check(itv, "ivtv_serialized_open");
if (res < 0)
return -EIO;
}

if (s->type == IVTV_DEC_STREAM_TYPE_MPG &&
test_bit(IVTV_F_S_CLAIMED, &itv->streams[IVTV_DEC_STREAM_TYPE_YUV].s_flags))
Expand Down
76 changes: 76 additions & 0 deletions trunk/drivers/media/video/ivtv/ivtv-firmware.c
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,10 @@
#include "ivtv-mailbox.h"
#include "ivtv-firmware.h"
#include "ivtv-yuv.h"
#include "ivtv-ioctl.h"
#include "ivtv-cards.h"
#include <linux/firmware.h>
#include <media/saa7127.h>

#define IVTV_MASK_SPU_ENABLE 0xFFFFFFFE
#define IVTV_MASK_VPU_ENABLE15 0xFFFFFFF6
Expand Down Expand Up @@ -272,6 +275,58 @@ void ivtv_init_mpeg_decoder(struct ivtv *itv)
ivtv_vapi(itv, CX2341X_DEC_STOP_PLAYBACK, 4, 0, 0, 0, 1);
}

/* Try to restart the card & restore previous settings */
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 */
ivtv_call_hw(itv, IVTV_HW_SAA7127, video, s_routing,
SAA7127_INPUT_TYPE_TEST_IMAGE,
itv->card->video_outputs[itv->active_output].video_output,
0);

mutex_lock(&itv->udma.lock);

rc = ivtv_firmware_init(itv);
if (rc) {
mutex_unlock(&itv->udma.lock);
return rc;
}

/* Allow settings to reload */
ivtv_mailbox_cache_invalidate(itv);

/* Restore video standard */
std = itv->std;
itv->std = 0;
ivtv_s_std(NULL, &fh, &std);

if (itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT) {
ivtv_init_mpeg_decoder(itv);

/* Restore framebuffer if active */
if (itv->ivtvfb_restore)
itv->ivtvfb_restore(itv);

/* Restore alpha settings */
ivtv_set_osd_alpha(itv);

/* Restore normal output */
ivtv_call_hw(itv, IVTV_HW_SAA7127, video, s_routing,
SAA7127_INPUT_TYPE_NORMAL,
itv->card->video_outputs[itv->active_output].video_output,
0);
}

mutex_unlock(&itv->udma.lock);
return rc;
}

/* Check firmware running state. The checks fall through
allowing multiple failures to be logged. */
int ivtv_firmware_check(struct ivtv *itv, char *where)
Expand Down Expand Up @@ -315,5 +370,26 @@ int ivtv_firmware_check(struct ivtv *itv, char *where)
}
}

/* If something failed & currently idle, try to reload */
if (res && !atomic_read(&itv->capturing) &&
!atomic_read(&itv->decoding)) {
IVTV_INFO("Detected in %s that firmware had failed - "
"Reloading\n", where);
res = ivtv_firmware_restart(itv);
/*
* Even if restarted ok, still signal a problem had occured.
* The caller can come through this function again to check
* if things are really ok after the restart.
*/
if (!res) {
IVTV_INFO("Firmware restart okay\n");
res = -EAGAIN;
} else {
IVTV_INFO("Firmware restart failed\n");
}
} else if (res) {
res = -EIO;
}

return res;
}
8 changes: 8 additions & 0 deletions trunk/drivers/media/video/ivtv/ivtv-mailbox.c
Original file line number Diff line number Diff line change
Expand Up @@ -377,3 +377,11 @@ void ivtv_api_get_data(struct ivtv_mailbox_data *mbdata, int mb,
for (i = 0; i < argc; i++, p++)
data[i] = readl(p);
}

/* Wipe api cache */
void ivtv_mailbox_cache_invalidate(struct ivtv *itv)
{
int i;
for (i = 0; i < 256; i++)
itv->api_cache[i].last_jiffies = 0;
}
1 change: 1 addition & 0 deletions trunk/drivers/media/video/ivtv/ivtv-mailbox.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,5 +30,6 @@ int ivtv_api(struct ivtv *itv, int cmd, int args, u32 data[]);
int ivtv_vapi_result(struct ivtv *itv, u32 data[CX2341X_MBOX_MAX_DATA], int cmd, int args, ...);
int ivtv_vapi(struct ivtv *itv, int cmd, int args, ...);
int ivtv_api_func(void *priv, u32 cmd, int in, int out, u32 data[CX2341X_MBOX_MAX_DATA]);
void ivtv_mailbox_cache_invalidate(struct ivtv *itv);

#endif
5 changes: 1 addition & 4 deletions trunk/drivers/media/video/ivtv/ivtv-streams.c
Original file line number Diff line number Diff line change
Expand Up @@ -676,10 +676,7 @@ static int ivtv_setup_v4l2_decode_stream(struct ivtv_stream *s)
ivtv_msleep_timeout(10, 0);

/* Known failure point for firmware, so check */
if (ivtv_firmware_check(itv, "ivtv_setup_v4l2_decode_stream") < 0)
return -EIO;

return 0;
return ivtv_firmware_check(itv, "ivtv_setup_v4l2_decode_stream");
}

int ivtv_start_v4l2_decode_stream(struct ivtv_stream *s, int gop_offset)
Expand Down
41 changes: 39 additions & 2 deletions trunk/drivers/media/video/ivtv/ivtvfb.c
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@
#include "ivtv-i2c.h"
#include "ivtv-udma.h"
#include "ivtv-mailbox.h"
#include "ivtv-firmware.h"

/* card parameters */
static int ivtvfb_card_id = -1;
Expand Down Expand Up @@ -178,6 +179,12 @@ struct osd_info {
struct fb_info ivtvfb_info;
struct fb_var_screeninfo ivtvfb_defined;
struct fb_fix_screeninfo ivtvfb_fix;

/* Used for a warm start */
struct fb_var_screeninfo fbvar_cur;
int blank_cur;
u32 palette_cur[256];
u32 pan_cur;
};

struct ivtv_osd_coords {
Expand All @@ -199,6 +206,7 @@ static int ivtvfb_get_framebuffer(struct ivtv *itv, u32 *fbbase,
u32 data[CX2341X_MBOX_MAX_DATA];
int rc;

ivtv_firmware_check(itv, "ivtvfb_get_framebuffer");
rc = ivtv_vapi_result(itv, data, CX2341X_OSD_GET_FRAMEBUFFER, 0);
*fbbase = data[0];
*fblength = data[1];
Expand Down Expand Up @@ -581,8 +589,10 @@ static int ivtvfb_set_var(struct ivtv *itv, struct fb_var_screeninfo *var)
ivtv_window.height = var->yres;

/* Minimum margin cannot be 0, as X won't allow such a mode */
if (!var->upper_margin) var->upper_margin++;
if (!var->left_margin) var->left_margin++;
if (!var->upper_margin)
var->upper_margin++;
if (!var->left_margin)
var->left_margin++;
ivtv_window.top = var->upper_margin - 1;
ivtv_window.left = var->left_margin - 1;

Expand All @@ -595,6 +605,9 @@ static int ivtvfb_set_var(struct ivtv *itv, struct fb_var_screeninfo *var)
/* Force update of yuv registers */
itv->yuv_info.yuv_forced_update = 1;

/* Keep a copy of these settings */
memcpy(&oi->fbvar_cur, var, sizeof(oi->fbvar_cur));

IVTVFB_DEBUG_INFO("Display size: %dx%d (virtual %dx%d) @ %dbpp\n",
var->xres, var->yres,
var->xres_virtual, var->yres_virtual,
Expand Down Expand Up @@ -829,6 +842,8 @@ static int ivtvfb_pan_display(struct fb_var_screeninfo *var, struct fb_info *inf
itv->yuv_info.osd_y_pan = var->yoffset;
/* Force update of yuv registers */
itv->yuv_info.yuv_forced_update = 1;
/* Remember this value */
itv->osd_info->pan_cur = osd_pan_index;
return 0;
}

Expand All @@ -842,6 +857,7 @@ static int ivtvfb_set_par(struct fb_info *info)
rc = ivtvfb_set_var(itv, &info->var);
ivtvfb_pan_display(&info->var, info);
ivtvfb_get_fix(itv, &info->fix);
ivtv_firmware_check(itv, "ivtvfb_set_par");
return rc;
}

Expand All @@ -859,6 +875,7 @@ static int ivtvfb_setcolreg(unsigned regno, unsigned red, unsigned green,
if (info->var.bits_per_pixel <= 8) {
write_reg(regno, 0x02a30);
write_reg(color, 0x02a34);
itv->osd_info->palette_cur[regno] = color;
return 0;
}
if (regno >= 16)
Expand Down Expand Up @@ -911,6 +928,7 @@ static int ivtvfb_blank(int blank_mode, struct fb_info *info)
ivtv_vapi(itv, CX2341X_OSD_SET_STATE, 1, 0);
break;
}
itv->osd_info->blank_cur = blank_mode;
return 0;
}

Expand All @@ -929,6 +947,21 @@ static struct fb_ops ivtvfb_ops = {
.fb_blank = ivtvfb_blank,
};

/* Restore hardware after firmware restart */
static void ivtvfb_restore(struct ivtv *itv)
{
struct osd_info *oi = itv->osd_info;
int i;

ivtvfb_set_var(itv, &oi->fbvar_cur);
ivtvfb_blank(oi->blank_cur, &oi->ivtvfb_info);
for (i = 0; i < 256; i++) {
write_reg(i, 0x02a30);
write_reg(oi->palette_cur[i], 0x02a34);
}
write_reg(oi->pan_cur, 0x02a0c);
}

/* Initialization */


Expand Down Expand Up @@ -1192,6 +1225,9 @@ static int ivtvfb_init_card(struct ivtv *itv)
/* Enable the osd */
ivtvfb_blank(FB_BLANK_UNBLANK, &itv->osd_info->ivtvfb_info);

/* Enable restart */
itv->ivtvfb_restore = ivtvfb_restore;

/* Allocate DMA */
ivtv_udma_alloc(itv);
return 0;
Expand Down Expand Up @@ -1226,6 +1262,7 @@ static int ivtvfb_callback_cleanup(struct device *dev, void *p)
return 0;
}
IVTVFB_INFO("Unregister framebuffer %d\n", itv->instance);
itv->ivtvfb_restore = NULL;
ivtvfb_blank(FB_BLANK_VSYNC_SUSPEND, &oi->ivtvfb_info);
ivtvfb_release_buffers(itv);
itv->osd_video_pbase = 0;
Expand Down

0 comments on commit bc7d1dd

Please sign in to comment.