/*
    Vertical Blank Interval support functions
    Copyright (C) 2004-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 "ivtv-driver.h"
#include "ivtv-i2c.h"
#include "ivtv-ioctl.h"
#include "ivtv-queue.h"
#include "ivtv-vbi.h"

static void ivtv_set_vps(struct ivtv *itv, int enabled)
{
	struct v4l2_sliced_vbi_data data;

	if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT))
		return;
	data.id = V4L2_SLICED_VPS;
	data.field = 0;
	data.line = enabled ? 16 : 0;
	data.data[2] = itv->vbi.vps_payload.data[0];
	data.data[8] = itv->vbi.vps_payload.data[1];
	data.data[9] = itv->vbi.vps_payload.data[2];
	data.data[10] = itv->vbi.vps_payload.data[3];
	data.data[11] = itv->vbi.vps_payload.data[4];
	ivtv_saa7127(itv, VIDIOC_INT_S_VBI_DATA, &data);
}

static void ivtv_set_cc(struct ivtv *itv, int mode, const struct vbi_cc *cc)
{
	struct v4l2_sliced_vbi_data data;

	if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT))
		return;
	data.id = V4L2_SLICED_CAPTION_525;
	data.field = 0;
	data.line = (mode & 1) ? 21 : 0;
	data.data[0] = cc->odd[0];
	data.data[1] = cc->odd[1];
	ivtv_saa7127(itv, VIDIOC_INT_S_VBI_DATA, &data);
	data.field = 1;
	data.line = (mode & 2) ? 21 : 0;
	data.data[0] = cc->even[0];
	data.data[1] = cc->even[1];
	ivtv_saa7127(itv, VIDIOC_INT_S_VBI_DATA, &data);
}

static void ivtv_set_wss(struct ivtv *itv, int enabled, int mode)
{
	struct v4l2_sliced_vbi_data data;

	if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT))
		return;
	/* When using a 50 Hz system, always turn on the
	   wide screen signal with 4x3 ratio as the default.
	   Turning this signal on and off can confuse certain
	   TVs. As far as I can tell there is no reason not to
	   transmit this signal. */
	if ((itv->std & V4L2_STD_625_50) && !enabled) {
		enabled = 1;
		mode = 0x08;  /* 4x3 full format */
	}
	data.id = V4L2_SLICED_WSS_625;
	data.field = 0;
	data.line = enabled ? 23 : 0;
	data.data[0] = mode & 0xff;
	data.data[1] = (mode >> 8) & 0xff;
	ivtv_saa7127(itv, VIDIOC_INT_S_VBI_DATA, &data);
}

static int odd_parity(u8 c)
{
	c ^= (c >> 4);
	c ^= (c >> 2);
	c ^= (c >> 1);

	return c & 1;
}

void ivtv_write_vbi(struct ivtv *itv, const struct v4l2_sliced_vbi_data *sliced, size_t cnt)
{
	struct vbi_info *vi = &itv->vbi;
	struct vbi_cc cc = { .odd = { 0x80, 0x80 }, .even = { 0x80, 0x80 } };
	int found_cc = 0;
	size_t i;

	for (i = 0; i < cnt; i++) {
		const struct v4l2_sliced_vbi_data *d = sliced + i;

		if (d->id == V4L2_SLICED_CAPTION_525 && d->line == 21) {
			if (d->field) {
				cc.even[0] = d->data[0];
				cc.even[1] = d->data[1];
			} else {
				cc.odd[0] = d->data[0];
				cc.odd[1] = d->data[1];
			}
			found_cc = 1;
		}
		else if (d->id == V4L2_SLICED_VPS && d->line == 16 && d->field == 0) {
			struct vbi_vps vps;

			vps.data[0] = d->data[2];
			vps.data[1] = d->data[8];
			vps.data[2] = d->data[9];
			vps.data[3] = d->data[10];
			vps.data[4] = d->data[11];
			if (memcmp(&vps, &vi->vps_payload, sizeof(vps))) {
				vi->vps_payload = vps;
				set_bit(IVTV_F_I_UPDATE_VPS, &itv->i_flags);
			}
		}
		else if (d->id == V4L2_SLICED_WSS_625 && d->line == 23 && d->field == 0) {
			int wss = d->data[0] | d->data[1] << 8;

			if (vi->wss_payload != wss) {
				vi->wss_payload = wss;
				set_bit(IVTV_F_I_UPDATE_WSS, &itv->i_flags);
			}
		}
	}
	if (found_cc && vi->cc_payload_idx < sizeof(vi->cc_payload)) {
		vi->cc_payload[vi->cc_payload_idx++] = cc;
		set_bit(IVTV_F_I_UPDATE_CC, &itv->i_flags);
	}
}

