/*
 *  cx18 interrupt handling
 *
 *  Copyright (C) 2007  Hans Verkuil <hverkuil@xs4all.nl>
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
 *  02111-1307  USA
 */

#include "cx18-driver.h"
#include "cx18-firmware.h"
#include "cx18-fileops.h"
#include "cx18-queue.h"
#include "cx18-irq.h"
#include "cx18-ioctl.h"
#include "cx18-mailbox.h"
#include "cx18-vbi.h"
#include "cx18-scb.h"

#define DMA_MAGIC_COOKIE 0x000001fe

static void epu_dma_done(struct cx18 *cx, struct cx18_mailbox *mb)
{
	u32 handle = mb->args[0];
	struct cx18_stream *s = NULL;
	struct cx18_buffer *buf;
	u32 off;
	int i;
	int id;

	for (i = 0; i < CX18_MAX_STREAMS; i++) {
		s = &cx->streams[i];
		if ((handle == s->handle) && (s->dvb.enabled))
			break;
		if (s->v4l2dev && handle == s->handle)
			break;
	}
	if (i == CX18_MAX_STREAMS) {
		CX18_WARN("DMA done for unknown handle %d for stream %s\n",
			handle, s->name);
		mb->error = CXERR_NOT_OPEN;
		mb->cmd = 0;
		cx18_mb_ack(cx, mb);
		return;
	}

	off = mb->args[1];
	if (mb->args[2] != 1)
		CX18_WARN("Ack struct = %d for %s\n",
			mb->args[2], s->name);
	id = read_enc(off);
	buf = cx18_queue_find_buf(s, id, read_enc(off + 4));
	CX18_DEBUG_HI_DMA("DMA DONE for %s (buffer %d)\n", s->name, id);
	if (buf) {
		cx18_buf_sync_for_cpu(s, buf);
		if (s->type == CX18_ENC_STREAM_TYPE_TS && s->dvb.enabled) {
			/* process the buffer here */
			CX18_DEBUG_HI_DMA("TS recv and sent bytesused=%d\n",
					buf->bytesused);

			dvb_dmx_swfilter(&s->dvb.demux, buf->buf,
					buf->bytesused);

			cx18_buf_sync_for_device(s, buf);
			cx18_vapi(cx, CX18_CPU_DE_SET_MDL, 5, s->handle,
			    (void *)&cx->scb->cpu_mdl[buf->id] - cx->enc_mem,
			    1, buf->id, s->buf_size);
		} else
			set_bit(CX18_F_B_NEED_BUF_SWAP, &buf->b_flags);
	} else {
		CX18_WARN("Could not find buf %d for stream %s\n",
				read_enc(off), s->name);
	}
	mb->error = 0;
	mb->cmd = 0;
	cx18_mb_ack(cx, mb);
	wake_up(&cx->dma_waitq);
	if (s->id != -1)
		wake_up(&s->waitq);
}

static void epu_debug(struct cx18 *cx, struct cx18_mailbox *mb)
{
	char str[256] = { 0 };
	char *p;

	if (mb->args[1]) {
		setup_page(mb->args[1]);
		memcpy_fromio(str, cx->enc_mem + mb->args[1], 252);
		str[252] = 0;
	}
	cx18_mb_ack(cx, mb);
	CX18_DEBUG_INFO("%x %s\n", mb->args[0], str);
	p = strchr(str, '.');
	if (!test_bit(CX18_F_I_LOADED_FW, &cx->i_flags) && p && p > str)
		CX18_INFO("FW version: %s\n", p - 1);
}

static void hpu_cmd(struct cx18 *cx, u32 sw1)
{
	struct cx18_mailbox mb;

	if (sw1 & IRQ_CPU_TO_EPU) {
		memcpy_fromio(&mb, &cx->scb->cpu2epu_mb, sizeof(mb));
		mb.error = 0;

		switch (mb.cmd) {
		case CX18_EPU_DMA_DONE:
			epu_dma_done(cx, &mb);
			break;
		case CX18_EPU_DEBUG:
			epu_debug(cx, &mb);
			break;
		default:
			CX18_WARN("Unexpected mailbox command %08x\n", mb.cmd);
			break;
		}
	}
	if (sw1 & (IRQ_APU_TO_EPU | IRQ_HPU_TO_EPU))
		CX18_WARN("Unexpected interrupt %08x\n", sw1);
}

irqreturn_t cx18_irq_handler(int irq, void *dev_id)
{
	struct cx18 *cx = (struct cx18 *)dev_id;
	u32 sw1, sw1_mask;
	u32 sw2, sw2_mask;
	u32 hw2, hw2_mask;

	spin_lock(&cx->dma_reg_lock);

	hw2_mask = read_reg(HW2_INT_MASK5_PCI);
	hw2 = read_reg(HW2_INT_CLR_STATUS) & hw2_mask;
	sw2_mask = read_reg(SW2_INT_ENABLE_PCI) | IRQ_EPU_TO_HPU_ACK;
	sw2 = read_reg(SW2_INT_STATUS) & sw2_mask;
	sw1_mask = read_reg(SW1_INT_ENABLE_PCI) | IRQ_EPU_TO_HPU;
	sw1 = read_reg(SW1_INT_STATUS) & sw1_mask;

	write_reg(sw2&sw2_mask, SW2_INT_STATUS);
	write_reg(sw1&sw1_mask, SW1_INT_STATUS);
	write_reg(hw2&hw2_mask, HW2_INT_CLR_STATUS);

	if (sw1 || sw2 || hw2)
		CX18_DEBUG_HI_IRQ("SW1: %x  SW2: %x  HW2: %x\n", sw1, sw2, hw2);

	/* To do: interrupt-based I2C handling
	if (hw2 & 0x00c00000) {
	}
	*/

	if (sw2) {
		if (sw2 & (cx->scb->cpu2hpu_irq_ack | cx->scb->cpu2epu_irq_ack))
			wake_up(&cx->mb_cpu_waitq);
		if (sw2 & (cx->scb->apu2hpu_irq_ack | cx->scb->apu2epu_irq_ack))
			wake_up(&cx->mb_apu_waitq);
		if (sw2 & cx->scb->epu2hpu_irq_ack)
			wake_up(&cx->mb_epu_waitq);
		if (sw2 & cx->scb->hpu2epu_irq_ack)
			wake_up(&cx->mb_hpu_waitq);
	}

	if (sw1)
		hpu_cmd(cx, sw1);
	spin_unlock(&cx->dma_reg_lock);

	return (hw2 | sw1 | sw2) ? IRQ_HANDLED : IRQ_NONE;
}
