/*
 * Driver for Sharp IX2505V (marked B0017) DVB-S silicon tuner
 *
 * Copyright (C) 2010 Malcolm Priestley
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License Version 2, as
 * published by the Free Software Foundation.
 *
 * 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.
 *
 */

#include <linux/module.h>
#include <linux/dvb/frontend.h>
#include <linux/slab.h>
#include <linux/types.h>

#include "ix2505v.h"

static int ix2505v_debug;
#define dprintk(level, args...) do { \
	if (ix2505v_debug & level) \
		printk(KERN_DEBUG "ix2505v: " args); \
} while (0)

#define deb_info(args...)  dprintk(0x01, args)
#define deb_i2c(args...)  dprintk(0x02, args)

struct ix2505v_state {
	struct i2c_adapter *i2c;
	const struct ix2505v_config *config;
	u32 frequency;
};

/*
 *  Data read format of the Sharp IX2505V B0017
 *
 *  byte1:   1   |   1   |   0   |   0   |   0   |  MA1  |  MA0  |  1
 *  byte2:  POR  |   FL  |  RD2  |  RD1  |  RD0  |   X   |   X   |  X
 *
 *  byte1 = address
 *  byte2;
 *	POR = Power on Reset (VCC H=<2.2v L=>2.2v)
 *	FL  = Phase Lock (H=lock L=unlock)
 *	RD0-2 = Reserved internal operations
 *
 * Only POR can be used to check the tuner is present
 *
 * Caution: after byte2 the I2C reverts to write mode continuing to read
 *          may corrupt tuning data.
 *
 */

static int ix2505v_read_status_reg(struct ix2505v_state *state)
{
	u8 addr = state->config->tuner_address;
	u8 b2[] = {0};
	int ret;

	struct i2c_msg msg[1] = {
		{ .addr = addr, .flags = I2C_M_RD, .buf = b2, .len = 1 }
	};

	ret = i2c_transfer(state->i2c, msg, 1);
	deb_i2c("Read %s ", __func__);

	return (ret == 1) ? (int) b2[0] : -1;
}

static int ix2505v_write(struct ix2505v_state *state, u8 buf[], u8 count)
{
	struct i2c_msg msg[1] = {
		{ .addr = state->config->tuner_address, .flags = 0,
		  .buf = buf, .len = count },
	};

	int ret;

	ret = i2c_transfer(state->i2c, msg, 1);

	if (ret != 1) {
		deb_i2c("%s: i2c error, ret=%d\n", __func__, ret);
		return -EIO;
	}

	return 0;
}

static void ix2505v_release(struct dvb_frontend *fe)
{
	struct ix2505v_state *state = fe->tuner_priv;

	fe->tuner_priv = NULL;
	kfree(state);

}

/*
 *  Data write format of the Sharp IX2505V B0017
 *
 *  byte1:   1   |   1   |   0   |   0   |   0   | 0(MA1)| 0(MA0)|  0
 *  byte2:   0   |  BG1  |  BG2  |   N8  |   N7  |   N6  |  N5   |  N4
 *  byte3:   N3  |   N2  |   N1  |   A5  |   A4  |   A3  |   A2  |  A1
 *  byte4:   1   | 1(C1) | 1(C0) |  PD5  |  PD4  |   TM  | 0(RTS)| 1(REF)
 *  byte5:   BA2 |   BA1 |  BA0  |  PSC  |  PD3  |PD2/TS2|DIV/TS1|PD0/TS0
 *
 *  byte1 = address
 *
 *  Write order
 *  1) byte1 -> byte2 -> byte3 -> byte4 -> byte5
 *  2) byte1 -> byte4 -> byte5 -> byte2 -> byte3
 *  3) byte1 -> byte2 -> byte3 -> byte4
 *  4) byte1 -> byte4 -> byte5 -> byte2
 *  5) byte1 -> byte2 -> byte3
 *  6) byte1 -> byte4 -> byte5
 *  7) byte1 -> byte2
 *  8) byte1 -> byte4
 *
 *  Recommended Setup
 *  1 -> 8 -> 6
 */