static void copy_vbi_data(struct ivtv *itv, int lines, u32 pts_stamp)
{
	int line = 0;
	int i;
	u32 linemask[2] = { 0, 0 };
	unsigned short size;
	static const u8 mpeg_hdr_data[] = {
		0x00, 0x00, 0x01, 0xba, 0x44, 0x00, 0x0c, 0x66,
		0x24, 0x01, 0x01, 0xd1, 0xd3, 0xfa, 0xff, 0xff,
		0x00, 0x00, 0x01, 0xbd, 0x00, 0x1a, 0x84, 0x80,
		0x07, 0x21, 0x00, 0x5d, 0x63, 0xa7, 0xff, 0xff
	};
	const int sd = sizeof(mpeg_hdr_data);	/* start of vbi data */
	int idx = itv->vbi.frame % IVTV_VBI_FRAMES;
	u8 *dst = &itv->vbi.sliced_mpeg_data[idx][0];

	for (i = 0; i < lines; i++) {
		int f, l;

		if (itv->vbi.sliced_data[i].id == 0)
			continue;

		l = itv->vbi.sliced_data[i].line - 6;
		f = itv->vbi.sliced_data[i].field;
		if (f)
			l += 18;
		if (l < 32)
			linemask[0] |= (1 << l);
		else
			linemask[1] |= (1 << (l - 32));
		dst[sd + 12 + line * 43] = service2vbi(itv->vbi.sliced_data[i].id);
		memcpy(dst + sd + 12 + line * 43 + 1, itv->vbi.sliced_data[i].data, 42);
		line++;
	}
	memcpy(dst, mpeg_hdr_data, sizeof(mpeg_hdr_data));
	if (line == 36) {
		/* All lines are used, so there is no space for the linemask
		   (the max size of the VBI data is 36 * 43 + 4 bytes).
		   So in this case we use the magic number 'ITV0'. */
		memcpy(dst + sd, "ITV0", 4);
		memcpy(dst + sd + 4, dst + sd + 12, line * 43);
		size = 4 + ((43 * line + 3) & ~3);
	} else {
		memcpy(dst + sd, "itv0", 4);
		memcpy(dst + sd + 4, &linemask[0], 8);
		size = 12 + ((43 * line + 3) & ~3);
	}
	dst[4+16] = (size + 10) >> 8;
	dst[5+16] = (size + 10) & 0xff;
	dst[9+16] = 0x21 | ((pts_stamp >> 29) & 0x6);
	dst[10+16] = (pts_stamp >> 22) & 0xff;
	dst[11+16] = 1 | ((pts_stamp >> 14) & 0xff);
	dst[12+16] = (pts_stamp >> 7) & 0xff;
	dst[13+16] = 1 | ((pts_stamp & 0x7f) << 1);
	itv->vbi.sliced_mpeg_size[idx] = sd + size;
}

static int ivtv_convert_ivtv_vbi(struct ivtv *itv, u8 *p)
{
	u32 linemask[2];
	int i, l, id2;
	int line = 0;

	if (!memcmp(p, "itv0", 4)) {
		memcpy(linemask, p + 4, 8);
		p += 12;
	} else if (!memcmp(p, "ITV0", 4)) {
		linemask[0] = 0xffffffff;
		linemask[1] = 0xf;
		p += 4;
	} else {
		/* unknown VBI data, convert to empty VBI frame */
		linemask[0] = linemask[1] = 0;
	}
	for (i = 0; i < 36; i++) {
		int err = 0;

		if (i < 32 && !(linemask[0] & (1 << i)))
			continue;
		if (i >= 32 && !(linemask[1] & (1 << (i - 32))))
			continue;
		id2 = *p & 0xf;
		switch (id2) {
		case IVTV_SLICED_TYPE_TELETEXT_B:
			id2 = V4L2_SLICED_TELETEXT_B;
			break;
		case IVTV_SLICED_TYPE_CAPTION_525:
			id2 = V4L2_SLICED_CAPTION_525;
			err = !odd_parity(p[1]) || !odd_parity(p[2]);
			break;
		case IVTV_SLICED_TYPE_VPS:
			id2 = V4L2_SLICED_VPS;
			break;
		case IVTV_SLICED_TYPE_WSS_625:
			id2 = V4L2_SLICED_WSS_625;
			break;
		default:
			id2 = 0;
			break;
		}
		if (err == 0) {
			l = (i < 18) ? i + 6 : i - 18 + 6;
			itv->vbi.sliced_dec_data[line].line = l;
			itv->vbi.sliced_dec_data[line].field = i >= 18;
			itv->vbi.sliced_dec_data[line].id = id2;
			memcpy(itv->vbi.sliced_dec_data[line].data, p + 1, 42);
			line++;
		}
		p += 43;
	}
	while (line < 36) {
		itv->vbi.sliced_dec_data[line].id = 0;
		itv->vbi.sliced_dec_data[line].line = 0;
		itv->vbi.sliced_dec_data[line].field = 0;
		line++;
	}
	return line * sizeof(itv->vbi.sliced_dec_data[0]);
}

