34 static const char *rpu_str[] = {
"APU",
"CPU",
"EPU",
"HPU" };
36 #define API_FAST (1 << 2)
37 #define API_SLOW (1 << 3)
46 #define API_ENTRY(rpu, x, f) { (x), (f), (rpu), #x }
99 for (i = 0; api_info[
i].
cmd; i++)
100 if (api_info[i].cmd == cmd)
106 static char *u32arr2hex(
u32 data[],
int n,
char *
buf)
111 for (i = 0, p = buf; i <
n; i++, p += 11) {
113 snprintf(p, 12,
" %#010x", data[i]);
126 CX18_DEBUG_API(
"%s: req %#010x ack %#010x cmd %#010x err %#010x args%s"
146 if (list_is_singular(&mdl->
buf_list)) {
162 static void cx18_mdl_send_to_videobuf(
struct cx18_stream *s,
191 if ((offset + buf->
bytesused) <= vb_buf->
vb.bsize) {
217 static void cx18_mdl_send_to_alsa(
struct cx18 *cx,
struct cx18_stream *s,
228 if (list_is_singular(&mdl->
buf_list)) {
254 handle = mb->
args[0];
258 CX18_WARN(
"Got DMA done notification for unknown/inactive"
259 " handle %d, %s mailbox seq no %d\n", handle,
261 "stale" :
"good", mb->
request);
265 mdl_ack_count = mb->
args[2];
267 for (i = 0; i < mdl_ack_count; i++, mdl_ack++) {
293 CX18_WARN(
"Fell behind! Ignoring stale mailbox with "
294 " inconsistent data. Lost MDL for mailbox "
302 CX18_WARN(
"Could not find MDL %d for stream %s\n",
311 cx18_mdl_send_to_dvb(s, mdl);
312 cx18_enqueue(s, mdl, &s->
q_free);
316 cx18_mdl_send_to_alsa(cx, s, mdl);
317 cx18_enqueue(s, mdl, &s->
q_free);
319 cx18_enqueue(s, mdl, &s->
q_full);
322 cx18_mdl_send_to_videobuf(s, mdl);
323 cx18_enqueue(s, mdl, &s->
q_free);
325 cx18_enqueue(s, mdl, &s->
q_full);
331 cx18_stream_load_fw_queue(s);
351 switch (order->
rpu) {
354 switch (order->
mb.cmd) {
356 epu_dma_done(cx, order);
359 epu_debug(cx, order);
362 CX18_WARN(
"Unknown CPU to EPU mailbox command %#0x\n",
369 CX18_WARN(
"Unknown APU to EPU mailbox command %#0x\n",
387 struct cx18 *cx = order->
cx;
389 free_in_work_order(cx, order);
402 switch (order->
rpu) {
405 ack_mb = &cx->
scb->apu2epu_mb;
409 ack_mb = &cx->
scb->cpu2epu_mb;
412 CX18_WARN(
"Unhandled RPU (%d) for command %x ack\n",
413 order->
rpu, order->
mb.cmd);
417 req = order->
mb.request;
419 if (req != cx18_readl(cx, &ack_mb->
request) ||
420 req == cx18_readl(cx, &ack_mb->
ack)) {
422 "incoming %s to EPU mailbox (sequence no. %u) "
423 "while processing\n",
424 rpu_str[order->
rpu], rpu_str[order->
rpu], req);
428 cx18_writel(cx, req, &ack_mb->
ack);
429 cx18_write_reg_expect(cx, ack_irq,
SW2_INT_SET, ack_irq, ack_irq);
435 u32 handle, mdl_ack_offset, mdl_ack_count;
440 handle = mb->
args[0];
441 mdl_ack_offset = mb->
args[1];
442 mdl_ack_count = mb->
args[2];
447 mb_ack_irq(cx, order);
451 for (i = 0; i <
sizeof(
struct cx18_mdl_ack) * mdl_ack_count; i +=
sizeof(
u32))
453 cx18_readl(cx, cx->
enc_mem + mdl_ack_offset + i);
456 mb_ack_irq(cx, order);
464 char *str = order->
str;
467 str_offset = order->
mb.args[1];
470 cx18_memcpy_fromio(cx, str, cx->
enc_mem + str_offset, 252);
476 mb_ack_irq(cx, order);
478 return str_offset ? 1 : 0;
486 switch (order->
rpu) {
489 switch (order->
mb.cmd) {
491 ret = epu_dma_done_irq(cx, order);
494 ret = epu_debug_irq(cx, order);
497 CX18_WARN(
"Unknown CPU to EPU mailbox command %#0x\n",
504 CX18_WARN(
"Unknown APU to EPU mailbox command %#0x\n",
547 mb = &cx->
scb->cpu2epu_mb;
550 mb = &cx->
scb->apu2epu_mb;
556 order = alloc_in_work_order_irq(cx);
558 CX18_WARN(
"Unable to find blank work order form to schedule "
559 "incoming mailbox command processing\n");
565 order_mb = &order->
mb;
568 for (i = 0; i < 4; i++)
569 (&order_mb->
cmd)[
i] = cx18_readl(cx, &mb->
cmd + i);
572 for (i = 0; i < 2; i++)
577 "incoming %s to EPU mailbox (sequence no. %u)"
579 rpu_str[rpu], rpu_str[rpu], order_mb->
request);
581 dump_mb(cx, order_mb,
"incoming");
589 submit = epu_cmd_irq(cx, order);
600 static int cx18_api_call(
struct cx18 *cx,
u32 cmd,
int args,
u32 data[])
606 struct mutex *mb_lock;
622 u32arr2hex(data, args, argstr));
626 u32arr2hex(data, args, argstr));
634 mb = &cx->
scb->epu2apu_mb;
640 mb = &cx->
scb->epu2cpu_mb;
643 CX18_WARN(
"Unknown RPU (%d) for API call\n", info->
rpu);
658 req = cx18_readl(cx, &mb->
request);
661 (ack = cx18_readl(cx, &mb->
ack)) == req,
665 cx18_writel(cx, req, &mb->
ack);
666 CX18_ERR(
"mbox was found stuck busy when setting up for %s; "
667 "clearing busy and trying to proceed\n", info->
name);
668 }
else if (ret != timeout)
673 req = ((req & 0xfffffffe) == 0xfffffffe) ? 1 : req + 1;
675 cx18_writel(cx, cmd, &mb->
cmd);
676 for (i = 0; i < args; i++)
677 cx18_writel(cx, data[i], &mb->
args[i]);
678 cx18_writel(cx, 0, &mb->
error);
679 cx18_writel(cx, req, &mb->
request);
680 cx18_writel(cx, req - 1, &mb->
ack);
692 cx18_write_reg_expect(cx, irq,
SW1_INT_SET, irq, irq);
695 ack = cx18_readl(cx, &mb->
ack);
699 ack = cx18_readl(cx, &mb->
ack);
708 if (ret >= timeout) {
711 "for RPU acknowledgement\n",
715 "after submitting %s to RPU. only "
716 "waited %d msecs on req %u but awakened"
717 " with unmatched ack %u\n",
727 "sending %s; timed out waiting %d msecs\n",
735 data[i] = cx18_readl(cx, &mb->
args[i]);
736 err = cx18_readl(cx, &mb->
error);
750 return err ? -
EIO : 0;
755 return cx18_api_call(cx, cmd, args, data);
758 static int cx18_set_filter_param(
struct cx18_stream *s)
786 s->
handle, 0, 0, 0, 0, data[0]);
789 s->
handle, data[1], data[0]);
799 s->
handle, data[0], data[1]);
810 s->
handle, data[0], data[1], data[2], data[3]);
819 s->
handle, data[0], data[1], data[2]);
822 return cx18_set_filter_param(s);
826 return cx18_set_filter_param(s);
829 s->
handle, data[0], data[1]);
832 s->
handle, data[0], data[1], data[2], data[3]);
839 u32 cmd,
int args, ...)
845 for (i = 0; i < args; i++)
848 return cx18_api(cx, cmd, args, data);
858 CX18_ERR(
"cx == NULL (cmd=%x)\n", cmd);
861 if (args > MAX_MB_ARGUMENTS) {
862 CX18_ERR(
"args too big (cmd=%x)\n", cmd);
866 for (i = 0; i < args; i++)
869 return cx18_api(cx, cmd, args, data);