cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

tda827x.c (25870B)


      1// SPDX-License-Identifier: GPL-2.0-or-later
      2/*
      3 *
      4 * (c) 2005 Hartmut Hackmann
      5 * (c) 2007 Michael Krufky
      6 */
      7
      8#include <linux/module.h>
      9#include <linux/slab.h>
     10#include <asm/types.h>
     11#include <linux/dvb/frontend.h>
     12#include <linux/videodev2.h>
     13
     14#include "tda827x.h"
     15
     16static int debug;
     17module_param(debug, int, 0644);
     18MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off).");
     19
     20#define dprintk(args...) \
     21	do {					    \
     22		if (debug) printk(KERN_DEBUG "tda827x: " args); \
     23	} while (0)
     24
     25struct tda827x_priv {
     26	int i2c_addr;
     27	struct i2c_adapter *i2c_adap;
     28	struct tda827x_config *cfg;
     29
     30	unsigned int sgIF;
     31	unsigned char lpsel;
     32
     33	u32 frequency;
     34	u32 bandwidth;
     35};
     36
     37static void tda827x_set_std(struct dvb_frontend *fe,
     38			    struct analog_parameters *params)
     39{
     40	struct tda827x_priv *priv = fe->tuner_priv;
     41	char *mode;
     42
     43	priv->lpsel = 0;
     44	if (params->std & V4L2_STD_MN) {
     45		priv->sgIF = 92;
     46		priv->lpsel = 1;
     47		mode = "MN";
     48	} else if (params->std & V4L2_STD_B) {
     49		priv->sgIF = 108;
     50		mode = "B";
     51	} else if (params->std & V4L2_STD_GH) {
     52		priv->sgIF = 124;
     53		mode = "GH";
     54	} else if (params->std & V4L2_STD_PAL_I) {
     55		priv->sgIF = 124;
     56		mode = "I";
     57	} else if (params->std & V4L2_STD_DK) {
     58		priv->sgIF = 124;
     59		mode = "DK";
     60	} else if (params->std & V4L2_STD_SECAM_L) {
     61		priv->sgIF = 124;
     62		mode = "L";
     63	} else if (params->std & V4L2_STD_SECAM_LC) {
     64		priv->sgIF = 20;
     65		mode = "LC";
     66	} else {
     67		priv->sgIF = 124;
     68		mode = "xx";
     69	}
     70
     71	if (params->mode == V4L2_TUNER_RADIO) {
     72		priv->sgIF = 88; /* if frequency is 5.5 MHz */
     73		dprintk("setting tda827x to radio FM\n");
     74	} else
     75		dprintk("setting tda827x to system %s\n", mode);
     76}
     77
     78
     79/* ------------------------------------------------------------------ */
     80
     81struct tda827x_data {
     82	u32 lomax;
     83	u8  spd;
     84	u8  bs;
     85	u8  bp;
     86	u8  cp;
     87	u8  gc3;
     88	u8 div1p5;
     89};
     90
     91static const struct tda827x_data tda827x_table[] = {
     92	{ .lomax =  62000000, .spd = 3, .bs = 2, .bp = 0, .cp = 0, .gc3 = 3, .div1p5 = 1},
     93	{ .lomax =  66000000, .spd = 3, .bs = 3, .bp = 0, .cp = 0, .gc3 = 3, .div1p5 = 1},
     94	{ .lomax =  76000000, .spd = 3, .bs = 1, .bp = 0, .cp = 0, .gc3 = 3, .div1p5 = 0},
     95	{ .lomax =  84000000, .spd = 3, .bs = 2, .bp = 0, .cp = 0, .gc3 = 3, .div1p5 = 0},
     96	{ .lomax =  93000000, .spd = 3, .bs = 2, .bp = 0, .cp = 0, .gc3 = 1, .div1p5 = 0},
     97	{ .lomax =  98000000, .spd = 3, .bs = 3, .bp = 0, .cp = 0, .gc3 = 1, .div1p5 = 0},
     98	{ .lomax = 109000000, .spd = 3, .bs = 3, .bp = 1, .cp = 0, .gc3 = 1, .div1p5 = 0},
     99	{ .lomax = 123000000, .spd = 2, .bs = 2, .bp = 1, .cp = 0, .gc3 = 1, .div1p5 = 1},
    100	{ .lomax = 133000000, .spd = 2, .bs = 3, .bp = 1, .cp = 0, .gc3 = 1, .div1p5 = 1},
    101	{ .lomax = 151000000, .spd = 2, .bs = 1, .bp = 1, .cp = 0, .gc3 = 1, .div1p5 = 0},
    102	{ .lomax = 154000000, .spd = 2, .bs = 2, .bp = 1, .cp = 0, .gc3 = 1, .div1p5 = 0},
    103	{ .lomax = 181000000, .spd = 2, .bs = 2, .bp = 1, .cp = 0, .gc3 = 0, .div1p5 = 0},
    104	{ .lomax = 185000000, .spd = 2, .bs = 2, .bp = 2, .cp = 0, .gc3 = 1, .div1p5 = 0},
    105	{ .lomax = 217000000, .spd = 2, .bs = 3, .bp = 2, .cp = 0, .gc3 = 1, .div1p5 = 0},
    106	{ .lomax = 244000000, .spd = 1, .bs = 2, .bp = 2, .cp = 0, .gc3 = 1, .div1p5 = 1},
    107	{ .lomax = 265000000, .spd = 1, .bs = 3, .bp = 2, .cp = 0, .gc3 = 1, .div1p5 = 1},
    108	{ .lomax = 302000000, .spd = 1, .bs = 1, .bp = 2, .cp = 0, .gc3 = 1, .div1p5 = 0},
    109	{ .lomax = 324000000, .spd = 1, .bs = 2, .bp = 2, .cp = 0, .gc3 = 1, .div1p5 = 0},
    110	{ .lomax = 370000000, .spd = 1, .bs = 2, .bp = 3, .cp = 0, .gc3 = 1, .div1p5 = 0},
    111	{ .lomax = 454000000, .spd = 1, .bs = 3, .bp = 3, .cp = 0, .gc3 = 1, .div1p5 = 0},
    112	{ .lomax = 493000000, .spd = 0, .bs = 2, .bp = 3, .cp = 0, .gc3 = 1, .div1p5 = 1},
    113	{ .lomax = 530000000, .spd = 0, .bs = 3, .bp = 3, .cp = 0, .gc3 = 1, .div1p5 = 1},
    114	{ .lomax = 554000000, .spd = 0, .bs = 1, .bp = 3, .cp = 0, .gc3 = 1, .div1p5 = 0},
    115	{ .lomax = 604000000, .spd = 0, .bs = 1, .bp = 4, .cp = 0, .gc3 = 0, .div1p5 = 0},
    116	{ .lomax = 696000000, .spd = 0, .bs = 2, .bp = 4, .cp = 0, .gc3 = 0, .div1p5 = 0},
    117	{ .lomax = 740000000, .spd = 0, .bs = 2, .bp = 4, .cp = 1, .gc3 = 0, .div1p5 = 0},
    118	{ .lomax = 820000000, .spd = 0, .bs = 3, .bp = 4, .cp = 0, .gc3 = 0, .div1p5 = 0},
    119	{ .lomax = 865000000, .spd = 0, .bs = 3, .bp = 4, .cp = 1, .gc3 = 0, .div1p5 = 0},
    120	{ .lomax =         0, .spd = 0, .bs = 0, .bp = 0, .cp = 0, .gc3 = 0, .div1p5 = 0}
    121};
    122
    123static int tuner_transfer(struct dvb_frontend *fe,
    124			  struct i2c_msg *msg,
    125			  const int size)
    126{
    127	int rc;
    128	struct tda827x_priv *priv = fe->tuner_priv;
    129
    130	if (fe->ops.i2c_gate_ctrl)
    131		fe->ops.i2c_gate_ctrl(fe, 1);
    132	rc = i2c_transfer(priv->i2c_adap, msg, size);
    133	if (fe->ops.i2c_gate_ctrl)
    134		fe->ops.i2c_gate_ctrl(fe, 0);
    135
    136	if (rc >= 0 && rc != size)
    137		return -EIO;
    138
    139	return rc;
    140}
    141
    142static int tda827xo_set_params(struct dvb_frontend *fe)
    143{
    144	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
    145	struct tda827x_priv *priv = fe->tuner_priv;
    146	u8 buf[14];
    147	int rc;
    148
    149	struct i2c_msg msg = { .addr = priv->i2c_addr, .flags = 0,
    150			       .buf = buf, .len = sizeof(buf) };
    151	int i, tuner_freq, if_freq;
    152	u32 N;
    153
    154	dprintk("%s:\n", __func__);
    155	if (c->bandwidth_hz == 0) {
    156		if_freq = 5000000;
    157	} else if (c->bandwidth_hz <= 6000000) {
    158		if_freq = 4000000;
    159	} else if (c->bandwidth_hz <= 7000000) {
    160		if_freq = 4500000;
    161	} else {	/* 8 MHz */
    162		if_freq = 5000000;
    163	}
    164	tuner_freq = c->frequency;
    165
    166	i = 0;
    167	while (tda827x_table[i].lomax < tuner_freq) {
    168		if (tda827x_table[i + 1].lomax == 0)
    169			break;
    170		i++;
    171	}
    172
    173	tuner_freq += if_freq;
    174
    175	N = ((tuner_freq + 125000) / 250000) << (tda827x_table[i].spd + 2);
    176	buf[0] = 0;
    177	buf[1] = (N>>8) | 0x40;
    178	buf[2] = N & 0xff;
    179	buf[3] = 0;
    180	buf[4] = 0x52;
    181	buf[5] = (tda827x_table[i].spd << 6) + (tda827x_table[i].div1p5 << 5) +
    182				(tda827x_table[i].bs << 3) +
    183				tda827x_table[i].bp;
    184	buf[6] = (tda827x_table[i].gc3 << 4) + 0x8f;
    185	buf[7] = 0xbf;
    186	buf[8] = 0x2a;
    187	buf[9] = 0x05;
    188	buf[10] = 0xff;
    189	buf[11] = 0x00;
    190	buf[12] = 0x00;
    191	buf[13] = 0x40;
    192
    193	msg.len = 14;
    194	rc = tuner_transfer(fe, &msg, 1);
    195	if (rc < 0)
    196		goto err;
    197
    198	msleep(500);
    199	/* correct CP value */
    200	buf[0] = 0x30;
    201	buf[1] = 0x50 + tda827x_table[i].cp;
    202	msg.len = 2;
    203
    204	rc = tuner_transfer(fe, &msg, 1);
    205	if (rc < 0)
    206		goto err;
    207
    208	priv->frequency = c->frequency;
    209	priv->bandwidth = c->bandwidth_hz;
    210
    211	return 0;
    212
    213err:
    214	printk(KERN_ERR "%s: could not write to tuner at addr: 0x%02x\n",
    215	       __func__, priv->i2c_addr << 1);
    216	return rc;
    217}
    218
    219static int tda827xo_sleep(struct dvb_frontend *fe)
    220{
    221	struct tda827x_priv *priv = fe->tuner_priv;
    222	static u8 buf[] = { 0x30, 0xd0 };
    223	struct i2c_msg msg = { .addr = priv->i2c_addr, .flags = 0,
    224			       .buf = buf, .len = sizeof(buf) };
    225
    226	dprintk("%s:\n", __func__);
    227	tuner_transfer(fe, &msg, 1);
    228
    229	if (priv->cfg && priv->cfg->sleep)
    230		priv->cfg->sleep(fe);
    231
    232	return 0;
    233}
    234
    235/* ------------------------------------------------------------------ */
    236
    237static int tda827xo_set_analog_params(struct dvb_frontend *fe,
    238				      struct analog_parameters *params)
    239{
    240	unsigned char tuner_reg[8];
    241	unsigned char reg2[2];
    242	u32 N;
    243	int i;
    244	struct tda827x_priv *priv = fe->tuner_priv;
    245	struct i2c_msg msg = { .addr = priv->i2c_addr, .flags = 0 };
    246	unsigned int freq = params->frequency;
    247
    248	tda827x_set_std(fe, params);
    249
    250	if (params->mode == V4L2_TUNER_RADIO)
    251		freq = freq / 1000;
    252
    253	N = freq + priv->sgIF;
    254
    255	i = 0;
    256	while (tda827x_table[i].lomax < N * 62500) {
    257		if (tda827x_table[i + 1].lomax == 0)
    258			break;
    259		i++;
    260	}
    261
    262	N = N << tda827x_table[i].spd;
    263
    264	tuner_reg[0] = 0;
    265	tuner_reg[1] = (unsigned char)(N>>8);
    266	tuner_reg[2] = (unsigned char) N;
    267	tuner_reg[3] = 0x40;
    268	tuner_reg[4] = 0x52 + (priv->lpsel << 5);
    269	tuner_reg[5] = (tda827x_table[i].spd    << 6) +
    270		       (tda827x_table[i].div1p5 << 5) +
    271		       (tda827x_table[i].bs     << 3) + tda827x_table[i].bp;
    272	tuner_reg[6] = 0x8f + (tda827x_table[i].gc3 << 4);
    273	tuner_reg[7] = 0x8f;
    274
    275	msg.buf = tuner_reg;
    276	msg.len = 8;
    277	tuner_transfer(fe, &msg, 1);
    278
    279	msg.buf = reg2;
    280	msg.len = 2;
    281	reg2[0] = 0x80;
    282	reg2[1] = 0;
    283	tuner_transfer(fe, &msg, 1);
    284
    285	reg2[0] = 0x60;
    286	reg2[1] = 0xbf;
    287	tuner_transfer(fe, &msg, 1);
    288
    289	reg2[0] = 0x30;
    290	reg2[1] = tuner_reg[4] + 0x80;
    291	tuner_transfer(fe, &msg, 1);
    292
    293	msleep(1);
    294	reg2[0] = 0x30;
    295	reg2[1] = tuner_reg[4] + 4;
    296	tuner_transfer(fe, &msg, 1);
    297
    298	msleep(1);
    299	reg2[0] = 0x30;
    300	reg2[1] = tuner_reg[4];
    301	tuner_transfer(fe, &msg, 1);
    302
    303	msleep(550);
    304	reg2[0] = 0x30;
    305	reg2[1] = (tuner_reg[4] & 0xfc) + tda827x_table[i].cp;
    306	tuner_transfer(fe, &msg, 1);
    307
    308	reg2[0] = 0x60;
    309	reg2[1] = 0x3f;
    310	tuner_transfer(fe, &msg, 1);
    311
    312	reg2[0] = 0x80;
    313	reg2[1] = 0x08;   /* Vsync en */
    314	tuner_transfer(fe, &msg, 1);
    315
    316	priv->frequency = params->frequency;
    317
    318	return 0;
    319}
    320
    321static void tda827xo_agcf(struct dvb_frontend *fe)
    322{
    323	struct tda827x_priv *priv = fe->tuner_priv;
    324	unsigned char data[] = { 0x80, 0x0c };
    325	struct i2c_msg msg = { .addr = priv->i2c_addr, .flags = 0,
    326			       .buf = data, .len = 2};
    327
    328	tuner_transfer(fe, &msg, 1);
    329}
    330
    331/* ------------------------------------------------------------------ */
    332
    333struct tda827xa_data {
    334	u32 lomax;
    335	u8  svco;
    336	u8  spd;
    337	u8  scr;
    338	u8  sbs;
    339	u8  gc3;
    340};
    341
    342static struct tda827xa_data tda827xa_dvbt[] = {
    343	{ .lomax =  56875000, .svco = 3, .spd = 4, .scr = 0, .sbs = 0, .gc3 = 1},
    344	{ .lomax =  67250000, .svco = 0, .spd = 3, .scr = 0, .sbs = 0, .gc3 = 1},
    345	{ .lomax =  81250000, .svco = 1, .spd = 3, .scr = 0, .sbs = 0, .gc3 = 1},
    346	{ .lomax =  97500000, .svco = 2, .spd = 3, .scr = 0, .sbs = 0, .gc3 = 1},
    347	{ .lomax = 113750000, .svco = 3, .spd = 3, .scr = 0, .sbs = 1, .gc3 = 1},
    348	{ .lomax = 134500000, .svco = 0, .spd = 2, .scr = 0, .sbs = 1, .gc3 = 1},
    349	{ .lomax = 154000000, .svco = 1, .spd = 2, .scr = 0, .sbs = 1, .gc3 = 1},
    350	{ .lomax = 162500000, .svco = 1, .spd = 2, .scr = 0, .sbs = 1, .gc3 = 1},
    351	{ .lomax = 183000000, .svco = 2, .spd = 2, .scr = 0, .sbs = 1, .gc3 = 1},
    352	{ .lomax = 195000000, .svco = 2, .spd = 2, .scr = 0, .sbs = 2, .gc3 = 1},
    353	{ .lomax = 227500000, .svco = 3, .spd = 2, .scr = 0, .sbs = 2, .gc3 = 1},
    354	{ .lomax = 269000000, .svco = 0, .spd = 1, .scr = 0, .sbs = 2, .gc3 = 1},
    355	{ .lomax = 290000000, .svco = 1, .spd = 1, .scr = 0, .sbs = 2, .gc3 = 1},
    356	{ .lomax = 325000000, .svco = 1, .spd = 1, .scr = 0, .sbs = 3, .gc3 = 1},
    357	{ .lomax = 390000000, .svco = 2, .spd = 1, .scr = 0, .sbs = 3, .gc3 = 1},
    358	{ .lomax = 455000000, .svco = 3, .spd = 1, .scr = 0, .sbs = 3, .gc3 = 1},
    359	{ .lomax = 520000000, .svco = 0, .spd = 0, .scr = 0, .sbs = 3, .gc3 = 1},
    360	{ .lomax = 538000000, .svco = 0, .spd = 0, .scr = 1, .sbs = 3, .gc3 = 1},
    361	{ .lomax = 550000000, .svco = 1, .spd = 0, .scr = 0, .sbs = 3, .gc3 = 1},
    362	{ .lomax = 620000000, .svco = 1, .spd = 0, .scr = 0, .sbs = 4, .gc3 = 0},
    363	{ .lomax = 650000000, .svco = 1, .spd = 0, .scr = 1, .sbs = 4, .gc3 = 0},
    364	{ .lomax = 700000000, .svco = 2, .spd = 0, .scr = 0, .sbs = 4, .gc3 = 0},
    365	{ .lomax = 780000000, .svco = 2, .spd = 0, .scr = 1, .sbs = 4, .gc3 = 0},
    366	{ .lomax = 820000000, .svco = 3, .spd = 0, .scr = 0, .sbs = 4, .gc3 = 0},
    367	{ .lomax = 870000000, .svco = 3, .spd = 0, .scr = 1, .sbs = 4, .gc3 = 0},
    368	{ .lomax = 911000000, .svco = 3, .spd = 0, .scr = 2, .sbs = 4, .gc3 = 0},
    369	{ .lomax =         0, .svco = 0, .spd = 0, .scr = 0, .sbs = 0, .gc3 = 0}
    370};
    371
    372static struct tda827xa_data tda827xa_dvbc[] = {
    373	{ .lomax =  50125000, .svco = 2, .spd = 4, .scr = 2, .sbs = 0, .gc3 = 3},
    374	{ .lomax =  58500000, .svco = 3, .spd = 4, .scr = 2, .sbs = 0, .gc3 = 3},
    375	{ .lomax =  69250000, .svco = 0, .spd = 3, .scr = 2, .sbs = 0, .gc3 = 3},
    376	{ .lomax =  83625000, .svco = 1, .spd = 3, .scr = 2, .sbs = 0, .gc3 = 3},
    377	{ .lomax =  97500000, .svco = 2, .spd = 3, .scr = 2, .sbs = 0, .gc3 = 3},
    378	{ .lomax = 100250000, .svco = 2, .spd = 3, .scr = 2, .sbs = 1, .gc3 = 1},
    379	{ .lomax = 117000000, .svco = 3, .spd = 3, .scr = 2, .sbs = 1, .gc3 = 1},
    380	{ .lomax = 138500000, .svco = 0, .spd = 2, .scr = 2, .sbs = 1, .gc3 = 1},
    381	{ .lomax = 167250000, .svco = 1, .spd = 2, .scr = 2, .sbs = 1, .gc3 = 1},
    382	{ .lomax = 187000000, .svco = 2, .spd = 2, .scr = 2, .sbs = 1, .gc3 = 1},
    383	{ .lomax = 200500000, .svco = 2, .spd = 2, .scr = 2, .sbs = 2, .gc3 = 1},
    384	{ .lomax = 234000000, .svco = 3, .spd = 2, .scr = 2, .sbs = 2, .gc3 = 3},
    385	{ .lomax = 277000000, .svco = 0, .spd = 1, .scr = 2, .sbs = 2, .gc3 = 3},
    386	{ .lomax = 325000000, .svco = 1, .spd = 1, .scr = 2, .sbs = 2, .gc3 = 1},
    387	{ .lomax = 334500000, .svco = 1, .spd = 1, .scr = 2, .sbs = 3, .gc3 = 3},
    388	{ .lomax = 401000000, .svco = 2, .spd = 1, .scr = 2, .sbs = 3, .gc3 = 3},
    389	{ .lomax = 468000000, .svco = 3, .spd = 1, .scr = 2, .sbs = 3, .gc3 = 1},
    390	{ .lomax = 535000000, .svco = 0, .spd = 0, .scr = 1, .sbs = 3, .gc3 = 1},
    391	{ .lomax = 554000000, .svco = 0, .spd = 0, .scr = 2, .sbs = 3, .gc3 = 1},
    392	{ .lomax = 638000000, .svco = 1, .spd = 0, .scr = 1, .sbs = 4, .gc3 = 1},
    393	{ .lomax = 669000000, .svco = 1, .spd = 0, .scr = 2, .sbs = 4, .gc3 = 1},
    394	{ .lomax = 720000000, .svco = 2, .spd = 0, .scr = 1, .sbs = 4, .gc3 = 1},
    395	{ .lomax = 802000000, .svco = 2, .spd = 0, .scr = 2, .sbs = 4, .gc3 = 1},
    396	{ .lomax = 835000000, .svco = 3, .spd = 0, .scr = 1, .sbs = 4, .gc3 = 1},
    397	{ .lomax = 885000000, .svco = 3, .spd = 0, .scr = 1, .sbs = 4, .gc3 = 1},
    398	{ .lomax = 911000000, .svco = 3, .spd = 0, .scr = 2, .sbs = 4, .gc3 = 1},
    399	{ .lomax =         0, .svco = 0, .spd = 0, .scr = 0, .sbs = 0, .gc3 = 0}
    400};
    401
    402static struct tda827xa_data tda827xa_analog[] = {
    403	{ .lomax =  56875000, .svco = 3, .spd = 4, .scr = 0, .sbs = 0, .gc3 = 3},
    404	{ .lomax =  67250000, .svco = 0, .spd = 3, .scr = 0, .sbs = 0, .gc3 = 3},
    405	{ .lomax =  81250000, .svco = 1, .spd = 3, .scr = 0, .sbs = 0, .gc3 = 3},
    406	{ .lomax =  97500000, .svco = 2, .spd = 3, .scr = 0, .sbs = 0, .gc3 = 3},
    407	{ .lomax = 113750000, .svco = 3, .spd = 3, .scr = 0, .sbs = 1, .gc3 = 1},
    408	{ .lomax = 134500000, .svco = 0, .spd = 2, .scr = 0, .sbs = 1, .gc3 = 1},
    409	{ .lomax = 154000000, .svco = 1, .spd = 2, .scr = 0, .sbs = 1, .gc3 = 1},
    410	{ .lomax = 162500000, .svco = 1, .spd = 2, .scr = 0, .sbs = 1, .gc3 = 1},
    411	{ .lomax = 183000000, .svco = 2, .spd = 2, .scr = 0, .sbs = 1, .gc3 = 1},
    412	{ .lomax = 195000000, .svco = 2, .spd = 2, .scr = 0, .sbs = 2, .gc3 = 1},
    413	{ .lomax = 227500000, .svco = 3, .spd = 2, .scr = 0, .sbs = 2, .gc3 = 3},
    414	{ .lomax = 269000000, .svco = 0, .spd = 1, .scr = 0, .sbs = 2, .gc3 = 3},
    415	{ .lomax = 325000000, .svco = 1, .spd = 1, .scr = 0, .sbs = 2, .gc3 = 1},
    416	{ .lomax = 390000000, .svco = 2, .spd = 1, .scr = 0, .sbs = 3, .gc3 = 3},
    417	{ .lomax = 455000000, .svco = 3, .spd = 1, .scr = 0, .sbs = 3, .gc3 = 3},
    418	{ .lomax = 520000000, .svco = 0, .spd = 0, .scr = 0, .sbs = 3, .gc3 = 1},
    419	{ .lomax = 538000000, .svco = 0, .spd = 0, .scr = 1, .sbs = 3, .gc3 = 1},
    420	{ .lomax = 554000000, .svco = 1, .spd = 0, .scr = 0, .sbs = 3, .gc3 = 1},
    421	{ .lomax = 620000000, .svco = 1, .spd = 0, .scr = 0, .sbs = 4, .gc3 = 0},
    422	{ .lomax = 650000000, .svco = 1, .spd = 0, .scr = 1, .sbs = 4, .gc3 = 0},
    423	{ .lomax = 700000000, .svco = 2, .spd = 0, .scr = 0, .sbs = 4, .gc3 = 0},
    424	{ .lomax = 780000000, .svco = 2, .spd = 0, .scr = 1, .sbs = 4, .gc3 = 0},
    425	{ .lomax = 820000000, .svco = 3, .spd = 0, .scr = 0, .sbs = 4, .gc3 = 0},
    426	{ .lomax = 870000000, .svco = 3, .spd = 0, .scr = 1, .sbs = 4, .gc3 = 0},
    427	{ .lomax = 911000000, .svco = 3, .spd = 0, .scr = 2, .sbs = 4, .gc3 = 0},
    428	{ .lomax =         0, .svco = 0, .spd = 0, .scr = 0, .sbs = 0, .gc3 = 0}
    429};
    430
    431static int tda827xa_sleep(struct dvb_frontend *fe)
    432{
    433	struct tda827x_priv *priv = fe->tuner_priv;
    434	static u8 buf[] = { 0x30, 0x90 };
    435	struct i2c_msg msg = { .addr = priv->i2c_addr, .flags = 0,
    436			       .buf = buf, .len = sizeof(buf) };
    437
    438	dprintk("%s:\n", __func__);
    439
    440	tuner_transfer(fe, &msg, 1);
    441
    442	if (priv->cfg && priv->cfg->sleep)
    443		priv->cfg->sleep(fe);
    444
    445	return 0;
    446}
    447
    448static void tda827xa_lna_gain(struct dvb_frontend *fe, int high,
    449			      struct analog_parameters *params)
    450{
    451	struct tda827x_priv *priv = fe->tuner_priv;
    452	unsigned char buf[] = {0x22, 0x01};
    453	int arg;
    454	int gp_func;
    455	struct i2c_msg msg = { .flags = 0, .buf = buf, .len = sizeof(buf) };
    456
    457	if (NULL == priv->cfg) {
    458		dprintk("tda827x_config not defined, cannot set LNA gain!\n");
    459		return;
    460	}
    461	msg.addr = priv->cfg->switch_addr;
    462	if (priv->cfg->config) {
    463		if (high)
    464			dprintk("setting LNA to high gain\n");
    465		else
    466			dprintk("setting LNA to low gain\n");
    467	}
    468	switch (priv->cfg->config) {
    469	case TDA8290_LNA_OFF: /* no LNA */
    470		break;
    471	case TDA8290_LNA_GP0_HIGH_ON: /* switch is GPIO 0 of tda8290 */
    472	case TDA8290_LNA_GP0_HIGH_OFF:
    473		if (params == NULL) {
    474			gp_func = 0;
    475			arg  = 0;
    476		} else {
    477			/* turn Vsync on */
    478			gp_func = 1;
    479			if (params->std & V4L2_STD_MN)
    480				arg = 1;
    481			else
    482				arg = 0;
    483		}
    484		if (fe->callback)
    485			fe->callback(priv->i2c_adap->algo_data,
    486				     DVB_FRONTEND_COMPONENT_TUNER,
    487				     gp_func, arg);
    488		buf[1] = high ? 0 : 1;
    489		if (priv->cfg->config == TDA8290_LNA_GP0_HIGH_OFF)
    490			buf[1] = high ? 1 : 0;
    491		tuner_transfer(fe, &msg, 1);
    492		break;
    493	case TDA8290_LNA_ON_BRIDGE: /* switch with GPIO of saa713x */
    494		if (fe->callback)
    495			fe->callback(priv->i2c_adap->algo_data,
    496				     DVB_FRONTEND_COMPONENT_TUNER, 0, high);
    497		break;
    498	}
    499}
    500
    501static int tda827xa_set_params(struct dvb_frontend *fe)
    502{
    503	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
    504	struct tda827x_priv *priv = fe->tuner_priv;
    505	struct tda827xa_data *frequency_map = tda827xa_dvbt;
    506	u8 buf[11];
    507
    508	struct i2c_msg msg = { .addr = priv->i2c_addr, .flags = 0,
    509			       .buf = buf, .len = sizeof(buf) };
    510
    511	int i, tuner_freq, if_freq, rc;
    512	u32 N;
    513
    514	dprintk("%s:\n", __func__);
    515
    516	tda827xa_lna_gain(fe, 1, NULL);
    517	msleep(20);
    518
    519	if (c->bandwidth_hz == 0) {
    520		if_freq = 5000000;
    521	} else if (c->bandwidth_hz <= 6000000) {
    522		if_freq = 4000000;
    523	} else if (c->bandwidth_hz <= 7000000) {
    524		if_freq = 4500000;
    525	} else {	/* 8 MHz */
    526		if_freq = 5000000;
    527	}
    528	tuner_freq = c->frequency;
    529
    530	switch (c->delivery_system) {
    531	case SYS_DVBC_ANNEX_A:
    532	case SYS_DVBC_ANNEX_C:
    533		dprintk("%s select tda827xa_dvbc\n", __func__);
    534		frequency_map = tda827xa_dvbc;
    535		break;
    536	default:
    537		break;
    538	}
    539
    540	i = 0;
    541	while (frequency_map[i].lomax < tuner_freq) {
    542		if (frequency_map[i + 1].lomax == 0)
    543			break;
    544		i++;
    545	}
    546
    547	tuner_freq += if_freq;
    548
    549	N = ((tuner_freq + 31250) / 62500) << frequency_map[i].spd;
    550	buf[0] = 0;            // subaddress
    551	buf[1] = N >> 8;
    552	buf[2] = N & 0xff;
    553	buf[3] = 0;
    554	buf[4] = 0x16;
    555	buf[5] = (frequency_map[i].spd << 5) + (frequency_map[i].svco << 3) +
    556			frequency_map[i].sbs;
    557	buf[6] = 0x4b + (frequency_map[i].gc3 << 4);
    558	buf[7] = 0x1c;
    559	buf[8] = 0x06;
    560	buf[9] = 0x24;
    561	buf[10] = 0x00;
    562	msg.len = 11;
    563	rc = tuner_transfer(fe, &msg, 1);
    564	if (rc < 0)
    565		goto err;
    566
    567	buf[0] = 0x90;
    568	buf[1] = 0xff;
    569	buf[2] = 0x60;
    570	buf[3] = 0x00;
    571	buf[4] = 0x59;  // lpsel, for 6MHz + 2
    572	msg.len = 5;
    573	rc = tuner_transfer(fe, &msg, 1);
    574	if (rc < 0)
    575		goto err;
    576
    577	buf[0] = 0xa0;
    578	buf[1] = 0x40;
    579	msg.len = 2;
    580	rc = tuner_transfer(fe, &msg, 1);
    581	if (rc < 0)
    582		goto err;
    583
    584	msleep(11);
    585	msg.flags = I2C_M_RD;
    586	rc = tuner_transfer(fe, &msg, 1);
    587	if (rc < 0)
    588		goto err;
    589	msg.flags = 0;
    590
    591	buf[1] >>= 4;
    592	dprintk("tda8275a AGC2 gain is: %d\n", buf[1]);
    593	if ((buf[1]) < 2) {
    594		tda827xa_lna_gain(fe, 0, NULL);
    595		buf[0] = 0x60;
    596		buf[1] = 0x0c;
    597		rc = tuner_transfer(fe, &msg, 1);
    598		if (rc < 0)
    599			goto err;
    600	}
    601
    602	buf[0] = 0xc0;
    603	buf[1] = 0x99;    // lpsel, for 6MHz + 2
    604	rc = tuner_transfer(fe, &msg, 1);
    605	if (rc < 0)
    606		goto err;
    607
    608	buf[0] = 0x60;
    609	buf[1] = 0x3c;
    610	rc = tuner_transfer(fe, &msg, 1);
    611	if (rc < 0)
    612		goto err;
    613
    614	/* correct CP value */
    615	buf[0] = 0x30;
    616	buf[1] = 0x10 + frequency_map[i].scr;
    617	rc = tuner_transfer(fe, &msg, 1);
    618	if (rc < 0)
    619		goto err;
    620
    621	msleep(163);
    622	buf[0] = 0xc0;
    623	buf[1] = 0x39;  // lpsel, for 6MHz + 2
    624	rc = tuner_transfer(fe, &msg, 1);
    625	if (rc < 0)
    626		goto err;
    627
    628	msleep(3);
    629	/* freeze AGC1 */
    630	buf[0] = 0x50;
    631	buf[1] = 0x4f + (frequency_map[i].gc3 << 4);
    632	rc = tuner_transfer(fe, &msg, 1);
    633	if (rc < 0)
    634		goto err;
    635
    636	priv->frequency = c->frequency;
    637	priv->bandwidth = c->bandwidth_hz;
    638
    639	return 0;
    640
    641err:
    642	printk(KERN_ERR "%s: could not write to tuner at addr: 0x%02x\n",
    643	       __func__, priv->i2c_addr << 1);
    644	return rc;
    645}
    646
    647
    648static int tda827xa_set_analog_params(struct dvb_frontend *fe,
    649				      struct analog_parameters *params)
    650{
    651	unsigned char tuner_reg[11];
    652	u32 N;
    653	int i;
    654	struct tda827x_priv *priv = fe->tuner_priv;
    655	struct i2c_msg msg = { .addr = priv->i2c_addr, .flags = 0,
    656			       .buf = tuner_reg, .len = sizeof(tuner_reg) };
    657	unsigned int freq = params->frequency;
    658
    659	tda827x_set_std(fe, params);
    660
    661	tda827xa_lna_gain(fe, 1, params);
    662	msleep(10);
    663
    664	if (params->mode == V4L2_TUNER_RADIO)
    665		freq = freq / 1000;
    666
    667	N = freq + priv->sgIF;
    668
    669	i = 0;
    670	while (tda827xa_analog[i].lomax < N * 62500) {
    671		if (tda827xa_analog[i + 1].lomax == 0)
    672			break;
    673		i++;
    674	}
    675
    676	N = N << tda827xa_analog[i].spd;
    677
    678	tuner_reg[0] = 0;
    679	tuner_reg[1] = (unsigned char)(N>>8);
    680	tuner_reg[2] = (unsigned char) N;
    681	tuner_reg[3] = 0;
    682	tuner_reg[4] = 0x16;
    683	tuner_reg[5] = (tda827xa_analog[i].spd << 5) +
    684		       (tda827xa_analog[i].svco << 3) +
    685			tda827xa_analog[i].sbs;
    686	tuner_reg[6] = 0x8b + (tda827xa_analog[i].gc3 << 4);
    687	tuner_reg[7] = 0x1c;
    688	tuner_reg[8] = 4;
    689	tuner_reg[9] = 0x20;
    690	tuner_reg[10] = 0x00;
    691	msg.len = 11;
    692	tuner_transfer(fe, &msg, 1);
    693
    694	tuner_reg[0] = 0x90;
    695	tuner_reg[1] = 0xff;
    696	tuner_reg[2] = 0xe0;
    697	tuner_reg[3] = 0;
    698	tuner_reg[4] = 0x99 + (priv->lpsel << 1);
    699	msg.len = 5;
    700	tuner_transfer(fe, &msg, 1);
    701
    702	tuner_reg[0] = 0xa0;
    703	tuner_reg[1] = 0xc0;
    704	msg.len = 2;
    705	tuner_transfer(fe, &msg, 1);
    706
    707	tuner_reg[0] = 0x30;
    708	tuner_reg[1] = 0x10 + tda827xa_analog[i].scr;
    709	tuner_transfer(fe, &msg, 1);
    710
    711	msg.flags = I2C_M_RD;
    712	tuner_transfer(fe, &msg, 1);
    713	msg.flags = 0;
    714	tuner_reg[1] >>= 4;
    715	dprintk("AGC2 gain is: %d\n", tuner_reg[1]);
    716	if (tuner_reg[1] < 1)
    717		tda827xa_lna_gain(fe, 0, params);
    718
    719	msleep(100);
    720	tuner_reg[0] = 0x60;
    721	tuner_reg[1] = 0x3c;
    722	tuner_transfer(fe, &msg, 1);
    723
    724	msleep(163);
    725	tuner_reg[0] = 0x50;
    726	tuner_reg[1] = 0x8f + (tda827xa_analog[i].gc3 << 4);
    727	tuner_transfer(fe, &msg, 1);
    728
    729	tuner_reg[0] = 0x80;
    730	tuner_reg[1] = 0x28;
    731	tuner_transfer(fe, &msg, 1);
    732
    733	tuner_reg[0] = 0xb0;
    734	tuner_reg[1] = 0x01;
    735	tuner_transfer(fe, &msg, 1);
    736
    737	tuner_reg[0] = 0xc0;
    738	tuner_reg[1] = 0x19 + (priv->lpsel << 1);
    739	tuner_transfer(fe, &msg, 1);
    740
    741	priv->frequency = params->frequency;
    742
    743	return 0;
    744}
    745
    746static void tda827xa_agcf(struct dvb_frontend *fe)
    747{
    748	struct tda827x_priv *priv = fe->tuner_priv;
    749	unsigned char data[] = {0x80, 0x2c};
    750	struct i2c_msg msg = {.addr = priv->i2c_addr, .flags = 0,
    751			      .buf = data, .len = 2};
    752	tuner_transfer(fe, &msg, 1);
    753}
    754
    755/* ------------------------------------------------------------------ */
    756
    757static void tda827x_release(struct dvb_frontend *fe)
    758{
    759	kfree(fe->tuner_priv);
    760	fe->tuner_priv = NULL;
    761}
    762
    763static int tda827x_get_frequency(struct dvb_frontend *fe, u32 *frequency)
    764{
    765	struct tda827x_priv *priv = fe->tuner_priv;
    766	*frequency = priv->frequency;
    767	return 0;
    768}
    769
    770static int tda827x_get_bandwidth(struct dvb_frontend *fe, u32 *bandwidth)
    771{
    772	struct tda827x_priv *priv = fe->tuner_priv;
    773	*bandwidth = priv->bandwidth;
    774	return 0;
    775}
    776
    777static int tda827x_init(struct dvb_frontend *fe)
    778{
    779	struct tda827x_priv *priv = fe->tuner_priv;
    780	dprintk("%s:\n", __func__);
    781	if (priv->cfg && priv->cfg->init)
    782		priv->cfg->init(fe);
    783
    784	return 0;
    785}
    786
    787static int tda827x_probe_version(struct dvb_frontend *fe);
    788
    789static int tda827x_initial_init(struct dvb_frontend *fe)
    790{
    791	int ret;
    792	ret = tda827x_probe_version(fe);
    793	if (ret)
    794		return ret;
    795	return fe->ops.tuner_ops.init(fe);
    796}
    797
    798static int tda827x_initial_sleep(struct dvb_frontend *fe)
    799{
    800	int ret;
    801	ret = tda827x_probe_version(fe);
    802	if (ret)
    803		return ret;
    804	return fe->ops.tuner_ops.sleep(fe);
    805}
    806
    807static const struct dvb_tuner_ops tda827xo_tuner_ops = {
    808	.info = {
    809		.name = "Philips TDA827X",
    810		.frequency_min_hz  =  55 * MHz,
    811		.frequency_max_hz  = 860 * MHz,
    812		.frequency_step_hz = 250 * kHz
    813	},
    814	.release = tda827x_release,
    815	.init = tda827x_initial_init,
    816	.sleep = tda827x_initial_sleep,
    817	.set_params = tda827xo_set_params,
    818	.set_analog_params = tda827xo_set_analog_params,
    819	.get_frequency = tda827x_get_frequency,
    820	.get_bandwidth = tda827x_get_bandwidth,
    821};
    822
    823static const struct dvb_tuner_ops tda827xa_tuner_ops = {
    824	.info = {
    825		.name = "Philips TDA827XA",
    826		.frequency_min_hz  =  44 * MHz,
    827		.frequency_max_hz  = 906 * MHz,
    828		.frequency_step_hz = 62500
    829	},
    830	.release = tda827x_release,
    831	.init = tda827x_init,
    832	.sleep = tda827xa_sleep,
    833	.set_params = tda827xa_set_params,
    834	.set_analog_params = tda827xa_set_analog_params,
    835	.get_frequency = tda827x_get_frequency,
    836	.get_bandwidth = tda827x_get_bandwidth,
    837};
    838
    839static int tda827x_probe_version(struct dvb_frontend *fe)
    840{
    841	u8 data;
    842	int rc;
    843	struct tda827x_priv *priv = fe->tuner_priv;
    844	struct i2c_msg msg = { .addr = priv->i2c_addr, .flags = I2C_M_RD,
    845			       .buf = &data, .len = 1 };
    846
    847	rc = tuner_transfer(fe, &msg, 1);
    848
    849	if (rc < 0) {
    850		printk("%s: could not read from tuner at addr: 0x%02x\n",
    851		       __func__, msg.addr << 1);
    852		return rc;
    853	}
    854	if ((data & 0x3c) == 0) {
    855		dprintk("tda827x tuner found\n");
    856		fe->ops.tuner_ops.init  = tda827x_init;
    857		fe->ops.tuner_ops.sleep = tda827xo_sleep;
    858		if (priv->cfg)
    859			priv->cfg->agcf = tda827xo_agcf;
    860	} else {
    861		dprintk("tda827xa tuner found\n");
    862		memcpy(&fe->ops.tuner_ops, &tda827xa_tuner_ops, sizeof(struct dvb_tuner_ops));
    863		if (priv->cfg)
    864			priv->cfg->agcf = tda827xa_agcf;
    865	}
    866	return 0;
    867}
    868
    869struct dvb_frontend *tda827x_attach(struct dvb_frontend *fe, int addr,
    870				    struct i2c_adapter *i2c,
    871				    struct tda827x_config *cfg)
    872{
    873	struct tda827x_priv *priv = NULL;
    874
    875	dprintk("%s:\n", __func__);
    876	priv = kzalloc(sizeof(struct tda827x_priv), GFP_KERNEL);
    877	if (priv == NULL)
    878		return NULL;
    879
    880	priv->i2c_addr = addr;
    881	priv->i2c_adap = i2c;
    882	priv->cfg = cfg;
    883	memcpy(&fe->ops.tuner_ops, &tda827xo_tuner_ops, sizeof(struct dvb_tuner_ops));
    884	fe->tuner_priv = priv;
    885
    886	dprintk("type set to %s\n", fe->ops.tuner_ops.info.name);
    887
    888	return fe;
    889}
    890EXPORT_SYMBOL_GPL(tda827x_attach);
    891
    892MODULE_DESCRIPTION("DVB TDA827x driver");
    893MODULE_AUTHOR("Hartmut Hackmann <hartmut.hackmann@t-online.de>");
    894MODULE_AUTHOR("Michael Krufky <mkrufky@linuxtv.org>");
    895MODULE_LICENSE("GPL");