/* Compress raw VBI format, removes leading SAV codes and surplus space after the
   field.
   Returns new compressed size. */
static u32 compress_raw_buf(struct ivtv *itv, u8 *buf, u32 size)
{
	u32 line_size = itv->vbi.raw_decoder_line_size;
	u32 lines = itv->vbi.count;
	u8 sav1 = itv->vbi.raw_decoder_sav_odd_field;
	u8 sav2 = itv->vbi.raw_decoder_sav_even_field;
	u8 *q = buf;
	u8 *p;
	int i;

	for (i = 0; i < lines; i++) {
		p = buf + i * line_size;

		/* Look for SAV code */
		if (p[0] != 0xff || p[1] || p[2] || (p[3] != sav1 && p[3] != sav2)) {
			break;
		}
		memcpy(q, p + 4, line_size - 4);
		q += line_size - 4;
	}
	return lines * (line_size - 4);
}


/* Compressed VBI format, all found sliced blocks put next to one another
   Returns new compressed size */
static u32 compress_sliced_buf(struct ivtv *itv, u32 line, u8 *buf, u32 size, u8 sav)
{
	u32 line_size = itv->vbi.sliced_decoder_line_size;
	struct v4l2_decode_vbi_line vbi;
	int i;

	/* find the first valid line */
	for (i = 0; i < size; i++, buf++) {
		if (buf[0] == 0xff && !buf[1] && !buf[2] && buf[3] == sav)
			break;
	}

	size -= i;
	if (size < line_size) {
		return line;
	}
	for (i = 0; i < size / line_size; i++) {
		u8 *p = buf + i * line_size;

		/* Look for SAV code  */
		if (p[0] != 0xff || p[1] || p[2] || p[3] != sav) {
			continue;
		}
		vbi.p = p + 4;
		itv->video_dec_func(itv, VIDIOC_INT_DECODE_VBI_LINE, &vbi);
		if (vbi.type) {
			itv->vbi.sliced_data[line].id = vbi.type;
			itv->vbi.sliced_data[line].field = vbi.is_second_field;
			itv->vbi.sliced_data[line].line = vbi.line;
			memcpy(itv->vbi.sliced_data[line].data, vbi.p, 42);
			line++;
		}
	}
	return line;
}

void ivtv_process_vbi_data(struct ivtv *itv, struct ivtv_buffer *buf,
			   u64 pts_stamp, int streamtype)
{
	u8 *p = (u8 *) buf->buf;
	u32 size = buf->bytesused;
	int y;

	/* Raw VBI data */
	if (streamtype == IVTV_ENC_STREAM_TYPE_VBI && itv->vbi.sliced_in->service_set == 0) {
		u8 type;

		ivtv_buf_swap(buf);

		type = p[3];

		size = buf->bytesused = compress_raw_buf(itv, p, size);

		/* second field of the frame? */
		if (type == itv->vbi.raw_decoder_sav_even_field) {
			/* Dirty hack needed for backwards
			   compatibility of old VBI software. */
			p += size - 4;
			memcpy(p, &itv->vbi.frame, 4);
			itv->vbi.frame++;
		}
		return;
	}

	/* Sliced VBI data with data insertion */
	if (streamtype == IVTV_ENC_STREAM_TYPE_VBI) {
		int lines;

		ivtv_buf_swap(buf);

		/* first field */
		lines = compress_sliced_buf(itv, 0, p, size / 2,
			itv->vbi.sliced_decoder_sav_odd_field);
		/* second field */
		/* experimentation shows that the second half does not always begin
		   at the exact address. So start a bit earlier (hence 32). */
		lines = compress_sliced_buf(itv, lines, p + size / 2 - 32, size / 2 + 32,
			itv->vbi.sliced_decoder_sav_even_field);
		/* always return at least one empty line */
		if (lines == 0) {
			itv->vbi.sliced_data[0].id = 0;
			itv->vbi.sliced_data[0].line = 0;
			itv->vbi.sliced_data[0].field = 0;
			lines = 1;
		}
		buf->bytesused = size = lines * sizeof(itv->vbi.sliced_data[0]);
		memcpy(p, &itv->vbi.sliced_data[0], size);

		if (itv->vbi.insert_mpeg) {
			copy_vbi_data(itv, lines, pts_stamp);
		}
		itv->vbi.frame++;
		return;
	}

	/* Sliced VBI re-inserted from an MPEG stream */
	if (streamtype == IVTV_DEC_STREAM_TYPE_VBI) {
		/* If the size is not 4-byte aligned, then the starting address
		   for the swapping is also shifted. After swapping the data the
		   real start address of the VBI data is exactly 4 bytes after the
		   original start. It's a bit fiddly but it works like a charm.
		   Non-4-byte alignment happens when an lseek is done on the input
		   mpeg file to a non-4-byte aligned position. So on arrival here
		   the VBI data is also non-4-byte aligned. */
		int offset = size & 3;
		int cnt;

		if (offset) {
			p += 4 - offset;
		}
		/* Swap Buffer */
		for (y = 0; y < size; y += 4) {
		       swab32s((u32 *)(p + y));
		}

		cnt = ivtv_convert_ivtv_vbi(itv, p + offset);
		memcpy(buf->buf, itv->vbi.sliced_dec_data, cnt);
		buf->bytesused = cnt;

		ivtv_write_vbi(itv, itv->vbi.sliced_dec_data,
			       cnt / sizeof(itv->vbi.sliced_dec_data[0]));
		return;
	}
}

