/*
 * Sony CXD2820R demodulator driver
 *
 * Copyright (C) 2010 Antti Palosaari <crope@iki.fi>
 *
 *    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.,
 *    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 */


#include "cxd2820r_priv.h"

int cxd2820r_set_frontend_c(struct dvb_frontend *fe,
	struct dvb_frontend_parameters *params)
{
	struct cxd2820r_priv *priv = fe->demodulator_priv;
	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
	int ret, i;
	u8 buf[2];
	u16 if_ctl;
	u64 num;
	struct reg_val_mask tab[] = {
		{ 0x00080, 0x01, 0xff },
		{ 0x00081, 0x05, 0xff },
		{ 0x00085, 0x07, 0xff },
		{ 0x00088, 0x01, 0xff },

		{ 0x00082, 0x20, 0x60 },
		{ 0x1016a, 0x48, 0xff },
		{ 0x100a5, 0x00, 0x01 },
		{ 0x10020, 0x06, 0x07 },
		{ 0x10059, 0x50, 0xff },
		{ 0x10087, 0x0c, 0x3c },
		{ 0x1008b, 0x07, 0xff },
		{ 0x1001f, priv->cfg.if_agc_polarity << 7, 0x80 },
		{ 0x10070, priv->cfg.ts_mode, 0xff },
	};

	dbg("%s: RF=%d SR=%d", __func__, c->frequency, c->symbol_rate);

	/* update GPIOs */
	ret = cxd2820r_gpio(fe);
	if (ret)
		goto error;

	/* program tuner */
	if (fe->ops.tuner_ops.set_params)
		fe->ops.tuner_ops.set_params(fe, params);

	if (priv->delivery_system !=  SYS_DVBC_ANNEX_AC) {
		for (i = 0; i < ARRAY_SIZE(tab); i++) {
			ret = cxd2820r_wr_reg_mask(priv, tab[i].reg,
				tab[i].val, tab[i].mask);
			if (ret)
				goto error;
		}
	}

	priv->delivery_system = SYS_DVBC_ANNEX_AC;
	priv->ber_running = 0; /* tune stops BER counter */

	num = priv->cfg.if_dvbc;
	num *= 0x4000;
	if_ctl = cxd2820r_div_u64_round_closest(num, 41000);
	buf[0] = (if_ctl >> 8) & 0x3f;
	buf[1] = (if_ctl >> 0) & 0xff;

	ret = cxd2820r_wr_regs(priv, 0x10042, buf, 2);
	if (ret)
		goto error;

	ret = cxd2820r_wr_reg(priv, 0x000ff, 0x08);
	if (ret)
		goto error;

	ret = cxd2820r_wr_reg(priv, 0x000fe, 0x01);
	if (ret)
		goto error;

	return ret;
error:
	dbg("%s: failed:%d", __func__, ret);
	return ret;
}

int cxd2820r_get_frontend_c(struct dvb_frontend *fe,
	struct dvb_frontend_parameters *p)
{
	struct cxd2820r_priv *priv = fe->demodulator_priv;
	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
	int ret;
	u8 buf[2];

	ret = cxd2820r_rd_regs(priv, 0x1001a, buf, 2);
	if (ret)
		goto error;

	c->symbol_rate = 2500 * ((buf[0] & 0x0f) << 8 | buf[1]);

	ret = cxd2820r_rd_reg(priv, 0x10019, &buf[0]);
	if (ret)
		goto error;

	switch ((buf[0] >> 0) & 0x03) {
	case 0:
		c->modulation = QAM_16;
		break;
	case 1:
		c->modulation = QAM_32;
		break;
	case 2:
		c->modulation = QAM_64;
		break;
	case 3:
		c->modulation = QAM_128;
		break;
	case 4:
		c->modulation = QAM_256;
		break;
	}

	switch ((buf[0] >> 7) & 0x01) {
	case 0:
		c->inversion = INVERSION_OFF;
		break;
	case 1:
		c->inversion = INVERSION_ON;
		break;
	}

	return ret;
error:
	dbg("%s: failed:%d", __func__, ret);
	return ret;
}

int cxd2820r_read_ber_c(struct dvb_frontend *fe, u32 *ber)
{
	struct cxd2820r_priv *priv = fe->demodulator_priv;
	int ret;
	u8 buf[3], start_ber = 0;
	*ber = 0;

	if (priv->ber_running) {
		ret = cxd2820r_rd_regs(priv, 0x10076, buf, sizeof(buf));
		if (ret)
			goto error;

		if ((buf[2] >> 7) & 0x01 || (buf[2] >> 4) & 0x01) {
			*ber = (buf[2] & 0x0f) << 16 | buf[1] << 8 | buf[0];
			start_ber = 1;
		}
	} else {
		priv->ber_running = 1;
		start_ber = 1;
	}

	if (start_ber) {
		/* (re)start BER */
		ret = cxd2820r_wr_reg(priv, 0x10079, 0x01);
		if (ret)
			goto error;
	}

	return ret;
error:
	dbg("%s: failed:%d", __func__, ret);
	return ret;
}

