/*
 * Copyright (c) 2001 Jean-Fredric Clere, Nikolas Zimmermann, Georg Acher
 *		      Mark Cave-Ayland, Carlo E Prelz, Dick Streefland
 * Copyright (c) 2002, 2003 Tuukka Toivonen
 * Copyright (c) 2008 Erik Andrén
 * Copyright (c) 2008 Chia-I Wu
 *
 * 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
 *
 * P/N 861037:      Sensor HDCS1000        ASIC STV0600
 * P/N 861050-0010: Sensor HDCS1000        ASIC STV0600
 * P/N 861050-0020: Sensor Photobit PB100  ASIC STV0600-1 - QuickCam Express
 * P/N 861055:      Sensor ST VV6410       ASIC STV0610   - LEGO cam
 * P/N 861075-0040: Sensor HDCS1000        ASIC
 * P/N 961179-0700: Sensor ST VV6410       ASIC STV0602   - Dexxa WebCam USB
 * P/N 861040-0000: Sensor ST VV6410       ASIC STV0610   - QuickCam Web
 */

#include "stv06xx_hdcs.h"

enum hdcs_power_state {
	HDCS_STATE_SLEEP,
	HDCS_STATE_IDLE,
	HDCS_STATE_RUN
};

/* no lock? */
struct hdcs {
	enum hdcs_power_state state;
	int w, h;

	/* visible area of the sensor array */
	struct {
		int left, top;
		int width, height;
		int border;
	} array;

	struct {
		/* Column timing overhead */
		u8 cto;
		/* Column processing overhead */
		u8 cpo;
		/* Row sample period constant */
		u16 rs;
		/* Exposure reset duration */
		u16 er;
	} exp;

	int psmp;
};

static int hdcs_reg_write_seq(struct sd *sd, u8 reg, u8 *vals, u8 len)
{
	u8 regs[I2C_MAX_BYTES * 2];
	int i;

	if (unlikely((len <= 0) || (len >= I2C_MAX_BYTES) ||
		     (reg + len > 0xff)))
		return -EINVAL;

	for (i = 0; i < len; i++, reg++) {
		regs[2*i] = reg;
		regs[2*i+1] = vals[i];
	}

	return stv06xx_write_sensor_bytes(sd, regs, len);
}

static int hdcs_set_state(struct sd *sd, enum hdcs_power_state state)
{
	struct hdcs *hdcs = sd->sensor_priv;
	u8 val;
	int ret;

	if (hdcs->state == state)
		return 0;

	/* we need to go idle before running or sleeping */
	if (hdcs->state != HDCS_STATE_IDLE) {
		ret = stv06xx_write_sensor(sd, HDCS_REG_CONTROL(sd), 0);
		if (ret)
			return ret;
	}

	hdcs->state = HDCS_STATE_IDLE;

	if (state == HDCS_STATE_IDLE)
		return 0;

	switch (state) {
	case HDCS_STATE_SLEEP:
		val = HDCS_SLEEP_MODE;
		break;

	case HDCS_STATE_RUN:
		val = HDCS_RUN_ENABLE;
		break;

	default:
		return -EINVAL;
	}

	ret = stv06xx_write_sensor(sd, HDCS_REG_CONTROL(sd), val);
	if (ret < 0)
		hdcs->state = state;

	return ret;
}

static int hdcs_reset(struct sd *sd)
{
	struct hdcs *hdcs = sd->sensor_priv;
	int err;

	err = stv06xx_write_sensor(sd, HDCS_REG_CONTROL(sd), 1);
	if (err < 0)
		return err;

	err = stv06xx_write_sensor(sd, HDCS_REG_CONTROL(sd), 0);
	if (err < 0)
		hdcs->state = HDCS_STATE_IDLE;

	return err;
}

static int hdcs_get_exposure(struct gspca_dev *gspca_dev, __s32 *val)
{
	struct sd *sd = (struct sd *) gspca_dev;
	struct hdcs *hdcs = sd->sensor_priv;

	/* Column time period */
	int ct;
	/* Column processing period */
	int cp;
	/* Row processing period */
	int rp;
	int cycles;
	int err;
	int rowexp;
	u16 data[2];

	err = stv06xx_read_sensor(sd, HDCS_ROWEXPL, &data[0]);
	if (err < 0)
		return err;

	err = stv06xx_read_sensor(sd, HDCS_ROWEXPH, &data[1]);
	if (err < 0)
		return err;

	rowexp = (data[1] << 8) | data[0];

	ct = hdcs->exp.cto + hdcs->psmp + (HDCS_ADC_START_SIG_DUR + 2);
	cp = hdcs->exp.cto + (hdcs->w * ct / 2);
	rp = hdcs->exp.rs + cp;

	cycles = rp * rowexp;
	*val = cycles / HDCS_CLK_FREQ_MHZ;
	PDEBUG(D_V4L2, "Read exposure %d", *val);
	return 0;
}

