aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/video/cx18/cx18-firmware.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/media/video/cx18/cx18-firmware.c')
-rw-r--r--drivers/media/video/cx18/cx18-firmware.c101
1 files changed, 51 insertions, 50 deletions
diff --git a/drivers/media/video/cx18/cx18-firmware.c b/drivers/media/video/cx18/cx18-firmware.c
index 8eac84314d40..e74f76d47df5 100644
--- a/drivers/media/video/cx18/cx18-firmware.c
+++ b/drivers/media/video/cx18/cx18-firmware.c
@@ -332,6 +332,10 @@ void cx18_init_memory(struct cx18 *cx)
332 332
333int cx18_firmware_init(struct cx18 *cx) 333int cx18_firmware_init(struct cx18 *cx)
334{ 334{
335 u32 fw_entry_addr;
336 int sz, retries;
337 u32 api_args[MAX_MB_ARGUMENTS];
338
335 /* Allow chip to control CLKRUN */ 339 /* Allow chip to control CLKRUN */
336 cx18_write_reg(cx, 0x5, CX18_DSP0_INTERRUPT_MASK); 340 cx18_write_reg(cx, 0x5, CX18_DSP0_INTERRUPT_MASK);
337 341
@@ -341,65 +345,62 @@ int cx18_firmware_init(struct cx18 *cx)
341 345
342 cx18_msleep_timeout(1, 0); 346 cx18_msleep_timeout(1, 0);
343 347
348 /* If the CPU is still running */
349 if ((cx18_read_reg(cx, CX18_PROC_SOFT_RESET) & 8) == 0) {
350 CX18_ERR("%s: couldn't stop CPU to load firmware\n", __func__);
351 return -EIO;
352 }
353
344 cx18_sw1_irq_enable(cx, IRQ_CPU_TO_EPU | IRQ_APU_TO_EPU); 354 cx18_sw1_irq_enable(cx, IRQ_CPU_TO_EPU | IRQ_APU_TO_EPU);
345 cx18_sw2_irq_enable(cx, IRQ_CPU_TO_EPU_ACK | IRQ_APU_TO_EPU_ACK); 355 cx18_sw2_irq_enable(cx, IRQ_CPU_TO_EPU_ACK | IRQ_APU_TO_EPU_ACK);
346 356
347 /* Only if the processor is not running */ 357 sz = load_cpu_fw_direct("v4l-cx23418-cpu.fw", cx->enc_mem, cx);
348 if (cx18_read_reg(cx, CX18_PROC_SOFT_RESET) & 8) { 358 if (sz <= 0)
349 u32 fw_entry_addr = 0; 359 return sz;
350 int sz = load_apu_fw_direct("v4l-cx23418-apu.fw", 360
351 cx->enc_mem, cx, &fw_entry_addr); 361 /* The SCB & IPC area *must* be correct before starting the firmwares */
352 362 cx18_init_scb(cx);
353 if (sz <= 0) 363
354 return sz; 364 fw_entry_addr = 0;
355 365 sz = load_apu_fw_direct("v4l-cx23418-apu.fw", cx->enc_mem, cx,
356 /* Clear bit0 for APU to start from 0 */ 366 &fw_entry_addr);
357 cx18_write_reg(cx, cx18_read_reg(cx, 0xc72030) & ~1, 0xc72030); 367 if (sz <= 0)
358 368 return sz;
359 cx18_write_enc(cx, 0xE51FF004, 0); /* ldr pc, [pc, #-4] */ 369
360 cx18_write_enc(cx, fw_entry_addr, 4); 370 /* Start the CPU. The CPU will take care of the APU for us. */
361 371 cx18_write_reg_expect(cx, 0x00080000, CX18_PROC_SOFT_RESET,
362 /* Start APU */ 372 0x00000000, 0x00080008);
363 cx18_write_reg_expect(cx, 0x00010000, CX18_PROC_SOFT_RESET, 373
364 0x00000000, 0x00010001); 374 /* Wait up to 500 ms for the APU to come out of reset */
365 cx18_msleep_timeout(500, 0); 375 for (retries = 0;
366 376 retries < 50 && (cx18_read_reg(cx, CX18_PROC_SOFT_RESET) & 1) == 1;
367 sz = sz <= 0 ? sz : load_cpu_fw_direct("v4l-cx23418-cpu.fw", 377 retries++)
368 cx->enc_mem, cx); 378 cx18_msleep_timeout(10, 0);
369 379
370 if (sz > 0) { 380 cx18_msleep_timeout(200, 0);
371 int retries = 0; 381
372 382 if (retries == 50 &&
373 /* start the CPU */ 383 (cx18_read_reg(cx, CX18_PROC_SOFT_RESET) & 1) == 1) {
374 cx18_write_reg_expect(cx, 384 CX18_ERR("Could not start the CPU\n");
375 0x00080000, CX18_PROC_SOFT_RESET, 385 return -EIO;
376 0x00000000, 0x00080008);
377 while (retries++ < 50) { /* Loop for max 500mS */
378 if ((cx18_read_reg(cx, CX18_PROC_SOFT_RESET)
379 & 1) == 0)
380 break;
381 cx18_msleep_timeout(10, 0);
382 }
383 cx18_msleep_timeout(200, 0);
384 if (retries == 51) {
385 CX18_ERR("Could not start the CPU\n");
386 return -EIO;
387 }
388 }
389 if (sz <= 0)
390 return -EIO;
391 } 386 }
392 387
393 /* 388 /*
394 * The CPU firmware apparently sets up to receive an interrupt for it's 389 * The CPU had once before set up to receive an interrupt for it's
395 * outgoing IRQ_CPU_TO_EPU_ACK to us (*boggle*). We get an interrupt 390 * outgoing IRQ_CPU_TO_EPU_ACK to us. If it ever does this, we get an
396 * when it sends us an ack, but by the time we process it, that flag in 391 * interrupt when it sends us an ack, but by the time we process it,
397 * the SW2 status register has been cleared by the CPU firmware. 392 * that flag in the SW2 status register has been cleared by the CPU
398 * We'll prevent that not so useful behavior by clearing the CPU's 393 * firmware. We'll prevent that not so useful condition from happening
399 * interrupt enables for Ack IRQ's we want to process. 394 * by clearing the CPU's interrupt enables for Ack IRQ's we want to
395 * process.
400 */ 396 */
401 cx18_sw2_irq_disable_cpu(cx, IRQ_CPU_TO_EPU_ACK | IRQ_APU_TO_EPU_ACK); 397 cx18_sw2_irq_disable_cpu(cx, IRQ_CPU_TO_EPU_ACK | IRQ_APU_TO_EPU_ACK);
402 398
399 /* Try a benign command to see if the CPU is alive and well */
400 sz = cx18_vapi_result(cx, api_args, CX18_CPU_DEBUG_PEEK32, 1, 0);
401 if (sz < 0)
402 return sz;
403
403 /* initialize GPIO */ 404 /* initialize GPIO */
404 cx18_write_reg_expect(cx, 0x14001400, 0xc78110, 0x00001400, 0x14001400); 405 cx18_write_reg_expect(cx, 0x14001400, 0xc78110, 0x00001400, 0x14001400);
405 return 0; 406 return 0;