int cxd2820r_read_signal_strength_c(struct dvb_frontend *fe,
	u16 *strength)
{
	struct cxd2820r_priv *priv = fe->demodulator_priv;
	int ret;
	u8 buf[2];
	u16 tmp;

	ret = cxd2820r_rd_regs(priv, 0x10049, buf, sizeof(buf));
	if (ret)
		goto error;

	tmp = (buf[0] & 0x03) << 8 | buf[1];
	tmp = (~tmp & 0x03ff);

	if (tmp == 512)
		/* ~no signal */
		tmp = 0;
	else if (tmp > 350)
		tmp = 350;

	/* scale value to 0x0000-0xffff */
	*strength = tmp * 0xffff / (350-0);

	return ret;
error:
	dbg("%s: failed:%d", __func__, ret);
	return ret;
}

int cxd2820r_read_snr_c(struct dvb_frontend *fe, u16 *snr)
{
	struct cxd2820r_priv *priv = fe->demodulator_priv;
	int ret;
	u8 tmp;
	unsigned int A, B;
	/* report SNR in dB * 10 */

	ret = cxd2820r_rd_reg(priv, 0x10019, &tmp);
	if (ret)
		goto error;

	if (((tmp >> 0) & 0x03) % 2) {
		A = 875;
		B = 650;
	} else {
		A = 950;
		B = 760;
	}

	ret = cxd2820r_rd_reg(priv, 0x1004d, &tmp);
	if (ret)
		goto error;

	#define CXD2820R_LOG2_E_24 24204406 /* log2(e) << 24 */
	if (tmp)
		*snr = A * (intlog2(B / tmp) >> 5) / (CXD2820R_LOG2_E_24 >> 5)
			/ 10;
	else
		*snr = 0;

	return ret;
error:
	dbg("%s: failed:%d", __func__, ret);
	return ret;
}

int cxd2820r_read_ucblocks_c(struct dvb_frontend *fe, u32 *ucblocks)
{
	*ucblocks = 0;
	/* no way to read ? */
	return 0;
}

int cxd2820r_read_status_c(struct dvb_frontend *fe, fe_status_t *status)
{
	struct cxd2820r_priv *priv = fe->demodulator_priv;
	int ret;
	u8 buf[2];
	*status = 0;

	ret = cxd2820r_rd_regs(priv, 0x10088, buf, sizeof(buf));
	if (ret)
		goto error;

	if (((buf[0] >> 0) & 0x01) == 1) {
		*status |= FE_HAS_SIGNAL | FE_HAS_CARRIER |
			FE_HAS_VITERBI | FE_HAS_SYNC;

		if (((buf[1] >> 3) & 0x01) == 1) {
			*status |= FE_HAS_SIGNAL | FE_HAS_CARRIER |
				FE_HAS_VITERBI | FE_HAS_SYNC | FE_HAS_LOCK;
		}
	}

	dbg("%s: lock=%02x %02x", __func__, buf[0], buf[1]);

	return ret;
error:
	dbg("%s: failed:%d", __func__, ret);
	return ret;
}

int cxd2820r_init_c(struct dvb_frontend *fe)
{
	struct cxd2820r_priv *priv = fe->demodulator_priv;
	int ret;

	ret = cxd2820r_wr_reg(priv, 0x00085, 0x07);
	if (ret)
		goto error;

	return ret;
error:
	dbg("%s: failed:%d", __func__, ret);
	return ret;
}

int cxd2820r_sleep_c(struct dvb_frontend *fe)
{
	struct cxd2820r_priv *priv = fe->demodulator_priv;
	int ret, i;
	struct reg_val_mask tab[] = {
		{ 0x000ff, 0x1f, 0xff },
		{ 0x00085, 0x00, 0xff },
		{ 0x00088, 0x01, 0xff },
		{ 0x00081, 0x00, 0xff },
		{ 0x00080, 0x00, 0xff },
	};

	dbg("%s", __func__);

	priv->delivery_system = SYS_UNDEFINED;

	for (i = 0; i < ARRAY_SIZE(tab); i++) {
		ret = cxd2820r_wr_reg_mask(priv, tab[i].reg, tab[i].val,
			tab[i].mask);
		if (ret)
			goto error;
	}

	return ret;
error:
	dbg("%s: failed:%d", __func__, ret);
	return ret;
}

int cxd2820r_get_tune_settings_c(struct dvb_frontend *fe,
	struct dvb_frontend_tune_settings *s)
{
	s->min_delay_ms = 500;
	s->step_size = 0; /* no zigzag */
	s->max_drift = 0;

	return 0;
}