static int hdcs_set_exposure(struct gspca_dev *gspca_dev, __s32 val)
{
	struct sd *sd = (struct sd *) gspca_dev;
	struct hdcs *hdcs = sd->sensor_priv;
	int rowexp, srowexp;
	int max_srowexp;
	/* Column time period */
	int ct;
	/* Column processing period */
	int cp;
	/* Row processing period */
	int rp;
	/* Minimum number of column timing periods
	   within the column processing period */
	int mnct;
	int cycles, err;
	u8 exp[4];

	cycles = val * HDCS_CLK_FREQ_MHZ;

	ct = hdcs->exp.cto + hdcs->psmp + (HDCS_ADC_START_SIG_DUR + 2);
	cp = hdcs->exp.cto + (hdcs->w * ct / 2);

	/* the cycles one row takes */
	rp = hdcs->exp.rs + cp;

	rowexp = cycles / rp;

	/* the remaining cycles */
	cycles -= rowexp * rp;

	/* calculate sub-row exposure */
	if (IS_1020(sd)) {
		/* see HDCS-1020 datasheet 3.5.6.4, p. 63 */
		srowexp = hdcs->w - (cycles + hdcs->exp.er + 13) / ct;

		mnct = (hdcs->exp.er + 12 + ct - 1) / ct;
		max_srowexp = hdcs->w - mnct;
	} else {
		/* see HDCS-1000 datasheet 3.4.5.5, p. 61 */
		srowexp = cp - hdcs->exp.er - 6 - cycles;

		mnct = (hdcs->exp.er + 5 + ct - 1) / ct;
		max_srowexp = cp - mnct * ct - 1;
	}

	if (srowexp < 0)
		srowexp = 0;
	else if (srowexp > max_srowexp)
		srowexp = max_srowexp;

	if (IS_1020(sd)) {
		exp[0] = rowexp & 0xff;
		exp[1] = rowexp >> 8;
		exp[2] = (srowexp >> 2) & 0xff;
		/* this clears exposure error flag */
		exp[3] = 0x1;
		err = hdcs_reg_write_seq(sd, HDCS_ROWEXPL, exp, 4);
	} else {
		exp[0] = rowexp & 0xff;
		exp[1] = rowexp >> 8;
		exp[2] = srowexp & 0xff;
		exp[3] = srowexp >> 8;
		err = hdcs_reg_write_seq(sd, HDCS_ROWEXPL, exp, 4);
		if (err < 0)
			return err;

		/* clear exposure error flag */
		err = stv06xx_write_sensor(sd,
		     HDCS_STATUS, BIT(4));
	}
	PDEBUG(D_V4L2, "Writing exposure %d, rowexp %d, srowexp %d",
	       val, rowexp, srowexp);
	return err;
}

static int hdcs_set_gains(struct sd *sd, u8 r, u8 g, u8 b)
{
	u8 gains[4];

	/* the voltage gain Av = (1 + 19 * val / 127) * (1 + bit7) */
	if (r > 127)
		r = 0x80 | (r / 2);
	if (g > 127)
		g = 0x80 | (g / 2);
	if (b > 127)
		b = 0x80 | (b / 2);

	gains[0] = g;
	gains[1] = r;
	gains[2] = b;
	gains[3] = g;

	return hdcs_reg_write_seq(sd, HDCS_ERECPGA, gains, 4);
}

static int hdcs_get_gain(struct gspca_dev *gspca_dev, __s32 *val)
{
	struct sd *sd = (struct sd *) gspca_dev;
	int err;
	u16 data;

	err = stv06xx_read_sensor(sd, HDCS_ERECPGA, &data);

	/* Bit 7 doubles the gain */
	if (data & 0x80)
		*val = (data & 0x7f) * 2;
	else
		*val = data;

	PDEBUG(D_V4L2, "Read gain %d", *val);
	return err;
}