void ivtv_disable_cc(struct ivtv *itv)
{
	struct vbi_cc cc = { .odd = { 0x80, 0x80 }, .even = { 0x80, 0x80 } };

	clear_bit(IVTV_F_I_UPDATE_CC, &itv->i_flags);
	ivtv_set_cc(itv, 0, &cc);
	itv->vbi.cc_payload_idx = 0;
}


void ivtv_vbi_work_handler(struct ivtv *itv)
{
	struct vbi_info *vi = &itv->vbi;
	struct v4l2_sliced_vbi_data data;
	struct vbi_cc cc = { .odd = { 0x80, 0x80 }, .even = { 0x80, 0x80 } };

	/* Lock */
	if (itv->output_mode == OUT_PASSTHROUGH) {
		if (itv->is_50hz) {
			data.id = V4L2_SLICED_WSS_625;
			data.field = 0;

			if (itv->video_dec_func(itv, VIDIOC_INT_G_VBI_DATA, &data) == 0) {
				ivtv_set_wss(itv, 1, data.data[0] & 0xf);
				vi->wss_missing_cnt = 0;
			} else if (vi->wss_missing_cnt == 4) {
				ivtv_set_wss(itv, 1, 0x8);  /* 4x3 full format */
			} else {
				vi->wss_missing_cnt++;
			}
		}
		else {
			int mode = 0;

			data.id = V4L2_SLICED_CAPTION_525;
			data.field = 0;
			if (itv->video_dec_func(itv, VIDIOC_INT_G_VBI_DATA, &data) == 0) {
				mode |= 1;
				cc.odd[0] = data.data[0];
				cc.odd[1] = data.data[1];
			}
			data.field = 1;
			if (itv->video_dec_func(itv, VIDIOC_INT_G_VBI_DATA, &data) == 0) {
				mode |= 2;
				cc.even[0] = data.data[0];
				cc.even[1] = data.data[1];
			}
			if (mode) {
				vi->cc_missing_cnt = 0;
				ivtv_set_cc(itv, mode, &cc);
			} else if (vi->cc_missing_cnt == 4) {
				ivtv_set_cc(itv, 0, &cc);
			} else {
				vi->cc_missing_cnt++;
			}
		}
		return;
	}

	if (test_and_clear_bit(IVTV_F_I_UPDATE_WSS, &itv->i_flags)) {
		ivtv_set_wss(itv, 1, vi->wss_payload & 0xf);
	}

	if (test_bit(IVTV_F_I_UPDATE_CC, &itv->i_flags)) {
		if (vi->cc_payload_idx == 0) {
			clear_bit(IVTV_F_I_UPDATE_CC, &itv->i_flags);
			ivtv_set_cc(itv, 3, &cc);
		}
		while (vi->cc_payload_idx) {
			cc = vi->cc_payload[0];

			memcpy(vi->cc_payload, vi->cc_payload + 1,
					sizeof(vi->cc_payload) - sizeof(vi->cc_payload[0]));
			vi->cc_payload_idx--;
			if (vi->cc_payload_idx && cc.odd[0] == 0x80 && cc.odd[1] == 0x80)
				continue;

			ivtv_set_cc(itv, 3, &cc);
			break;
		}
	}

	if (test_and_clear_bit(IVTV_F_I_UPDATE_VPS, &itv->i_flags)) {
		ivtv_set_vps(itv, 1);
	}
}
