aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/video/ivtv
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/media/video/ivtv')
-rw-r--r--drivers/media/video/ivtv/ivtv-driver.c1
-rw-r--r--drivers/media/video/ivtv/ivtv-driver.h1
-rw-r--r--drivers/media/video/ivtv/ivtv-fileops.c24
-rw-r--r--drivers/media/video/ivtv/ivtv-firmware.c76
-rw-r--r--drivers/media/video/ivtv/ivtv-mailbox.c8
-rw-r--r--drivers/media/video/ivtv/ivtv-mailbox.h1
-rw-r--r--drivers/media/video/ivtv/ivtv-streams.c5
-rw-r--r--drivers/media/video/ivtv/ivtvfb.c41
8 files changed, 142 insertions, 15 deletions
diff --git a/drivers/media/video/ivtv/ivtv-driver.c b/drivers/media/video/ivtv/ivtv-driver.c
index 3737797f20ea..90daa6e751d8 100644
--- a/drivers/media/video/ivtv/ivtv-driver.c
+++ b/drivers/media/video/ivtv/ivtv-driver.c
@@ -1444,6 +1444,7 @@ EXPORT_SYMBOL(ivtv_udma_unmap);
1444EXPORT_SYMBOL(ivtv_udma_alloc); 1444EXPORT_SYMBOL(ivtv_udma_alloc);
1445EXPORT_SYMBOL(ivtv_udma_prepare); 1445EXPORT_SYMBOL(ivtv_udma_prepare);
1446EXPORT_SYMBOL(ivtv_init_on_first_open); 1446EXPORT_SYMBOL(ivtv_init_on_first_open);
1447EXPORT_SYMBOL(ivtv_firmware_check);
1447 1448
1448module_init(module_start); 1449module_init(module_start);
1449module_exit(module_cleanup); 1450module_exit(module_cleanup);
diff --git a/drivers/media/video/ivtv/ivtv-driver.h b/drivers/media/video/ivtv/ivtv-driver.h
index c038dc8beb3c..bd084df4448a 100644
--- a/drivers/media/video/ivtv/ivtv-driver.h
+++ b/drivers/media/video/ivtv/ivtv-driver.h
@@ -737,6 +737,7 @@ struct ivtv {
737 struct v4l2_rect osd_rect; /* current OSD position and size */ 737 struct v4l2_rect osd_rect; /* current OSD position and size */
738 struct v4l2_rect main_rect; /* current Main window position and size */ 738 struct v4l2_rect main_rect; /* current Main window position and size */
739 struct osd_info *osd_info; /* ivtvfb private OSD info */ 739 struct osd_info *osd_info; /* ivtvfb private OSD info */
740 void (*ivtvfb_restore)(struct ivtv *itv); /* Used for a warm start */
740}; 741};
741 742
742static inline struct ivtv *to_ivtv(struct v4l2_device *v4l2_dev) 743static inline struct ivtv *to_ivtv(struct v4l2_device *v4l2_dev)
diff --git a/drivers/media/video/ivtv/ivtv-fileops.c b/drivers/media/video/ivtv/ivtv-fileops.c
index 3fb21e1406a1..a6a2cdb81566 100644
--- a/drivers/media/video/ivtv/ivtv-fileops.c
+++ b/drivers/media/video/ivtv/ivtv-fileops.c
@@ -536,8 +536,12 @@ int ivtv_start_decoding(struct ivtv_open_id *id, int speed)
536 return -EBUSY; 536 return -EBUSY;
537 } 537 }
538 rc = ivtv_start_v4l2_decode_stream(s, 0); 538 rc = ivtv_start_v4l2_decode_stream(s, 0);
539 if (rc < 0) 539 if (rc < 0) {
540 return rc; 540 if (rc == -EAGAIN)
541 rc = ivtv_start_v4l2_decode_stream(s, 0);
542 if (rc < 0)
543 return rc;
544 }
541 } 545 }
542 if (s->type == IVTV_DEC_STREAM_TYPE_MPG) 546 if (s->type == IVTV_DEC_STREAM_TYPE_MPG)
543 return ivtv_set_speed(itv, speed); 547 return ivtv_set_speed(itv, speed);
@@ -926,19 +930,21 @@ static int ivtv_serialized_open(struct ivtv_stream *s, struct file *filp)
926 IVTV_DEBUG_FILE("open %s\n", s->name); 930 IVTV_DEBUG_FILE("open %s\n", s->name);
927 931
928#ifdef CONFIG_VIDEO_ADV_DEBUG 932#ifdef CONFIG_VIDEO_ADV_DEBUG
933 /* Unless ivtv_fw_debug is set, error out if firmware dead. */
929 if (ivtv_fw_debug) { 934 if (ivtv_fw_debug) {
930 IVTV_WARN("Opening %s with dead firmware lockout disabled\n", 935 IVTV_WARN("Opening %s with dead firmware lockout disabled\n",
931 video_device_node_name(vdev)); 936 video_device_node_name(vdev));
932 IVTV_WARN("Selected firmware errors will be ignored\n"); 937 IVTV_WARN("Selected firmware errors will be ignored\n");
933 } 938 } else {
934
935 /* Unless ivtv_fw_debug is set, error out if firmware dead. */
936 if (ivtv_firmware_check(itv, "ivtv_serialized_open") && !ivtv_fw_debug)
937 return -EIO;
938#else 939#else
939 if (ivtv_firmware_check(itv, "ivtv_serialized_open")) 940 if (1) {
940 return -EIO;
941#endif 941#endif
942 res = ivtv_firmware_check(itv, "ivtv_serialized_open");
943 if (res == -EAGAIN)
944 res = ivtv_firmware_check(itv, "ivtv_serialized_open");
945 if (res < 0)
946 return -EIO;
947 }
942 948
943 if (s->type == IVTV_DEC_STREAM_TYPE_MPG && 949 if (s->type == IVTV_DEC_STREAM_TYPE_MPG &&
944 test_bit(IVTV_F_S_CLAIMED, &itv->streams[IVTV_DEC_STREAM_TYPE_YUV].s_flags)) 950 test_bit(IVTV_F_S_CLAIMED, &itv->streams[IVTV_DEC_STREAM_TYPE_YUV].s_flags))
diff --git a/drivers/media/video/ivtv/ivtv-firmware.c b/drivers/media/video/ivtv/ivtv-firmware.c
index efb288d34ca3..d8bf2b01729d 100644
--- a/drivers/media/video/ivtv/ivtv-firmware.c
+++ b/drivers/media/video/ivtv/ivtv-firmware.c
@@ -23,7 +23,10 @@
23#include "ivtv-mailbox.h" 23#include "ivtv-mailbox.h"
24#include "ivtv-firmware.h" 24#include "ivtv-firmware.h"
25#include "ivtv-yuv.h" 25#include "ivtv-yuv.h"
26#include "ivtv-ioctl.h"
27#include "ivtv-cards.h"
26#include <linux/firmware.h> 28#include <linux/firmware.h>
29#include <media/saa7127.h>
27 30
28#define IVTV_MASK_SPU_ENABLE 0xFFFFFFFE 31#define IVTV_MASK_SPU_ENABLE 0xFFFFFFFE
29#define IVTV_MASK_VPU_ENABLE15 0xFFFFFFF6 32#define IVTV_MASK_VPU_ENABLE15 0xFFFFFFF6
@@ -272,6 +275,58 @@ void ivtv_init_mpeg_decoder(struct ivtv *itv)
272 ivtv_vapi(itv, CX2341X_DEC_STOP_PLAYBACK, 4, 0, 0, 0, 1); 275 ivtv_vapi(itv, CX2341X_DEC_STOP_PLAYBACK, 4, 0, 0, 0, 1);
273} 276}
274 277
278/* Try to restart the card & restore previous settings */
279int ivtv_firmware_restart(struct ivtv *itv)
280{
281 int rc = 0;
282 v4l2_std_id std;
283 struct ivtv_open_id fh;
284 fh.itv = itv;
285
286 if (itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT)
287 /* Display test image during restart */
288 ivtv_call_hw(itv, IVTV_HW_SAA7127, video, s_routing,
289 SAA7127_INPUT_TYPE_TEST_IMAGE,
290 itv->card->video_outputs[itv->active_output].video_output,
291 0);
292
293 mutex_lock(&itv->udma.lock);
294
295 rc = ivtv_firmware_init(itv);
296 if (rc) {
297 mutex_unlock(&itv->udma.lock);
298 return rc;
299 }
300
301 /* Allow settings to reload */
302 ivtv_mailbox_cache_invalidate(itv);
303
304 /* Restore video standard */
305 std = itv->std;
306 itv->std = 0;
307 ivtv_s_std(NULL, &fh, &std);
308
309 if (itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT) {
310 ivtv_init_mpeg_decoder(itv);
311
312 /* Restore framebuffer if active */
313 if (itv->ivtvfb_restore)
314 itv->ivtvfb_restore(itv);
315
316 /* Restore alpha settings */
317 ivtv_set_osd_alpha(itv);
318
319 /* Restore normal output */
320 ivtv_call_hw(itv, IVTV_HW_SAA7127, video, s_routing,
321 SAA7127_INPUT_TYPE_NORMAL,
322 itv->card->video_outputs[itv->active_output].video_output,
323 0);
324 }
325
326 mutex_unlock(&itv->udma.lock);
327 return rc;
328}
329
275/* Check firmware running state. The checks fall through 330/* Check firmware running state. The checks fall through
276 allowing multiple failures to be logged. */ 331 allowing multiple failures to be logged. */
277int ivtv_firmware_check(struct ivtv *itv, char *where) 332int ivtv_firmware_check(struct ivtv *itv, char *where)
@@ -315,5 +370,26 @@ int ivtv_firmware_check(struct ivtv *itv, char *where)
315 } 370 }
316 } 371 }
317 372
373 /* If something failed & currently idle, try to reload */
374 if (res && !atomic_read(&itv->capturing) &&
375 !atomic_read(&itv->decoding)) {
376 IVTV_INFO("Detected in %s that firmware had failed - "
377 "Reloading\n", where);
378 res = ivtv_firmware_restart(itv);
379 /*
380 * Even if restarted ok, still signal a problem had occured.
381 * The caller can come through this function again to check
382 * if things are really ok after the restart.
383 */
384 if (!res) {
385 IVTV_INFO("Firmware restart okay\n");
386 res = -EAGAIN;
387 } else {
388 IVTV_INFO("Firmware restart failed\n");
389 }
390 } else if (res) {
391 res = -EIO;
392 }
393
318 return res; 394 return res;
319} 395}
diff --git a/drivers/media/video/ivtv/ivtv-mailbox.c b/drivers/media/video/ivtv/ivtv-mailbox.c
index 84577f6f41a2..e3ce96763785 100644
--- a/drivers/media/video/ivtv/ivtv-mailbox.c
+++ b/drivers/media/video/ivtv/ivtv-mailbox.c
@@ -377,3 +377,11 @@ void ivtv_api_get_data(struct ivtv_mailbox_data *mbdata, int mb,
377 for (i = 0; i < argc; i++, p++) 377 for (i = 0; i < argc; i++, p++)
378 data[i] = readl(p); 378 data[i] = readl(p);
379} 379}
380
381/* Wipe api cache */
382void ivtv_mailbox_cache_invalidate(struct ivtv *itv)
383{
384 int i;
385 for (i = 0; i < 256; i++)
386 itv->api_cache[i].last_jiffies = 0;
387}
diff --git a/drivers/media/video/ivtv/ivtv-mailbox.h b/drivers/media/video/ivtv/ivtv-mailbox.h
index 8247662c928e..2c834d2cb56f 100644
--- a/drivers/media/video/ivtv/ivtv-mailbox.h
+++ b/drivers/media/video/ivtv/ivtv-mailbox.h
@@ -30,5 +30,6 @@ int ivtv_api(struct ivtv *itv, int cmd, int args, u32 data[]);
30int ivtv_vapi_result(struct ivtv *itv, u32 data[CX2341X_MBOX_MAX_DATA], int cmd, int args, ...); 30int ivtv_vapi_result(struct ivtv *itv, u32 data[CX2341X_MBOX_MAX_DATA], int cmd, int args, ...);
31int ivtv_vapi(struct ivtv *itv, int cmd, int args, ...); 31int ivtv_vapi(struct ivtv *itv, int cmd, int args, ...);
32int ivtv_api_func(void *priv, u32 cmd, int in, int out, u32 data[CX2341X_MBOX_MAX_DATA]); 32int ivtv_api_func(void *priv, u32 cmd, int in, int out, u32 data[CX2341X_MBOX_MAX_DATA]);
33void ivtv_mailbox_cache_invalidate(struct ivtv *itv);
33 34
34#endif 35#endif
diff --git a/drivers/media/video/ivtv/ivtv-streams.c b/drivers/media/video/ivtv/ivtv-streams.c
index f0dd011a2ccc..55df4190c28d 100644
--- a/drivers/media/video/ivtv/ivtv-streams.c
+++ b/drivers/media/video/ivtv/ivtv-streams.c
@@ -676,10 +676,7 @@ static int ivtv_setup_v4l2_decode_stream(struct ivtv_stream *s)
676 ivtv_msleep_timeout(10, 0); 676 ivtv_msleep_timeout(10, 0);
677 677
678 /* Known failure point for firmware, so check */ 678 /* Known failure point for firmware, so check */
679 if (ivtv_firmware_check(itv, "ivtv_setup_v4l2_decode_stream") < 0) 679 return ivtv_firmware_check(itv, "ivtv_setup_v4l2_decode_stream");
680 return -EIO;
681
682 return 0;
683} 680}
684 681
685int ivtv_start_v4l2_decode_stream(struct ivtv_stream *s, int gop_offset) 682int ivtv_start_v4l2_decode_stream(struct ivtv_stream *s, int gop_offset)
diff --git a/drivers/media/video/ivtv/ivtvfb.c b/drivers/media/video/ivtv/ivtvfb.c
index 9ff3425891ed..2c2d862ca89f 100644
--- a/drivers/media/video/ivtv/ivtvfb.c
+++ b/drivers/media/video/ivtv/ivtvfb.c
@@ -53,6 +53,7 @@
53#include "ivtv-i2c.h" 53#include "ivtv-i2c.h"
54#include "ivtv-udma.h" 54#include "ivtv-udma.h"
55#include "ivtv-mailbox.h" 55#include "ivtv-mailbox.h"
56#include "ivtv-firmware.h"
56 57
57/* card parameters */ 58/* card parameters */
58static int ivtvfb_card_id = -1; 59static int ivtvfb_card_id = -1;
@@ -178,6 +179,12 @@ struct osd_info {
178 struct fb_info ivtvfb_info; 179 struct fb_info ivtvfb_info;
179 struct fb_var_screeninfo ivtvfb_defined; 180 struct fb_var_screeninfo ivtvfb_defined;
180 struct fb_fix_screeninfo ivtvfb_fix; 181 struct fb_fix_screeninfo ivtvfb_fix;
182
183 /* Used for a warm start */
184 struct fb_var_screeninfo fbvar_cur;
185 int blank_cur;
186 u32 palette_cur[256];
187 u32 pan_cur;
181}; 188};
182 189
183struct ivtv_osd_coords { 190struct ivtv_osd_coords {
@@ -199,6 +206,7 @@ static int ivtvfb_get_framebuffer(struct ivtv *itv, u32 *fbbase,
199 u32 data[CX2341X_MBOX_MAX_DATA]; 206 u32 data[CX2341X_MBOX_MAX_DATA];
200 int rc; 207 int rc;
201 208
209 ivtv_firmware_check(itv, "ivtvfb_get_framebuffer");
202 rc = ivtv_vapi_result(itv, data, CX2341X_OSD_GET_FRAMEBUFFER, 0); 210 rc = ivtv_vapi_result(itv, data, CX2341X_OSD_GET_FRAMEBUFFER, 0);
203 *fbbase = data[0]; 211 *fbbase = data[0];
204 *fblength = data[1]; 212 *fblength = data[1];
@@ -581,8 +589,10 @@ static int ivtvfb_set_var(struct ivtv *itv, struct fb_var_screeninfo *var)
581 ivtv_window.height = var->yres; 589 ivtv_window.height = var->yres;
582 590
583 /* Minimum margin cannot be 0, as X won't allow such a mode */ 591 /* Minimum margin cannot be 0, as X won't allow such a mode */
584 if (!var->upper_margin) var->upper_margin++; 592 if (!var->upper_margin)
585 if (!var->left_margin) var->left_margin++; 593 var->upper_margin++;
594 if (!var->left_margin)
595 var->left_margin++;
586 ivtv_window.top = var->upper_margin - 1; 596 ivtv_window.top = var->upper_margin - 1;
587 ivtv_window.left = var->left_margin - 1; 597 ivtv_window.left = var->left_margin - 1;
588 598
@@ -595,6 +605,9 @@ static int ivtvfb_set_var(struct ivtv *itv, struct fb_var_screeninfo *var)
595 /* Force update of yuv registers */ 605 /* Force update of yuv registers */
596 itv->yuv_info.yuv_forced_update = 1; 606 itv->yuv_info.yuv_forced_update = 1;
597 607
608 /* Keep a copy of these settings */
609 memcpy(&oi->fbvar_cur, var, sizeof(oi->fbvar_cur));
610
598 IVTVFB_DEBUG_INFO("Display size: %dx%d (virtual %dx%d) @ %dbpp\n", 611 IVTVFB_DEBUG_INFO("Display size: %dx%d (virtual %dx%d) @ %dbpp\n",
599 var->xres, var->yres, 612 var->xres, var->yres,
600 var->xres_virtual, var->yres_virtual, 613 var->xres_virtual, var->yres_virtual,
@@ -829,6 +842,8 @@ static int ivtvfb_pan_display(struct fb_var_screeninfo *var, struct fb_info *inf
829 itv->yuv_info.osd_y_pan = var->yoffset; 842 itv->yuv_info.osd_y_pan = var->yoffset;
830 /* Force update of yuv registers */ 843 /* Force update of yuv registers */
831 itv->yuv_info.yuv_forced_update = 1; 844 itv->yuv_info.yuv_forced_update = 1;
845 /* Remember this value */
846 itv->osd_info->pan_cur = osd_pan_index;
832 return 0; 847 return 0;
833} 848}
834 849
@@ -842,6 +857,7 @@ static int ivtvfb_set_par(struct fb_info *info)
842 rc = ivtvfb_set_var(itv, &info->var); 857 rc = ivtvfb_set_var(itv, &info->var);
843 ivtvfb_pan_display(&info->var, info); 858 ivtvfb_pan_display(&info->var, info);
844 ivtvfb_get_fix(itv, &info->fix); 859 ivtvfb_get_fix(itv, &info->fix);
860 ivtv_firmware_check(itv, "ivtvfb_set_par");
845 return rc; 861 return rc;
846} 862}
847 863
@@ -859,6 +875,7 @@ static int ivtvfb_setcolreg(unsigned regno, unsigned red, unsigned green,
859 if (info->var.bits_per_pixel <= 8) { 875 if (info->var.bits_per_pixel <= 8) {
860 write_reg(regno, 0x02a30); 876 write_reg(regno, 0x02a30);
861 write_reg(color, 0x02a34); 877 write_reg(color, 0x02a34);
878 itv->osd_info->palette_cur[regno] = color;
862 return 0; 879 return 0;
863 } 880 }
864 if (regno >= 16) 881 if (regno >= 16)
@@ -911,6 +928,7 @@ static int ivtvfb_blank(int blank_mode, struct fb_info *info)
911 ivtv_vapi(itv, CX2341X_OSD_SET_STATE, 1, 0); 928 ivtv_vapi(itv, CX2341X_OSD_SET_STATE, 1, 0);
912 break; 929 break;
913 } 930 }
931 itv->osd_info->blank_cur = blank_mode;
914 return 0; 932 return 0;
915} 933}
916 934
@@ -929,6 +947,21 @@ static struct fb_ops ivtvfb_ops = {
929 .fb_blank = ivtvfb_blank, 947 .fb_blank = ivtvfb_blank,
930}; 948};
931 949
950/* Restore hardware after firmware restart */
951static void ivtvfb_restore(struct ivtv *itv)
952{
953 struct osd_info *oi = itv->osd_info;
954 int i;
955
956 ivtvfb_set_var(itv, &oi->fbvar_cur);
957 ivtvfb_blank(oi->blank_cur, &oi->ivtvfb_info);
958 for (i = 0; i < 256; i++) {
959 write_reg(i, 0x02a30);
960 write_reg(oi->palette_cur[i], 0x02a34);
961 }
962 write_reg(oi->pan_cur, 0x02a0c);
963}
964
932/* Initialization */ 965/* Initialization */
933 966
934 967
@@ -1192,6 +1225,9 @@ static int ivtvfb_init_card(struct ivtv *itv)
1192 /* Enable the osd */ 1225 /* Enable the osd */
1193 ivtvfb_blank(FB_BLANK_UNBLANK, &itv->osd_info->ivtvfb_info); 1226 ivtvfb_blank(FB_BLANK_UNBLANK, &itv->osd_info->ivtvfb_info);
1194 1227
1228 /* Enable restart */
1229 itv->ivtvfb_restore = ivtvfb_restore;
1230
1195 /* Allocate DMA */ 1231 /* Allocate DMA */
1196 ivtv_udma_alloc(itv); 1232 ivtv_udma_alloc(itv);
1197 return 0; 1233 return 0;
@@ -1226,6 +1262,7 @@ static int ivtvfb_callback_cleanup(struct device *dev, void *p)
1226 return 0; 1262 return 0;
1227 } 1263 }
1228 IVTVFB_INFO("Unregister framebuffer %d\n", itv->instance); 1264 IVTVFB_INFO("Unregister framebuffer %d\n", itv->instance);
1265 itv->ivtvfb_restore = NULL;
1229 ivtvfb_blank(FB_BLANK_VSYNC_SUSPEND, &oi->ivtvfb_info); 1266 ivtvfb_blank(FB_BLANK_VSYNC_SUSPEND, &oi->ivtvfb_info);
1230 ivtvfb_release_buffers(itv); 1267 ivtvfb_release_buffers(itv);
1231 itv->osd_video_pbase = 0; 1268 itv->osd_video_pbase = 0;