static int hdcs_set_gain(struct gspca_dev *gspca_dev, __s32 val)
{
	PDEBUG(D_V4L2, "Writing gain %d", val);
	return hdcs_set_gains((struct sd *) gspca_dev,
			       val & 0xff, val & 0xff, val & 0xff);
}

static int hdcs_set_size(struct sd *sd,
		unsigned int width, unsigned int height)
{
	struct hdcs *hdcs = sd->sensor_priv;
	u8 win[4];
	unsigned int x, y;
	int err;

	/* must be multiple of 4 */
	width = (width + 3) & ~0x3;
	height = (height + 3) & ~0x3;

	if (width > hdcs->array.width)
		width = hdcs->array.width;

	if (IS_1020(sd)) {
		/* the borders are also invalid */
		if (height + 2 * hdcs->array.border + HDCS_1020_BOTTOM_Y_SKIP
				  > hdcs->array.height)
			height = hdcs->array.height - 2 * hdcs->array.border -
				HDCS_1020_BOTTOM_Y_SKIP;

		y = (hdcs->array.height - HDCS_1020_BOTTOM_Y_SKIP - height) / 2
				+ hdcs->array.top;
	} else {
		if (height > hdcs->array.height)
			height = hdcs->array.height;

		y = hdcs->array.top + (hdcs->array.height - height) / 2;
	}

	x = hdcs->array.left + (hdcs->array.width - width) / 2;

	win[0] = y / 4;
	win[1] = x / 4;
	win[2] = (y + height) / 4 - 1;
	win[3] = (x + width) / 4 - 1;

	err = hdcs_reg_write_seq(sd, HDCS_FWROW, win, 4);
	if (err < 0)
		return err;

	/* Update the current width and height */
	hdcs->w = width;
	hdcs->h = height;
	return err;
}

static int hdcs_probe_1x00(struct sd *sd)
{
	struct hdcs *hdcs;
	u16 sensor;
	int ret;

	ret = stv06xx_read_sensor(sd, HDCS_IDENT, &sensor);
	if (ret < 0 || sensor != 0x08)
		return -ENODEV;

	info("HDCS-1000/1100 sensor detected");

	sd->gspca_dev.cam.cam_mode = stv06xx_sensor_hdcs1x00.modes;
	sd->gspca_dev.cam.nmodes = stv06xx_sensor_hdcs1x00.nmodes;
	sd->desc.ctrls = stv06xx_sensor_hdcs1x00.ctrls;
	sd->desc.nctrls = stv06xx_sensor_hdcs1x00.nctrls;

	hdcs = kmalloc(sizeof(struct hdcs), GFP_KERNEL);
	if (!hdcs)
		return -ENOMEM;

	hdcs->array.left = 8;
	hdcs->array.top = 8;
	hdcs->array.width = HDCS_1X00_DEF_WIDTH;
	hdcs->array.height = HDCS_1X00_DEF_HEIGHT;
	hdcs->array.border = 4;

	hdcs->exp.cto = 4;
	hdcs->exp.cpo = 2;
	hdcs->exp.rs = 186;
	hdcs->exp.er = 100;

	/*
	 * Frame rate on HDCS-1000 0x46D:0x840 depends on PSMP:
	 *  4 = doesn't work at all
	 *  5 = 7.8 fps,
	 *  6 = 6.9 fps,
	 *  8 = 6.3 fps,
	 * 10 = 5.5 fps,
	 * 15 = 4.4 fps,
	 * 31 = 2.8 fps
	 *
	 * Frame rate on HDCS-1000 0x46D:0x870 depends on PSMP:
	 * 15 = doesn't work at all
	 * 18 = doesn't work at all
	 * 19 = 7.3 fps
	 * 20 = 7.4 fps
	 * 21 = 7.4 fps
	 * 22 = 7.4 fps
	 * 24 = 6.3 fps
	 * 30 = 5.4 fps
	 */
	hdcs->psmp = IS_870(sd) ? 20 : 5;

	sd->sensor_priv = hdcs;

	return 0;
}

