diff options
Diffstat (limited to 'drivers/media/video/ivtv/ivtv-firmware.c')
-rw-r--r-- | drivers/media/video/ivtv/ivtv-firmware.c | 122 |
1 files changed, 122 insertions, 0 deletions
diff --git a/drivers/media/video/ivtv/ivtv-firmware.c b/drivers/media/video/ivtv/ivtv-firmware.c index a71e8ba306b0..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 |
@@ -271,3 +274,122 @@ void ivtv_init_mpeg_decoder(struct ivtv *itv) | |||
271 | } | 274 | } |
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 | } |
277 | |||
278 | /* Try to restart the card & restore previous settings */ | ||
279 | int 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 | |||
330 | /* Check firmware running state. The checks fall through | ||
331 | allowing multiple failures to be logged. */ | ||
332 | int ivtv_firmware_check(struct ivtv *itv, char *where) | ||
333 | { | ||
334 | int res = 0; | ||
335 | |||
336 | /* Check encoder is still running */ | ||
337 | if (ivtv_vapi(itv, CX2341X_ENC_PING_FW, 0) < 0) { | ||
338 | IVTV_WARN("Encoder has died : %s\n", where); | ||
339 | res = -1; | ||
340 | } | ||
341 | |||
342 | /* Also check audio. Only check if not in use & encoder is okay */ | ||
343 | if (!res && !atomic_read(&itv->capturing) && | ||
344 | (!atomic_read(&itv->decoding) || | ||
345 | (atomic_read(&itv->decoding) < 2 && test_bit(IVTV_F_I_DEC_YUV, | ||
346 | &itv->i_flags)))) { | ||
347 | |||
348 | if (ivtv_vapi(itv, CX2341X_ENC_MISC, 1, 12) < 0) { | ||
349 | IVTV_WARN("Audio has died (Encoder OK) : %s\n", where); | ||
350 | res = -2; | ||
351 | } | ||
352 | } | ||
353 | |||
354 | if (itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT) { | ||
355 | /* Second audio check. Skip if audio already failed */ | ||
356 | if (res != -2 && read_dec(0x100) != read_dec(0x104)) { | ||
357 | /* Wait & try again to be certain. */ | ||
358 | ivtv_msleep_timeout(14, 0); | ||
359 | if (read_dec(0x100) != read_dec(0x104)) { | ||
360 | IVTV_WARN("Audio has died (Decoder) : %s\n", | ||
361 | where); | ||
362 | res = -1; | ||
363 | } | ||
364 | } | ||
365 | |||
366 | /* Check decoder is still running */ | ||
367 | if (ivtv_vapi(itv, CX2341X_DEC_PING_FW, 0) < 0) { | ||
368 | IVTV_WARN("Decoder has died : %s\n", where); | ||
369 | res = -1; | ||
370 | } | ||
371 | } | ||
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 | |||
394 | return res; | ||
395 | } | ||