aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/media/video/cx18/cx18-driver.c1
-rw-r--r--drivers/media/video/cx18/cx18-firmware.c101
-rw-r--r--drivers/media/video/cx18/cx18-mailbox.c3
-rw-r--r--drivers/media/video/cx18/cx18-scb.c1
-rw-r--r--drivers/media/video/cx18/cx23418.h6
5 files changed, 60 insertions, 52 deletions
diff --git a/drivers/media/video/cx18/cx18-driver.c b/drivers/media/video/cx18/cx18-driver.c
index d7baf1b97cb8..f50cf2167adc 100644
--- a/drivers/media/video/cx18/cx18-driver.c
+++ b/drivers/media/video/cx18/cx18-driver.c
@@ -878,6 +878,7 @@ static int __devinit cx18_probe(struct pci_dev *dev,
878 goto free_i2c; 878 goto free_i2c;
879 } 879 }
880 cx18_init_memory(cx); 880 cx18_init_memory(cx);
881 cx18_init_scb(cx);
881 882
882 /* Register IRQ */ 883 /* Register IRQ */
883 retval = request_irq(cx->dev->irq, cx18_irq_handler, 884 retval = request_irq(cx->dev->irq, cx18_irq_handler,
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;
diff --git a/drivers/media/video/cx18/cx18-mailbox.c b/drivers/media/video/cx18/cx18-mailbox.c
index d62351466e26..de5e723fdf44 100644
--- a/drivers/media/video/cx18/cx18-mailbox.c
+++ b/drivers/media/video/cx18/cx18-mailbox.c
@@ -82,8 +82,9 @@ static const struct cx18_api_info api_info[] = {
82 API_ENTRY(CPU, CX18_CPU_GET_ENC_PTS, 0), 82 API_ENTRY(CPU, CX18_CPU_GET_ENC_PTS, 0),
83 API_ENTRY(CPU, CX18_CPU_DE_SET_MDL_ACK, 0), 83 API_ENTRY(CPU, CX18_CPU_DE_SET_MDL_ACK, 0),
84 API_ENTRY(CPU, CX18_CPU_DE_SET_MDL, API_FAST), 84 API_ENTRY(CPU, CX18_CPU_DE_SET_MDL, API_FAST),
85 API_ENTRY(CPU, CX18_APU_RESETAI, API_FAST),
86 API_ENTRY(CPU, CX18_CPU_DE_RELEASE_MDL, API_SLOW), 85 API_ENTRY(CPU, CX18_CPU_DE_RELEASE_MDL, API_SLOW),
86 API_ENTRY(APU, CX18_APU_RESETAI, 0),
87 API_ENTRY(CPU, CX18_CPU_DEBUG_PEEK32, 0),
87 API_ENTRY(0, 0, 0), 88 API_ENTRY(0, 0, 0),
88}; 89};
89 90
diff --git a/drivers/media/video/cx18/cx18-scb.c b/drivers/media/video/cx18/cx18-scb.c
index ac18bd9326d5..34b4d03c55cd 100644
--- a/drivers/media/video/cx18/cx18-scb.c
+++ b/drivers/media/video/cx18/cx18-scb.c
@@ -118,6 +118,5 @@ void cx18_init_scb(struct cx18 *cx)
118 cx18_writel(cx, SCB_OFFSET + offsetof(struct cx18_scb, cpu_state), 118 cx18_writel(cx, SCB_OFFSET + offsetof(struct cx18_scb, cpu_state),
119 &cx->scb->ipc_offset); 119 &cx->scb->ipc_offset);
120 120
121 cx18_writel(cx, 1, &cx->scb->hpu_state);
122 cx18_writel(cx, 1, &cx->scb->epu_state); 121 cx18_writel(cx, 1, &cx->scb->epu_state);
123} 122}
diff --git a/drivers/media/video/cx18/cx23418.h b/drivers/media/video/cx18/cx23418.h
index 668f968d7761..601f3a2ab742 100644
--- a/drivers/media/video/cx18/cx23418.h
+++ b/drivers/media/video/cx18/cx23418.h
@@ -44,6 +44,7 @@
44 44
45/* All commands for CPU have the following mask set */ 45/* All commands for CPU have the following mask set */
46#define CPU_CMD_MASK 0x20000000 46#define CPU_CMD_MASK 0x20000000
47#define CPU_CMD_MASK_DEBUG (CPU_CMD_MASK | 0x00000000)
47#define CPU_CMD_MASK_ACK (CPU_CMD_MASK | 0x80000000) 48#define CPU_CMD_MASK_ACK (CPU_CMD_MASK | 0x80000000)
48#define CPU_CMD_MASK_CAPTURE (CPU_CMD_MASK | 0x00020000) 49#define CPU_CMD_MASK_CAPTURE (CPU_CMD_MASK | 0x00020000)
49#define CPU_CMD_MASK_TS (CPU_CMD_MASK | 0x00040000) 50#define CPU_CMD_MASK_TS (CPU_CMD_MASK | 0x00040000)
@@ -71,6 +72,11 @@
71 0/zero/NULL means "I have nothing to say" */ 72 0/zero/NULL means "I have nothing to say" */
72#define CX18_EPU_DEBUG (EPU_CMD_MASK_DEBUG | 0x0003) 73#define CX18_EPU_DEBUG (EPU_CMD_MASK_DEBUG | 0x0003)
73 74
75/* Reads memory/registers (32-bit)
76 IN[0] - Address
77 OUT[1] - Value */
78#define CX18_CPU_DEBUG_PEEK32 (CPU_CMD_MASK_DEBUG | 0x0003)
79
74/* Description: This command starts streaming with the set channel type 80/* Description: This command starts streaming with the set channel type
75 IN[0] - Task handle. Handle of the task to start 81 IN[0] - Task handle. Handle of the task to start
76 ReturnCode - One of the ERR_CAPTURE_... */ 82 ReturnCode - One of the ERR_CAPTURE_... */