static int hdcs_probe_1020(struct sd *sd)
{
	struct hdcs *hdcs;
	u16 sensor;
	int ret;

	ret = stv06xx_read_sensor(sd, HDCS_IDENT, &sensor);
	if (ret < 0 || sensor != 0x10)
		return -ENODEV;

	info("HDCS-1020 sensor detected");

	sd->gspca_dev.cam.cam_mode = stv06xx_sensor_hdcs1020.modes;
	sd->gspca_dev.cam.nmodes = stv06xx_sensor_hdcs1020.nmodes;
	sd->desc.ctrls = stv06xx_sensor_hdcs1020.ctrls;
	sd->desc.nctrls = stv06xx_sensor_hdcs1020.nctrls;

	hdcs = kmalloc(sizeof(struct hdcs), GFP_KERNEL);
	if (!hdcs)
		return -ENOMEM;

	/*
	 * From Andrey's test image: looks like HDCS-1020 upper-left
	 * visible pixel is at 24,8 (y maybe even smaller?) and lower-right
	 * visible pixel at 375,299 (x maybe even larger?)
	 */
	hdcs->array.left = 24;
	hdcs->array.top  = 4;
	hdcs->array.width = HDCS_1020_DEF_WIDTH;
	hdcs->array.height = 304;
	hdcs->array.border = 4;

	hdcs->psmp = 6;

	hdcs->exp.cto = 3;
	hdcs->exp.cpo = 3;
	hdcs->exp.rs = 155;
	hdcs->exp.er = 96;

	sd->sensor_priv = hdcs;

	return 0;
}

static int hdcs_start(struct sd *sd)
{
	PDEBUG(D_STREAM, "Starting stream");

	return hdcs_set_state(sd, HDCS_STATE_RUN);
}

static int hdcs_stop(struct sd *sd)
{
	PDEBUG(D_STREAM, "Halting stream");

	return hdcs_set_state(sd, HDCS_STATE_SLEEP);
}

static void hdcs_disconnect(struct sd *sd)
{
	PDEBUG(D_PROBE, "Disconnecting the sensor");
	kfree(sd->sensor_priv);
}

static int hdcs_init(struct sd *sd)
{
	struct hdcs *hdcs = sd->sensor_priv;
	int i, err = 0;

	/* Set the STV0602AA in STV0600 emulation mode */
	if (IS_870(sd))
		stv06xx_write_bridge(sd, STV_STV0600_EMULATION, 1);

	/* Execute the bridge init */
	for (i = 0; i < ARRAY_SIZE(stv_bridge_init) && !err; i++) {
		err = stv06xx_write_bridge(sd, stv_bridge_init[i][0],
					   stv_bridge_init[i][1]);
	}
	if (err < 0)
		return err;

	/* sensor soft reset */
	hdcs_reset(sd);

	/* Execute the sensor init */
	for (i = 0; i < ARRAY_SIZE(stv_sensor_init) && !err; i++) {
		err = stv06xx_write_sensor(sd, stv_sensor_init[i][0],
					     stv_sensor_init[i][1]);
	}
	if (err < 0)
		return err;

	/* Enable continous frame capture, bit 2: stop when frame complete */
	err = stv06xx_write_sensor(sd, HDCS_REG_CONFIG(sd), BIT(3));
	if (err < 0)
		return err;

	/* Set PGA sample duration
	(was 0x7E for IS_870, but caused slow framerate with HDCS-1020) */
	if (IS_1020(sd))
		err = stv06xx_write_sensor(sd, HDCS_TCTRL,
				(HDCS_ADC_START_SIG_DUR << 6) | hdcs->psmp);
	else
		err = stv06xx_write_sensor(sd, HDCS_TCTRL,
				(HDCS_ADC_START_SIG_DUR << 5) | hdcs->psmp);
	if (err < 0)
		return err;

	err = hdcs_set_gains(sd, HDCS_DEFAULT_GAIN, HDCS_DEFAULT_GAIN,
			     HDCS_DEFAULT_GAIN);
	if (err < 0)
		return err;

	err = hdcs_set_exposure(&sd->gspca_dev, HDCS_DEFAULT_EXPOSURE);
	if (err < 0)
		return err;

	err = hdcs_set_size(sd, hdcs->array.width, hdcs->array.height);
	return err;
}

static int hdcs_dump(struct sd *sd)
{
	u16 reg, val;

	info("Dumping sensor registers:");

	for (reg = HDCS_IDENT; reg <= HDCS_ROWEXPH; reg++) {
		stv06xx_read_sensor(sd, reg, &val);
		info("reg 0x%02x = 0x%02x", reg, val);
	}
	return 0;
}