static int ix2505v_set_params(struct dvb_frontend *fe)
{
	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
	struct ix2505v_state *state = fe->tuner_priv;
	u32 frequency = c->frequency;
	u32 b_w  = (c->symbol_rate * 27) / 32000;
	u32 div_factor, N , A, x;
	int ret = 0, len;
	u8 gain, cc, ref, psc, local_osc, lpf;
	u8 data[4] = {0};

	if ((frequency < fe->ops.info.frequency_min_hz / kHz)
	||  (frequency > fe->ops.info.frequency_max_hz / kHz))
		return -EINVAL;

	if (state->config->tuner_gain)
		gain = (state->config->tuner_gain < 4)
			? state->config->tuner_gain : 0;
	else
		gain = 0x0;

	if (state->config->tuner_chargepump)
		cc = state->config->tuner_chargepump;
	else
		cc = 0x3;

	ref = 8; /* REF =1 */
	psc = 32; /* PSC = 0 */

	div_factor = (frequency * ref) / 40; /* local osc = 4Mhz */
	x = div_factor / psc;
	N = x/100;
	A = ((x - (N * 100)) * psc) / 100;

	data[0] = ((gain & 0x3) << 5) | (N >> 3);
	data[1] = (N << 5) | (A & 0x1f);
	data[2] = 0x81 | ((cc & 0x3) << 5) ; /*PD5,PD4 & TM = 0|C1,C0|REF=1*/

	deb_info("Frq=%d x=%d N=%d A=%d\n", frequency, x, N, A);

	if (frequency <= 1065000)
		local_osc = (6 << 5) | 2;
	else if (frequency <= 1170000)
		local_osc = (7 << 5) | 2;
	else if (frequency <= 1300000)
		local_osc = (1 << 5);
	else if (frequency <= 1445000)
		local_osc = (2 << 5);
	else if (frequency <= 1607000)
		local_osc = (3 << 5);
	else if (frequency <= 1778000)
		local_osc = (4 << 5);
	else if (frequency <= 1942000)
		local_osc = (5 << 5);
	else		/*frequency up to 2150000*/
		local_osc = (6 << 5);

	data[3] = local_osc; /* all other bits set 0 */

	if (b_w <= 10000)
		lpf = 0xc;
	else if (b_w <= 12000)
		lpf = 0x2;
	else if (b_w <= 14000)
		lpf = 0xa;
	else if (b_w <= 16000)
		lpf = 0x6;
	else if (b_w <= 18000)
		lpf = 0xe;
	else if (b_w <= 20000)
		lpf = 0x1;
	else if (b_w <= 22000)
		lpf = 0x9;
	else if (b_w <= 24000)
		lpf = 0x5;
	else if (b_w <= 26000)
		lpf = 0xd;
	else if (b_w <= 28000)
		lpf = 0x3;
		else
		lpf = 0xb;

	deb_info("Osc=%x b_w=%x lpf=%x\n", local_osc, b_w, lpf);
	deb_info("Data 0=[%4phN]\n", data);

	if (fe->ops.i2c_gate_ctrl)
		fe->ops.i2c_gate_ctrl(fe, 1);

	len = sizeof(data);
	ret |= ix2505v_write(state, data, len);

	data[2] |= 0x4; /* set TM = 1 other bits same */

	if (fe->ops.i2c_gate_ctrl)
		fe->ops.i2c_gate_ctrl(fe, 1);

	len = 1;
	ret |= ix2505v_write(state, &data[2], len); /* write byte 4 only */

	msleep(10);

	data[2] |= ((lpf >> 2) & 0x3) << 3; /* lpf */
	data[3] |= (lpf & 0x3) << 2;

	deb_info("Data 2=[%x%x]\n", data[2], data[3]);

	if (fe->ops.i2c_gate_ctrl)
		fe->ops.i2c_gate_ctrl(fe, 1);

	len = 2;
	ret |= ix2505v_write(state, &data[2], len); /* write byte 4 & 5 */

	if (state->config->min_delay_ms)
		msleep(state->config->min_delay_ms);

	state->frequency = frequency;

	return ret;
}

static int ix2505v_get_frequency(struct dvb_frontend *fe, u32 *frequency)
{
	struct ix2505v_state *state = fe->tuner_priv;

	*frequency = state->frequency;

	return 0;
}

static const struct dvb_tuner_ops ix2505v_tuner_ops = {
	.info = {
		.name = "Sharp IX2505V (B0017)",
		.frequency_min_hz =  950 * MHz,
		.frequency_max_hz = 2175 * MHz
	},
	.release = ix2505v_release,
	.set_params = ix2505v_set_params,
	.get_frequency = ix2505v_get_frequency,
};

struct dvb_frontend *ix2505v_attach(struct dvb_frontend *fe,
				    const struct ix2505v_config *config,
				    struct i2c_adapter *i2c)
{
	struct ix2505v_state *state = NULL;
	int ret;

	if (NULL == config) {
		deb_i2c("%s: no config ", __func__);
		goto error;
	}

	state = kzalloc(sizeof(struct ix2505v_state), GFP_KERNEL);
	if (NULL == state)
		return NULL;

	state->config = config;
	state->i2c = i2c;

	if (state->config->tuner_write_only) {
		if (fe->ops.i2c_gate_ctrl)
			fe->ops.i2c_gate_ctrl(fe, 1);

		ret = ix2505v_read_status_reg(state);

		if (ret & 0x80) {
			deb_i2c("%s: No IX2505V found\n", __func__);
			goto error;
		}

		if (fe->ops.i2c_gate_ctrl)
			fe->ops.i2c_gate_ctrl(fe, 0);
	}

	fe->tuner_priv = state;

	memcpy(&fe->ops.tuner_ops, &ix2505v_tuner_ops,
		sizeof(struct dvb_tuner_ops));
	deb_i2c("%s: initialization (%s addr=0x%02x) ok\n",
		__func__, fe->ops.tuner_ops.info.name, config->tuner_address);

	return fe;

error:
	kfree(state);
	return NULL;
}
EXPORT_SYMBOL(ix2505v_attach);

module_param_named(debug, ix2505v_debug, int, 0644);
MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off).");
MODULE_DESCRIPTION("DVB IX2505V tuner driver");
MODULE_AUTHOR("Malcolm Priestley");
MODULE_LICENSE("GPL");
