18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci *
48c2ecf20Sopenharmony_ci * (c) 2005 Hartmut Hackmann
58c2ecf20Sopenharmony_ci * (c) 2007 Michael Krufky
68c2ecf20Sopenharmony_ci */
78c2ecf20Sopenharmony_ci
88c2ecf20Sopenharmony_ci#include <linux/module.h>
98c2ecf20Sopenharmony_ci#include <linux/slab.h>
108c2ecf20Sopenharmony_ci#include <asm/types.h>
118c2ecf20Sopenharmony_ci#include <linux/dvb/frontend.h>
128c2ecf20Sopenharmony_ci#include <linux/videodev2.h>
138c2ecf20Sopenharmony_ci
148c2ecf20Sopenharmony_ci#include "tda827x.h"
158c2ecf20Sopenharmony_ci
168c2ecf20Sopenharmony_cistatic int debug;
178c2ecf20Sopenharmony_cimodule_param(debug, int, 0644);
188c2ecf20Sopenharmony_ciMODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off).");
198c2ecf20Sopenharmony_ci
208c2ecf20Sopenharmony_ci#define dprintk(args...) \
218c2ecf20Sopenharmony_ci	do {					    \
228c2ecf20Sopenharmony_ci		if (debug) printk(KERN_DEBUG "tda827x: " args); \
238c2ecf20Sopenharmony_ci	} while (0)
248c2ecf20Sopenharmony_ci
258c2ecf20Sopenharmony_cistruct tda827x_priv {
268c2ecf20Sopenharmony_ci	int i2c_addr;
278c2ecf20Sopenharmony_ci	struct i2c_adapter *i2c_adap;
288c2ecf20Sopenharmony_ci	struct tda827x_config *cfg;
298c2ecf20Sopenharmony_ci
308c2ecf20Sopenharmony_ci	unsigned int sgIF;
318c2ecf20Sopenharmony_ci	unsigned char lpsel;
328c2ecf20Sopenharmony_ci
338c2ecf20Sopenharmony_ci	u32 frequency;
348c2ecf20Sopenharmony_ci	u32 bandwidth;
358c2ecf20Sopenharmony_ci};
368c2ecf20Sopenharmony_ci
378c2ecf20Sopenharmony_cistatic void tda827x_set_std(struct dvb_frontend *fe,
388c2ecf20Sopenharmony_ci			    struct analog_parameters *params)
398c2ecf20Sopenharmony_ci{
408c2ecf20Sopenharmony_ci	struct tda827x_priv *priv = fe->tuner_priv;
418c2ecf20Sopenharmony_ci	char *mode;
428c2ecf20Sopenharmony_ci
438c2ecf20Sopenharmony_ci	priv->lpsel = 0;
448c2ecf20Sopenharmony_ci	if (params->std & V4L2_STD_MN) {
458c2ecf20Sopenharmony_ci		priv->sgIF = 92;
468c2ecf20Sopenharmony_ci		priv->lpsel = 1;
478c2ecf20Sopenharmony_ci		mode = "MN";
488c2ecf20Sopenharmony_ci	} else if (params->std & V4L2_STD_B) {
498c2ecf20Sopenharmony_ci		priv->sgIF = 108;
508c2ecf20Sopenharmony_ci		mode = "B";
518c2ecf20Sopenharmony_ci	} else if (params->std & V4L2_STD_GH) {
528c2ecf20Sopenharmony_ci		priv->sgIF = 124;
538c2ecf20Sopenharmony_ci		mode = "GH";
548c2ecf20Sopenharmony_ci	} else if (params->std & V4L2_STD_PAL_I) {
558c2ecf20Sopenharmony_ci		priv->sgIF = 124;
568c2ecf20Sopenharmony_ci		mode = "I";
578c2ecf20Sopenharmony_ci	} else if (params->std & V4L2_STD_DK) {
588c2ecf20Sopenharmony_ci		priv->sgIF = 124;
598c2ecf20Sopenharmony_ci		mode = "DK";
608c2ecf20Sopenharmony_ci	} else if (params->std & V4L2_STD_SECAM_L) {
618c2ecf20Sopenharmony_ci		priv->sgIF = 124;
628c2ecf20Sopenharmony_ci		mode = "L";
638c2ecf20Sopenharmony_ci	} else if (params->std & V4L2_STD_SECAM_LC) {
648c2ecf20Sopenharmony_ci		priv->sgIF = 20;
658c2ecf20Sopenharmony_ci		mode = "LC";
668c2ecf20Sopenharmony_ci	} else {
678c2ecf20Sopenharmony_ci		priv->sgIF = 124;
688c2ecf20Sopenharmony_ci		mode = "xx";
698c2ecf20Sopenharmony_ci	}
708c2ecf20Sopenharmony_ci
718c2ecf20Sopenharmony_ci	if (params->mode == V4L2_TUNER_RADIO) {
728c2ecf20Sopenharmony_ci		priv->sgIF = 88; /* if frequency is 5.5 MHz */
738c2ecf20Sopenharmony_ci		dprintk("setting tda827x to radio FM\n");
748c2ecf20Sopenharmony_ci	} else
758c2ecf20Sopenharmony_ci		dprintk("setting tda827x to system %s\n", mode);
768c2ecf20Sopenharmony_ci}
778c2ecf20Sopenharmony_ci
788c2ecf20Sopenharmony_ci
798c2ecf20Sopenharmony_ci/* ------------------------------------------------------------------ */
808c2ecf20Sopenharmony_ci
818c2ecf20Sopenharmony_cistruct tda827x_data {
828c2ecf20Sopenharmony_ci	u32 lomax;
838c2ecf20Sopenharmony_ci	u8  spd;
848c2ecf20Sopenharmony_ci	u8  bs;
858c2ecf20Sopenharmony_ci	u8  bp;
868c2ecf20Sopenharmony_ci	u8  cp;
878c2ecf20Sopenharmony_ci	u8  gc3;
888c2ecf20Sopenharmony_ci	u8 div1p5;
898c2ecf20Sopenharmony_ci};
908c2ecf20Sopenharmony_ci
918c2ecf20Sopenharmony_cistatic const struct tda827x_data tda827x_table[] = {
928c2ecf20Sopenharmony_ci	{ .lomax =  62000000, .spd = 3, .bs = 2, .bp = 0, .cp = 0, .gc3 = 3, .div1p5 = 1},
938c2ecf20Sopenharmony_ci	{ .lomax =  66000000, .spd = 3, .bs = 3, .bp = 0, .cp = 0, .gc3 = 3, .div1p5 = 1},
948c2ecf20Sopenharmony_ci	{ .lomax =  76000000, .spd = 3, .bs = 1, .bp = 0, .cp = 0, .gc3 = 3, .div1p5 = 0},
958c2ecf20Sopenharmony_ci	{ .lomax =  84000000, .spd = 3, .bs = 2, .bp = 0, .cp = 0, .gc3 = 3, .div1p5 = 0},
968c2ecf20Sopenharmony_ci	{ .lomax =  93000000, .spd = 3, .bs = 2, .bp = 0, .cp = 0, .gc3 = 1, .div1p5 = 0},
978c2ecf20Sopenharmony_ci	{ .lomax =  98000000, .spd = 3, .bs = 3, .bp = 0, .cp = 0, .gc3 = 1, .div1p5 = 0},
988c2ecf20Sopenharmony_ci	{ .lomax = 109000000, .spd = 3, .bs = 3, .bp = 1, .cp = 0, .gc3 = 1, .div1p5 = 0},
998c2ecf20Sopenharmony_ci	{ .lomax = 123000000, .spd = 2, .bs = 2, .bp = 1, .cp = 0, .gc3 = 1, .div1p5 = 1},
1008c2ecf20Sopenharmony_ci	{ .lomax = 133000000, .spd = 2, .bs = 3, .bp = 1, .cp = 0, .gc3 = 1, .div1p5 = 1},
1018c2ecf20Sopenharmony_ci	{ .lomax = 151000000, .spd = 2, .bs = 1, .bp = 1, .cp = 0, .gc3 = 1, .div1p5 = 0},
1028c2ecf20Sopenharmony_ci	{ .lomax = 154000000, .spd = 2, .bs = 2, .bp = 1, .cp = 0, .gc3 = 1, .div1p5 = 0},
1038c2ecf20Sopenharmony_ci	{ .lomax = 181000000, .spd = 2, .bs = 2, .bp = 1, .cp = 0, .gc3 = 0, .div1p5 = 0},
1048c2ecf20Sopenharmony_ci	{ .lomax = 185000000, .spd = 2, .bs = 2, .bp = 2, .cp = 0, .gc3 = 1, .div1p5 = 0},
1058c2ecf20Sopenharmony_ci	{ .lomax = 217000000, .spd = 2, .bs = 3, .bp = 2, .cp = 0, .gc3 = 1, .div1p5 = 0},
1068c2ecf20Sopenharmony_ci	{ .lomax = 244000000, .spd = 1, .bs = 2, .bp = 2, .cp = 0, .gc3 = 1, .div1p5 = 1},
1078c2ecf20Sopenharmony_ci	{ .lomax = 265000000, .spd = 1, .bs = 3, .bp = 2, .cp = 0, .gc3 = 1, .div1p5 = 1},
1088c2ecf20Sopenharmony_ci	{ .lomax = 302000000, .spd = 1, .bs = 1, .bp = 2, .cp = 0, .gc3 = 1, .div1p5 = 0},
1098c2ecf20Sopenharmony_ci	{ .lomax = 324000000, .spd = 1, .bs = 2, .bp = 2, .cp = 0, .gc3 = 1, .div1p5 = 0},
1108c2ecf20Sopenharmony_ci	{ .lomax = 370000000, .spd = 1, .bs = 2, .bp = 3, .cp = 0, .gc3 = 1, .div1p5 = 0},
1118c2ecf20Sopenharmony_ci	{ .lomax = 454000000, .spd = 1, .bs = 3, .bp = 3, .cp = 0, .gc3 = 1, .div1p5 = 0},
1128c2ecf20Sopenharmony_ci	{ .lomax = 493000000, .spd = 0, .bs = 2, .bp = 3, .cp = 0, .gc3 = 1, .div1p5 = 1},
1138c2ecf20Sopenharmony_ci	{ .lomax = 530000000, .spd = 0, .bs = 3, .bp = 3, .cp = 0, .gc3 = 1, .div1p5 = 1},
1148c2ecf20Sopenharmony_ci	{ .lomax = 554000000, .spd = 0, .bs = 1, .bp = 3, .cp = 0, .gc3 = 1, .div1p5 = 0},
1158c2ecf20Sopenharmony_ci	{ .lomax = 604000000, .spd = 0, .bs = 1, .bp = 4, .cp = 0, .gc3 = 0, .div1p5 = 0},
1168c2ecf20Sopenharmony_ci	{ .lomax = 696000000, .spd = 0, .bs = 2, .bp = 4, .cp = 0, .gc3 = 0, .div1p5 = 0},
1178c2ecf20Sopenharmony_ci	{ .lomax = 740000000, .spd = 0, .bs = 2, .bp = 4, .cp = 1, .gc3 = 0, .div1p5 = 0},
1188c2ecf20Sopenharmony_ci	{ .lomax = 820000000, .spd = 0, .bs = 3, .bp = 4, .cp = 0, .gc3 = 0, .div1p5 = 0},
1198c2ecf20Sopenharmony_ci	{ .lomax = 865000000, .spd = 0, .bs = 3, .bp = 4, .cp = 1, .gc3 = 0, .div1p5 = 0},
1208c2ecf20Sopenharmony_ci	{ .lomax =         0, .spd = 0, .bs = 0, .bp = 0, .cp = 0, .gc3 = 0, .div1p5 = 0}
1218c2ecf20Sopenharmony_ci};
1228c2ecf20Sopenharmony_ci
1238c2ecf20Sopenharmony_cistatic int tuner_transfer(struct dvb_frontend *fe,
1248c2ecf20Sopenharmony_ci			  struct i2c_msg *msg,
1258c2ecf20Sopenharmony_ci			  const int size)
1268c2ecf20Sopenharmony_ci{
1278c2ecf20Sopenharmony_ci	int rc;
1288c2ecf20Sopenharmony_ci	struct tda827x_priv *priv = fe->tuner_priv;
1298c2ecf20Sopenharmony_ci
1308c2ecf20Sopenharmony_ci	if (fe->ops.i2c_gate_ctrl)
1318c2ecf20Sopenharmony_ci		fe->ops.i2c_gate_ctrl(fe, 1);
1328c2ecf20Sopenharmony_ci	rc = i2c_transfer(priv->i2c_adap, msg, size);
1338c2ecf20Sopenharmony_ci	if (fe->ops.i2c_gate_ctrl)
1348c2ecf20Sopenharmony_ci		fe->ops.i2c_gate_ctrl(fe, 0);
1358c2ecf20Sopenharmony_ci
1368c2ecf20Sopenharmony_ci	if (rc >= 0 && rc != size)
1378c2ecf20Sopenharmony_ci		return -EIO;
1388c2ecf20Sopenharmony_ci
1398c2ecf20Sopenharmony_ci	return rc;
1408c2ecf20Sopenharmony_ci}
1418c2ecf20Sopenharmony_ci
1428c2ecf20Sopenharmony_cistatic int tda827xo_set_params(struct dvb_frontend *fe)
1438c2ecf20Sopenharmony_ci{
1448c2ecf20Sopenharmony_ci	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
1458c2ecf20Sopenharmony_ci	struct tda827x_priv *priv = fe->tuner_priv;
1468c2ecf20Sopenharmony_ci	u8 buf[14];
1478c2ecf20Sopenharmony_ci	int rc;
1488c2ecf20Sopenharmony_ci
1498c2ecf20Sopenharmony_ci	struct i2c_msg msg = { .addr = priv->i2c_addr, .flags = 0,
1508c2ecf20Sopenharmony_ci			       .buf = buf, .len = sizeof(buf) };
1518c2ecf20Sopenharmony_ci	int i, tuner_freq, if_freq;
1528c2ecf20Sopenharmony_ci	u32 N;
1538c2ecf20Sopenharmony_ci
1548c2ecf20Sopenharmony_ci	dprintk("%s:\n", __func__);
1558c2ecf20Sopenharmony_ci	if (c->bandwidth_hz == 0) {
1568c2ecf20Sopenharmony_ci		if_freq = 5000000;
1578c2ecf20Sopenharmony_ci	} else if (c->bandwidth_hz <= 6000000) {
1588c2ecf20Sopenharmony_ci		if_freq = 4000000;
1598c2ecf20Sopenharmony_ci	} else if (c->bandwidth_hz <= 7000000) {
1608c2ecf20Sopenharmony_ci		if_freq = 4500000;
1618c2ecf20Sopenharmony_ci	} else {	/* 8 MHz */
1628c2ecf20Sopenharmony_ci		if_freq = 5000000;
1638c2ecf20Sopenharmony_ci	}
1648c2ecf20Sopenharmony_ci	tuner_freq = c->frequency;
1658c2ecf20Sopenharmony_ci
1668c2ecf20Sopenharmony_ci	i = 0;
1678c2ecf20Sopenharmony_ci	while (tda827x_table[i].lomax < tuner_freq) {
1688c2ecf20Sopenharmony_ci		if (tda827x_table[i + 1].lomax == 0)
1698c2ecf20Sopenharmony_ci			break;
1708c2ecf20Sopenharmony_ci		i++;
1718c2ecf20Sopenharmony_ci	}
1728c2ecf20Sopenharmony_ci
1738c2ecf20Sopenharmony_ci	tuner_freq += if_freq;
1748c2ecf20Sopenharmony_ci
1758c2ecf20Sopenharmony_ci	N = ((tuner_freq + 125000) / 250000) << (tda827x_table[i].spd + 2);
1768c2ecf20Sopenharmony_ci	buf[0] = 0;
1778c2ecf20Sopenharmony_ci	buf[1] = (N>>8) | 0x40;
1788c2ecf20Sopenharmony_ci	buf[2] = N & 0xff;
1798c2ecf20Sopenharmony_ci	buf[3] = 0;
1808c2ecf20Sopenharmony_ci	buf[4] = 0x52;
1818c2ecf20Sopenharmony_ci	buf[5] = (tda827x_table[i].spd << 6) + (tda827x_table[i].div1p5 << 5) +
1828c2ecf20Sopenharmony_ci				(tda827x_table[i].bs << 3) +
1838c2ecf20Sopenharmony_ci				tda827x_table[i].bp;
1848c2ecf20Sopenharmony_ci	buf[6] = (tda827x_table[i].gc3 << 4) + 0x8f;
1858c2ecf20Sopenharmony_ci	buf[7] = 0xbf;
1868c2ecf20Sopenharmony_ci	buf[8] = 0x2a;
1878c2ecf20Sopenharmony_ci	buf[9] = 0x05;
1888c2ecf20Sopenharmony_ci	buf[10] = 0xff;
1898c2ecf20Sopenharmony_ci	buf[11] = 0x00;
1908c2ecf20Sopenharmony_ci	buf[12] = 0x00;
1918c2ecf20Sopenharmony_ci	buf[13] = 0x40;
1928c2ecf20Sopenharmony_ci
1938c2ecf20Sopenharmony_ci	msg.len = 14;
1948c2ecf20Sopenharmony_ci	rc = tuner_transfer(fe, &msg, 1);
1958c2ecf20Sopenharmony_ci	if (rc < 0)
1968c2ecf20Sopenharmony_ci		goto err;
1978c2ecf20Sopenharmony_ci
1988c2ecf20Sopenharmony_ci	msleep(500);
1998c2ecf20Sopenharmony_ci	/* correct CP value */
2008c2ecf20Sopenharmony_ci	buf[0] = 0x30;
2018c2ecf20Sopenharmony_ci	buf[1] = 0x50 + tda827x_table[i].cp;
2028c2ecf20Sopenharmony_ci	msg.len = 2;
2038c2ecf20Sopenharmony_ci
2048c2ecf20Sopenharmony_ci	rc = tuner_transfer(fe, &msg, 1);
2058c2ecf20Sopenharmony_ci	if (rc < 0)
2068c2ecf20Sopenharmony_ci		goto err;
2078c2ecf20Sopenharmony_ci
2088c2ecf20Sopenharmony_ci	priv->frequency = c->frequency;
2098c2ecf20Sopenharmony_ci	priv->bandwidth = c->bandwidth_hz;
2108c2ecf20Sopenharmony_ci
2118c2ecf20Sopenharmony_ci	return 0;
2128c2ecf20Sopenharmony_ci
2138c2ecf20Sopenharmony_cierr:
2148c2ecf20Sopenharmony_ci	printk(KERN_ERR "%s: could not write to tuner at addr: 0x%02x\n",
2158c2ecf20Sopenharmony_ci	       __func__, priv->i2c_addr << 1);
2168c2ecf20Sopenharmony_ci	return rc;
2178c2ecf20Sopenharmony_ci}
2188c2ecf20Sopenharmony_ci
2198c2ecf20Sopenharmony_cistatic int tda827xo_sleep(struct dvb_frontend *fe)
2208c2ecf20Sopenharmony_ci{
2218c2ecf20Sopenharmony_ci	struct tda827x_priv *priv = fe->tuner_priv;
2228c2ecf20Sopenharmony_ci	static u8 buf[] = { 0x30, 0xd0 };
2238c2ecf20Sopenharmony_ci	struct i2c_msg msg = { .addr = priv->i2c_addr, .flags = 0,
2248c2ecf20Sopenharmony_ci			       .buf = buf, .len = sizeof(buf) };
2258c2ecf20Sopenharmony_ci
2268c2ecf20Sopenharmony_ci	dprintk("%s:\n", __func__);
2278c2ecf20Sopenharmony_ci	tuner_transfer(fe, &msg, 1);
2288c2ecf20Sopenharmony_ci
2298c2ecf20Sopenharmony_ci	if (priv->cfg && priv->cfg->sleep)
2308c2ecf20Sopenharmony_ci		priv->cfg->sleep(fe);
2318c2ecf20Sopenharmony_ci
2328c2ecf20Sopenharmony_ci	return 0;
2338c2ecf20Sopenharmony_ci}
2348c2ecf20Sopenharmony_ci
2358c2ecf20Sopenharmony_ci/* ------------------------------------------------------------------ */
2368c2ecf20Sopenharmony_ci
2378c2ecf20Sopenharmony_cistatic int tda827xo_set_analog_params(struct dvb_frontend *fe,
2388c2ecf20Sopenharmony_ci				      struct analog_parameters *params)
2398c2ecf20Sopenharmony_ci{
2408c2ecf20Sopenharmony_ci	unsigned char tuner_reg[8];
2418c2ecf20Sopenharmony_ci	unsigned char reg2[2];
2428c2ecf20Sopenharmony_ci	u32 N;
2438c2ecf20Sopenharmony_ci	int i;
2448c2ecf20Sopenharmony_ci	struct tda827x_priv *priv = fe->tuner_priv;
2458c2ecf20Sopenharmony_ci	struct i2c_msg msg = { .addr = priv->i2c_addr, .flags = 0 };
2468c2ecf20Sopenharmony_ci	unsigned int freq = params->frequency;
2478c2ecf20Sopenharmony_ci
2488c2ecf20Sopenharmony_ci	tda827x_set_std(fe, params);
2498c2ecf20Sopenharmony_ci
2508c2ecf20Sopenharmony_ci	if (params->mode == V4L2_TUNER_RADIO)
2518c2ecf20Sopenharmony_ci		freq = freq / 1000;
2528c2ecf20Sopenharmony_ci
2538c2ecf20Sopenharmony_ci	N = freq + priv->sgIF;
2548c2ecf20Sopenharmony_ci
2558c2ecf20Sopenharmony_ci	i = 0;
2568c2ecf20Sopenharmony_ci	while (tda827x_table[i].lomax < N * 62500) {
2578c2ecf20Sopenharmony_ci		if (tda827x_table[i + 1].lomax == 0)
2588c2ecf20Sopenharmony_ci			break;
2598c2ecf20Sopenharmony_ci		i++;
2608c2ecf20Sopenharmony_ci	}
2618c2ecf20Sopenharmony_ci
2628c2ecf20Sopenharmony_ci	N = N << tda827x_table[i].spd;
2638c2ecf20Sopenharmony_ci
2648c2ecf20Sopenharmony_ci	tuner_reg[0] = 0;
2658c2ecf20Sopenharmony_ci	tuner_reg[1] = (unsigned char)(N>>8);
2668c2ecf20Sopenharmony_ci	tuner_reg[2] = (unsigned char) N;
2678c2ecf20Sopenharmony_ci	tuner_reg[3] = 0x40;
2688c2ecf20Sopenharmony_ci	tuner_reg[4] = 0x52 + (priv->lpsel << 5);
2698c2ecf20Sopenharmony_ci	tuner_reg[5] = (tda827x_table[i].spd    << 6) +
2708c2ecf20Sopenharmony_ci		       (tda827x_table[i].div1p5 << 5) +
2718c2ecf20Sopenharmony_ci		       (tda827x_table[i].bs     << 3) + tda827x_table[i].bp;
2728c2ecf20Sopenharmony_ci	tuner_reg[6] = 0x8f + (tda827x_table[i].gc3 << 4);
2738c2ecf20Sopenharmony_ci	tuner_reg[7] = 0x8f;
2748c2ecf20Sopenharmony_ci
2758c2ecf20Sopenharmony_ci	msg.buf = tuner_reg;
2768c2ecf20Sopenharmony_ci	msg.len = 8;
2778c2ecf20Sopenharmony_ci	tuner_transfer(fe, &msg, 1);
2788c2ecf20Sopenharmony_ci
2798c2ecf20Sopenharmony_ci	msg.buf = reg2;
2808c2ecf20Sopenharmony_ci	msg.len = 2;
2818c2ecf20Sopenharmony_ci	reg2[0] = 0x80;
2828c2ecf20Sopenharmony_ci	reg2[1] = 0;
2838c2ecf20Sopenharmony_ci	tuner_transfer(fe, &msg, 1);
2848c2ecf20Sopenharmony_ci
2858c2ecf20Sopenharmony_ci	reg2[0] = 0x60;
2868c2ecf20Sopenharmony_ci	reg2[1] = 0xbf;
2878c2ecf20Sopenharmony_ci	tuner_transfer(fe, &msg, 1);
2888c2ecf20Sopenharmony_ci
2898c2ecf20Sopenharmony_ci	reg2[0] = 0x30;
2908c2ecf20Sopenharmony_ci	reg2[1] = tuner_reg[4] + 0x80;
2918c2ecf20Sopenharmony_ci	tuner_transfer(fe, &msg, 1);
2928c2ecf20Sopenharmony_ci
2938c2ecf20Sopenharmony_ci	msleep(1);
2948c2ecf20Sopenharmony_ci	reg2[0] = 0x30;
2958c2ecf20Sopenharmony_ci	reg2[1] = tuner_reg[4] + 4;
2968c2ecf20Sopenharmony_ci	tuner_transfer(fe, &msg, 1);
2978c2ecf20Sopenharmony_ci
2988c2ecf20Sopenharmony_ci	msleep(1);
2998c2ecf20Sopenharmony_ci	reg2[0] = 0x30;
3008c2ecf20Sopenharmony_ci	reg2[1] = tuner_reg[4];
3018c2ecf20Sopenharmony_ci	tuner_transfer(fe, &msg, 1);
3028c2ecf20Sopenharmony_ci
3038c2ecf20Sopenharmony_ci	msleep(550);
3048c2ecf20Sopenharmony_ci	reg2[0] = 0x30;
3058c2ecf20Sopenharmony_ci	reg2[1] = (tuner_reg[4] & 0xfc) + tda827x_table[i].cp;
3068c2ecf20Sopenharmony_ci	tuner_transfer(fe, &msg, 1);
3078c2ecf20Sopenharmony_ci
3088c2ecf20Sopenharmony_ci	reg2[0] = 0x60;
3098c2ecf20Sopenharmony_ci	reg2[1] = 0x3f;
3108c2ecf20Sopenharmony_ci	tuner_transfer(fe, &msg, 1);
3118c2ecf20Sopenharmony_ci
3128c2ecf20Sopenharmony_ci	reg2[0] = 0x80;
3138c2ecf20Sopenharmony_ci	reg2[1] = 0x08;   /* Vsync en */
3148c2ecf20Sopenharmony_ci	tuner_transfer(fe, &msg, 1);
3158c2ecf20Sopenharmony_ci
3168c2ecf20Sopenharmony_ci	priv->frequency = params->frequency;
3178c2ecf20Sopenharmony_ci
3188c2ecf20Sopenharmony_ci	return 0;
3198c2ecf20Sopenharmony_ci}
3208c2ecf20Sopenharmony_ci
3218c2ecf20Sopenharmony_cistatic void tda827xo_agcf(struct dvb_frontend *fe)
3228c2ecf20Sopenharmony_ci{
3238c2ecf20Sopenharmony_ci	struct tda827x_priv *priv = fe->tuner_priv;
3248c2ecf20Sopenharmony_ci	unsigned char data[] = { 0x80, 0x0c };
3258c2ecf20Sopenharmony_ci	struct i2c_msg msg = { .addr = priv->i2c_addr, .flags = 0,
3268c2ecf20Sopenharmony_ci			       .buf = data, .len = 2};
3278c2ecf20Sopenharmony_ci
3288c2ecf20Sopenharmony_ci	tuner_transfer(fe, &msg, 1);
3298c2ecf20Sopenharmony_ci}
3308c2ecf20Sopenharmony_ci
3318c2ecf20Sopenharmony_ci/* ------------------------------------------------------------------ */
3328c2ecf20Sopenharmony_ci
3338c2ecf20Sopenharmony_cistruct tda827xa_data {
3348c2ecf20Sopenharmony_ci	u32 lomax;
3358c2ecf20Sopenharmony_ci	u8  svco;
3368c2ecf20Sopenharmony_ci	u8  spd;
3378c2ecf20Sopenharmony_ci	u8  scr;
3388c2ecf20Sopenharmony_ci	u8  sbs;
3398c2ecf20Sopenharmony_ci	u8  gc3;
3408c2ecf20Sopenharmony_ci};
3418c2ecf20Sopenharmony_ci
3428c2ecf20Sopenharmony_cistatic struct tda827xa_data tda827xa_dvbt[] = {
3438c2ecf20Sopenharmony_ci	{ .lomax =  56875000, .svco = 3, .spd = 4, .scr = 0, .sbs = 0, .gc3 = 1},
3448c2ecf20Sopenharmony_ci	{ .lomax =  67250000, .svco = 0, .spd = 3, .scr = 0, .sbs = 0, .gc3 = 1},
3458c2ecf20Sopenharmony_ci	{ .lomax =  81250000, .svco = 1, .spd = 3, .scr = 0, .sbs = 0, .gc3 = 1},
3468c2ecf20Sopenharmony_ci	{ .lomax =  97500000, .svco = 2, .spd = 3, .scr = 0, .sbs = 0, .gc3 = 1},
3478c2ecf20Sopenharmony_ci	{ .lomax = 113750000, .svco = 3, .spd = 3, .scr = 0, .sbs = 1, .gc3 = 1},
3488c2ecf20Sopenharmony_ci	{ .lomax = 134500000, .svco = 0, .spd = 2, .scr = 0, .sbs = 1, .gc3 = 1},
3498c2ecf20Sopenharmony_ci	{ .lomax = 154000000, .svco = 1, .spd = 2, .scr = 0, .sbs = 1, .gc3 = 1},
3508c2ecf20Sopenharmony_ci	{ .lomax = 162500000, .svco = 1, .spd = 2, .scr = 0, .sbs = 1, .gc3 = 1},
3518c2ecf20Sopenharmony_ci	{ .lomax = 183000000, .svco = 2, .spd = 2, .scr = 0, .sbs = 1, .gc3 = 1},
3528c2ecf20Sopenharmony_ci	{ .lomax = 195000000, .svco = 2, .spd = 2, .scr = 0, .sbs = 2, .gc3 = 1},
3538c2ecf20Sopenharmony_ci	{ .lomax = 227500000, .svco = 3, .spd = 2, .scr = 0, .sbs = 2, .gc3 = 1},
3548c2ecf20Sopenharmony_ci	{ .lomax = 269000000, .svco = 0, .spd = 1, .scr = 0, .sbs = 2, .gc3 = 1},
3558c2ecf20Sopenharmony_ci	{ .lomax = 290000000, .svco = 1, .spd = 1, .scr = 0, .sbs = 2, .gc3 = 1},
3568c2ecf20Sopenharmony_ci	{ .lomax = 325000000, .svco = 1, .spd = 1, .scr = 0, .sbs = 3, .gc3 = 1},
3578c2ecf20Sopenharmony_ci	{ .lomax = 390000000, .svco = 2, .spd = 1, .scr = 0, .sbs = 3, .gc3 = 1},
3588c2ecf20Sopenharmony_ci	{ .lomax = 455000000, .svco = 3, .spd = 1, .scr = 0, .sbs = 3, .gc3 = 1},
3598c2ecf20Sopenharmony_ci	{ .lomax = 520000000, .svco = 0, .spd = 0, .scr = 0, .sbs = 3, .gc3 = 1},
3608c2ecf20Sopenharmony_ci	{ .lomax = 538000000, .svco = 0, .spd = 0, .scr = 1, .sbs = 3, .gc3 = 1},
3618c2ecf20Sopenharmony_ci	{ .lomax = 550000000, .svco = 1, .spd = 0, .scr = 0, .sbs = 3, .gc3 = 1},
3628c2ecf20Sopenharmony_ci	{ .lomax = 620000000, .svco = 1, .spd = 0, .scr = 0, .sbs = 4, .gc3 = 0},
3638c2ecf20Sopenharmony_ci	{ .lomax = 650000000, .svco = 1, .spd = 0, .scr = 1, .sbs = 4, .gc3 = 0},
3648c2ecf20Sopenharmony_ci	{ .lomax = 700000000, .svco = 2, .spd = 0, .scr = 0, .sbs = 4, .gc3 = 0},
3658c2ecf20Sopenharmony_ci	{ .lomax = 780000000, .svco = 2, .spd = 0, .scr = 1, .sbs = 4, .gc3 = 0},
3668c2ecf20Sopenharmony_ci	{ .lomax = 820000000, .svco = 3, .spd = 0, .scr = 0, .sbs = 4, .gc3 = 0},
3678c2ecf20Sopenharmony_ci	{ .lomax = 870000000, .svco = 3, .spd = 0, .scr = 1, .sbs = 4, .gc3 = 0},
3688c2ecf20Sopenharmony_ci	{ .lomax = 911000000, .svco = 3, .spd = 0, .scr = 2, .sbs = 4, .gc3 = 0},
3698c2ecf20Sopenharmony_ci	{ .lomax =         0, .svco = 0, .spd = 0, .scr = 0, .sbs = 0, .gc3 = 0}
3708c2ecf20Sopenharmony_ci};
3718c2ecf20Sopenharmony_ci
3728c2ecf20Sopenharmony_cistatic struct tda827xa_data tda827xa_dvbc[] = {
3738c2ecf20Sopenharmony_ci	{ .lomax =  50125000, .svco = 2, .spd = 4, .scr = 2, .sbs = 0, .gc3 = 3},
3748c2ecf20Sopenharmony_ci	{ .lomax =  58500000, .svco = 3, .spd = 4, .scr = 2, .sbs = 0, .gc3 = 3},
3758c2ecf20Sopenharmony_ci	{ .lomax =  69250000, .svco = 0, .spd = 3, .scr = 2, .sbs = 0, .gc3 = 3},
3768c2ecf20Sopenharmony_ci	{ .lomax =  83625000, .svco = 1, .spd = 3, .scr = 2, .sbs = 0, .gc3 = 3},
3778c2ecf20Sopenharmony_ci	{ .lomax =  97500000, .svco = 2, .spd = 3, .scr = 2, .sbs = 0, .gc3 = 3},
3788c2ecf20Sopenharmony_ci	{ .lomax = 100250000, .svco = 2, .spd = 3, .scr = 2, .sbs = 1, .gc3 = 1},
3798c2ecf20Sopenharmony_ci	{ .lomax = 117000000, .svco = 3, .spd = 3, .scr = 2, .sbs = 1, .gc3 = 1},
3808c2ecf20Sopenharmony_ci	{ .lomax = 138500000, .svco = 0, .spd = 2, .scr = 2, .sbs = 1, .gc3 = 1},
3818c2ecf20Sopenharmony_ci	{ .lomax = 167250000, .svco = 1, .spd = 2, .scr = 2, .sbs = 1, .gc3 = 1},
3828c2ecf20Sopenharmony_ci	{ .lomax = 187000000, .svco = 2, .spd = 2, .scr = 2, .sbs = 1, .gc3 = 1},
3838c2ecf20Sopenharmony_ci	{ .lomax = 200500000, .svco = 2, .spd = 2, .scr = 2, .sbs = 2, .gc3 = 1},
3848c2ecf20Sopenharmony_ci	{ .lomax = 234000000, .svco = 3, .spd = 2, .scr = 2, .sbs = 2, .gc3 = 3},
3858c2ecf20Sopenharmony_ci	{ .lomax = 277000000, .svco = 0, .spd = 1, .scr = 2, .sbs = 2, .gc3 = 3},
3868c2ecf20Sopenharmony_ci	{ .lomax = 325000000, .svco = 1, .spd = 1, .scr = 2, .sbs = 2, .gc3 = 1},
3878c2ecf20Sopenharmony_ci	{ .lomax = 334500000, .svco = 1, .spd = 1, .scr = 2, .sbs = 3, .gc3 = 3},
3888c2ecf20Sopenharmony_ci	{ .lomax = 401000000, .svco = 2, .spd = 1, .scr = 2, .sbs = 3, .gc3 = 3},
3898c2ecf20Sopenharmony_ci	{ .lomax = 468000000, .svco = 3, .spd = 1, .scr = 2, .sbs = 3, .gc3 = 1},
3908c2ecf20Sopenharmony_ci	{ .lomax = 535000000, .svco = 0, .spd = 0, .scr = 1, .sbs = 3, .gc3 = 1},
3918c2ecf20Sopenharmony_ci	{ .lomax = 554000000, .svco = 0, .spd = 0, .scr = 2, .sbs = 3, .gc3 = 1},
3928c2ecf20Sopenharmony_ci	{ .lomax = 638000000, .svco = 1, .spd = 0, .scr = 1, .sbs = 4, .gc3 = 1},
3938c2ecf20Sopenharmony_ci	{ .lomax = 669000000, .svco = 1, .spd = 0, .scr = 2, .sbs = 4, .gc3 = 1},
3948c2ecf20Sopenharmony_ci	{ .lomax = 720000000, .svco = 2, .spd = 0, .scr = 1, .sbs = 4, .gc3 = 1},
3958c2ecf20Sopenharmony_ci	{ .lomax = 802000000, .svco = 2, .spd = 0, .scr = 2, .sbs = 4, .gc3 = 1},
3968c2ecf20Sopenharmony_ci	{ .lomax = 835000000, .svco = 3, .spd = 0, .scr = 1, .sbs = 4, .gc3 = 1},
3978c2ecf20Sopenharmony_ci	{ .lomax = 885000000, .svco = 3, .spd = 0, .scr = 1, .sbs = 4, .gc3 = 1},
3988c2ecf20Sopenharmony_ci	{ .lomax = 911000000, .svco = 3, .spd = 0, .scr = 2, .sbs = 4, .gc3 = 1},
3998c2ecf20Sopenharmony_ci	{ .lomax =         0, .svco = 0, .spd = 0, .scr = 0, .sbs = 0, .gc3 = 0}
4008c2ecf20Sopenharmony_ci};
4018c2ecf20Sopenharmony_ci
4028c2ecf20Sopenharmony_cistatic struct tda827xa_data tda827xa_analog[] = {
4038c2ecf20Sopenharmony_ci	{ .lomax =  56875000, .svco = 3, .spd = 4, .scr = 0, .sbs = 0, .gc3 = 3},
4048c2ecf20Sopenharmony_ci	{ .lomax =  67250000, .svco = 0, .spd = 3, .scr = 0, .sbs = 0, .gc3 = 3},
4058c2ecf20Sopenharmony_ci	{ .lomax =  81250000, .svco = 1, .spd = 3, .scr = 0, .sbs = 0, .gc3 = 3},
4068c2ecf20Sopenharmony_ci	{ .lomax =  97500000, .svco = 2, .spd = 3, .scr = 0, .sbs = 0, .gc3 = 3},
4078c2ecf20Sopenharmony_ci	{ .lomax = 113750000, .svco = 3, .spd = 3, .scr = 0, .sbs = 1, .gc3 = 1},
4088c2ecf20Sopenharmony_ci	{ .lomax = 134500000, .svco = 0, .spd = 2, .scr = 0, .sbs = 1, .gc3 = 1},
4098c2ecf20Sopenharmony_ci	{ .lomax = 154000000, .svco = 1, .spd = 2, .scr = 0, .sbs = 1, .gc3 = 1},
4108c2ecf20Sopenharmony_ci	{ .lomax = 162500000, .svco = 1, .spd = 2, .scr = 0, .sbs = 1, .gc3 = 1},
4118c2ecf20Sopenharmony_ci	{ .lomax = 183000000, .svco = 2, .spd = 2, .scr = 0, .sbs = 1, .gc3 = 1},
4128c2ecf20Sopenharmony_ci	{ .lomax = 195000000, .svco = 2, .spd = 2, .scr = 0, .sbs = 2, .gc3 = 1},
4138c2ecf20Sopenharmony_ci	{ .lomax = 227500000, .svco = 3, .spd = 2, .scr = 0, .sbs = 2, .gc3 = 3},
4148c2ecf20Sopenharmony_ci	{ .lomax = 269000000, .svco = 0, .spd = 1, .scr = 0, .sbs = 2, .gc3 = 3},
4158c2ecf20Sopenharmony_ci	{ .lomax = 325000000, .svco = 1, .spd = 1, .scr = 0, .sbs = 2, .gc3 = 1},
4168c2ecf20Sopenharmony_ci	{ .lomax = 390000000, .svco = 2, .spd = 1, .scr = 0, .sbs = 3, .gc3 = 3},
4178c2ecf20Sopenharmony_ci	{ .lomax = 455000000, .svco = 3, .spd = 1, .scr = 0, .sbs = 3, .gc3 = 3},
4188c2ecf20Sopenharmony_ci	{ .lomax = 520000000, .svco = 0, .spd = 0, .scr = 0, .sbs = 3, .gc3 = 1},
4198c2ecf20Sopenharmony_ci	{ .lomax = 538000000, .svco = 0, .spd = 0, .scr = 1, .sbs = 3, .gc3 = 1},
4208c2ecf20Sopenharmony_ci	{ .lomax = 554000000, .svco = 1, .spd = 0, .scr = 0, .sbs = 3, .gc3 = 1},
4218c2ecf20Sopenharmony_ci	{ .lomax = 620000000, .svco = 1, .spd = 0, .scr = 0, .sbs = 4, .gc3 = 0},
4228c2ecf20Sopenharmony_ci	{ .lomax = 650000000, .svco = 1, .spd = 0, .scr = 1, .sbs = 4, .gc3 = 0},
4238c2ecf20Sopenharmony_ci	{ .lomax = 700000000, .svco = 2, .spd = 0, .scr = 0, .sbs = 4, .gc3 = 0},
4248c2ecf20Sopenharmony_ci	{ .lomax = 780000000, .svco = 2, .spd = 0, .scr = 1, .sbs = 4, .gc3 = 0},
4258c2ecf20Sopenharmony_ci	{ .lomax = 820000000, .svco = 3, .spd = 0, .scr = 0, .sbs = 4, .gc3 = 0},
4268c2ecf20Sopenharmony_ci	{ .lomax = 870000000, .svco = 3, .spd = 0, .scr = 1, .sbs = 4, .gc3 = 0},
4278c2ecf20Sopenharmony_ci	{ .lomax = 911000000, .svco = 3, .spd = 0, .scr = 2, .sbs = 4, .gc3 = 0},
4288c2ecf20Sopenharmony_ci	{ .lomax =         0, .svco = 0, .spd = 0, .scr = 0, .sbs = 0, .gc3 = 0}
4298c2ecf20Sopenharmony_ci};
4308c2ecf20Sopenharmony_ci
4318c2ecf20Sopenharmony_cistatic int tda827xa_sleep(struct dvb_frontend *fe)
4328c2ecf20Sopenharmony_ci{
4338c2ecf20Sopenharmony_ci	struct tda827x_priv *priv = fe->tuner_priv;
4348c2ecf20Sopenharmony_ci	static u8 buf[] = { 0x30, 0x90 };
4358c2ecf20Sopenharmony_ci	struct i2c_msg msg = { .addr = priv->i2c_addr, .flags = 0,
4368c2ecf20Sopenharmony_ci			       .buf = buf, .len = sizeof(buf) };
4378c2ecf20Sopenharmony_ci
4388c2ecf20Sopenharmony_ci	dprintk("%s:\n", __func__);
4398c2ecf20Sopenharmony_ci
4408c2ecf20Sopenharmony_ci	tuner_transfer(fe, &msg, 1);
4418c2ecf20Sopenharmony_ci
4428c2ecf20Sopenharmony_ci	if (priv->cfg && priv->cfg->sleep)
4438c2ecf20Sopenharmony_ci		priv->cfg->sleep(fe);
4448c2ecf20Sopenharmony_ci
4458c2ecf20Sopenharmony_ci	return 0;
4468c2ecf20Sopenharmony_ci}
4478c2ecf20Sopenharmony_ci
4488c2ecf20Sopenharmony_cistatic void tda827xa_lna_gain(struct dvb_frontend *fe, int high,
4498c2ecf20Sopenharmony_ci			      struct analog_parameters *params)
4508c2ecf20Sopenharmony_ci{
4518c2ecf20Sopenharmony_ci	struct tda827x_priv *priv = fe->tuner_priv;
4528c2ecf20Sopenharmony_ci	unsigned char buf[] = {0x22, 0x01};
4538c2ecf20Sopenharmony_ci	int arg;
4548c2ecf20Sopenharmony_ci	int gp_func;
4558c2ecf20Sopenharmony_ci	struct i2c_msg msg = { .flags = 0, .buf = buf, .len = sizeof(buf) };
4568c2ecf20Sopenharmony_ci
4578c2ecf20Sopenharmony_ci	if (NULL == priv->cfg) {
4588c2ecf20Sopenharmony_ci		dprintk("tda827x_config not defined, cannot set LNA gain!\n");
4598c2ecf20Sopenharmony_ci		return;
4608c2ecf20Sopenharmony_ci	}
4618c2ecf20Sopenharmony_ci	msg.addr = priv->cfg->switch_addr;
4628c2ecf20Sopenharmony_ci	if (priv->cfg->config) {
4638c2ecf20Sopenharmony_ci		if (high)
4648c2ecf20Sopenharmony_ci			dprintk("setting LNA to high gain\n");
4658c2ecf20Sopenharmony_ci		else
4668c2ecf20Sopenharmony_ci			dprintk("setting LNA to low gain\n");
4678c2ecf20Sopenharmony_ci	}
4688c2ecf20Sopenharmony_ci	switch (priv->cfg->config) {
4698c2ecf20Sopenharmony_ci	case TDA8290_LNA_OFF: /* no LNA */
4708c2ecf20Sopenharmony_ci		break;
4718c2ecf20Sopenharmony_ci	case TDA8290_LNA_GP0_HIGH_ON: /* switch is GPIO 0 of tda8290 */
4728c2ecf20Sopenharmony_ci	case TDA8290_LNA_GP0_HIGH_OFF:
4738c2ecf20Sopenharmony_ci		if (params == NULL) {
4748c2ecf20Sopenharmony_ci			gp_func = 0;
4758c2ecf20Sopenharmony_ci			arg  = 0;
4768c2ecf20Sopenharmony_ci		} else {
4778c2ecf20Sopenharmony_ci			/* turn Vsync on */
4788c2ecf20Sopenharmony_ci			gp_func = 1;
4798c2ecf20Sopenharmony_ci			if (params->std & V4L2_STD_MN)
4808c2ecf20Sopenharmony_ci				arg = 1;
4818c2ecf20Sopenharmony_ci			else
4828c2ecf20Sopenharmony_ci				arg = 0;
4838c2ecf20Sopenharmony_ci		}
4848c2ecf20Sopenharmony_ci		if (fe->callback)
4858c2ecf20Sopenharmony_ci			fe->callback(priv->i2c_adap->algo_data,
4868c2ecf20Sopenharmony_ci				     DVB_FRONTEND_COMPONENT_TUNER,
4878c2ecf20Sopenharmony_ci				     gp_func, arg);
4888c2ecf20Sopenharmony_ci		buf[1] = high ? 0 : 1;
4898c2ecf20Sopenharmony_ci		if (priv->cfg->config == TDA8290_LNA_GP0_HIGH_OFF)
4908c2ecf20Sopenharmony_ci			buf[1] = high ? 1 : 0;
4918c2ecf20Sopenharmony_ci		tuner_transfer(fe, &msg, 1);
4928c2ecf20Sopenharmony_ci		break;
4938c2ecf20Sopenharmony_ci	case TDA8290_LNA_ON_BRIDGE: /* switch with GPIO of saa713x */
4948c2ecf20Sopenharmony_ci		if (fe->callback)
4958c2ecf20Sopenharmony_ci			fe->callback(priv->i2c_adap->algo_data,
4968c2ecf20Sopenharmony_ci				     DVB_FRONTEND_COMPONENT_TUNER, 0, high);
4978c2ecf20Sopenharmony_ci		break;
4988c2ecf20Sopenharmony_ci	}
4998c2ecf20Sopenharmony_ci}
5008c2ecf20Sopenharmony_ci
5018c2ecf20Sopenharmony_cistatic int tda827xa_set_params(struct dvb_frontend *fe)
5028c2ecf20Sopenharmony_ci{
5038c2ecf20Sopenharmony_ci	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
5048c2ecf20Sopenharmony_ci	struct tda827x_priv *priv = fe->tuner_priv;
5058c2ecf20Sopenharmony_ci	struct tda827xa_data *frequency_map = tda827xa_dvbt;
5068c2ecf20Sopenharmony_ci	u8 buf[11];
5078c2ecf20Sopenharmony_ci
5088c2ecf20Sopenharmony_ci	struct i2c_msg msg = { .addr = priv->i2c_addr, .flags = 0,
5098c2ecf20Sopenharmony_ci			       .buf = buf, .len = sizeof(buf) };
5108c2ecf20Sopenharmony_ci
5118c2ecf20Sopenharmony_ci	int i, tuner_freq, if_freq, rc;
5128c2ecf20Sopenharmony_ci	u32 N;
5138c2ecf20Sopenharmony_ci
5148c2ecf20Sopenharmony_ci	dprintk("%s:\n", __func__);
5158c2ecf20Sopenharmony_ci
5168c2ecf20Sopenharmony_ci	tda827xa_lna_gain(fe, 1, NULL);
5178c2ecf20Sopenharmony_ci	msleep(20);
5188c2ecf20Sopenharmony_ci
5198c2ecf20Sopenharmony_ci	if (c->bandwidth_hz == 0) {
5208c2ecf20Sopenharmony_ci		if_freq = 5000000;
5218c2ecf20Sopenharmony_ci	} else if (c->bandwidth_hz <= 6000000) {
5228c2ecf20Sopenharmony_ci		if_freq = 4000000;
5238c2ecf20Sopenharmony_ci	} else if (c->bandwidth_hz <= 7000000) {
5248c2ecf20Sopenharmony_ci		if_freq = 4500000;
5258c2ecf20Sopenharmony_ci	} else {	/* 8 MHz */
5268c2ecf20Sopenharmony_ci		if_freq = 5000000;
5278c2ecf20Sopenharmony_ci	}
5288c2ecf20Sopenharmony_ci	tuner_freq = c->frequency;
5298c2ecf20Sopenharmony_ci
5308c2ecf20Sopenharmony_ci	switch (c->delivery_system) {
5318c2ecf20Sopenharmony_ci	case SYS_DVBC_ANNEX_A:
5328c2ecf20Sopenharmony_ci	case SYS_DVBC_ANNEX_C:
5338c2ecf20Sopenharmony_ci		dprintk("%s select tda827xa_dvbc\n", __func__);
5348c2ecf20Sopenharmony_ci		frequency_map = tda827xa_dvbc;
5358c2ecf20Sopenharmony_ci		break;
5368c2ecf20Sopenharmony_ci	default:
5378c2ecf20Sopenharmony_ci		break;
5388c2ecf20Sopenharmony_ci	}
5398c2ecf20Sopenharmony_ci
5408c2ecf20Sopenharmony_ci	i = 0;
5418c2ecf20Sopenharmony_ci	while (frequency_map[i].lomax < tuner_freq) {
5428c2ecf20Sopenharmony_ci		if (frequency_map[i + 1].lomax == 0)
5438c2ecf20Sopenharmony_ci			break;
5448c2ecf20Sopenharmony_ci		i++;
5458c2ecf20Sopenharmony_ci	}
5468c2ecf20Sopenharmony_ci
5478c2ecf20Sopenharmony_ci	tuner_freq += if_freq;
5488c2ecf20Sopenharmony_ci
5498c2ecf20Sopenharmony_ci	N = ((tuner_freq + 31250) / 62500) << frequency_map[i].spd;
5508c2ecf20Sopenharmony_ci	buf[0] = 0;            // subaddress
5518c2ecf20Sopenharmony_ci	buf[1] = N >> 8;
5528c2ecf20Sopenharmony_ci	buf[2] = N & 0xff;
5538c2ecf20Sopenharmony_ci	buf[3] = 0;
5548c2ecf20Sopenharmony_ci	buf[4] = 0x16;
5558c2ecf20Sopenharmony_ci	buf[5] = (frequency_map[i].spd << 5) + (frequency_map[i].svco << 3) +
5568c2ecf20Sopenharmony_ci			frequency_map[i].sbs;
5578c2ecf20Sopenharmony_ci	buf[6] = 0x4b + (frequency_map[i].gc3 << 4);
5588c2ecf20Sopenharmony_ci	buf[7] = 0x1c;
5598c2ecf20Sopenharmony_ci	buf[8] = 0x06;
5608c2ecf20Sopenharmony_ci	buf[9] = 0x24;
5618c2ecf20Sopenharmony_ci	buf[10] = 0x00;
5628c2ecf20Sopenharmony_ci	msg.len = 11;
5638c2ecf20Sopenharmony_ci	rc = tuner_transfer(fe, &msg, 1);
5648c2ecf20Sopenharmony_ci	if (rc < 0)
5658c2ecf20Sopenharmony_ci		goto err;
5668c2ecf20Sopenharmony_ci
5678c2ecf20Sopenharmony_ci	buf[0] = 0x90;
5688c2ecf20Sopenharmony_ci	buf[1] = 0xff;
5698c2ecf20Sopenharmony_ci	buf[2] = 0x60;
5708c2ecf20Sopenharmony_ci	buf[3] = 0x00;
5718c2ecf20Sopenharmony_ci	buf[4] = 0x59;  // lpsel, for 6MHz + 2
5728c2ecf20Sopenharmony_ci	msg.len = 5;
5738c2ecf20Sopenharmony_ci	rc = tuner_transfer(fe, &msg, 1);
5748c2ecf20Sopenharmony_ci	if (rc < 0)
5758c2ecf20Sopenharmony_ci		goto err;
5768c2ecf20Sopenharmony_ci
5778c2ecf20Sopenharmony_ci	buf[0] = 0xa0;
5788c2ecf20Sopenharmony_ci	buf[1] = 0x40;
5798c2ecf20Sopenharmony_ci	msg.len = 2;
5808c2ecf20Sopenharmony_ci	rc = tuner_transfer(fe, &msg, 1);
5818c2ecf20Sopenharmony_ci	if (rc < 0)
5828c2ecf20Sopenharmony_ci		goto err;
5838c2ecf20Sopenharmony_ci
5848c2ecf20Sopenharmony_ci	msleep(11);
5858c2ecf20Sopenharmony_ci	msg.flags = I2C_M_RD;
5868c2ecf20Sopenharmony_ci	rc = tuner_transfer(fe, &msg, 1);
5878c2ecf20Sopenharmony_ci	if (rc < 0)
5888c2ecf20Sopenharmony_ci		goto err;
5898c2ecf20Sopenharmony_ci	msg.flags = 0;
5908c2ecf20Sopenharmony_ci
5918c2ecf20Sopenharmony_ci	buf[1] >>= 4;
5928c2ecf20Sopenharmony_ci	dprintk("tda8275a AGC2 gain is: %d\n", buf[1]);
5938c2ecf20Sopenharmony_ci	if ((buf[1]) < 2) {
5948c2ecf20Sopenharmony_ci		tda827xa_lna_gain(fe, 0, NULL);
5958c2ecf20Sopenharmony_ci		buf[0] = 0x60;
5968c2ecf20Sopenharmony_ci		buf[1] = 0x0c;
5978c2ecf20Sopenharmony_ci		rc = tuner_transfer(fe, &msg, 1);
5988c2ecf20Sopenharmony_ci		if (rc < 0)
5998c2ecf20Sopenharmony_ci			goto err;
6008c2ecf20Sopenharmony_ci	}
6018c2ecf20Sopenharmony_ci
6028c2ecf20Sopenharmony_ci	buf[0] = 0xc0;
6038c2ecf20Sopenharmony_ci	buf[1] = 0x99;    // lpsel, for 6MHz + 2
6048c2ecf20Sopenharmony_ci	rc = tuner_transfer(fe, &msg, 1);
6058c2ecf20Sopenharmony_ci	if (rc < 0)
6068c2ecf20Sopenharmony_ci		goto err;
6078c2ecf20Sopenharmony_ci
6088c2ecf20Sopenharmony_ci	buf[0] = 0x60;
6098c2ecf20Sopenharmony_ci	buf[1] = 0x3c;
6108c2ecf20Sopenharmony_ci	rc = tuner_transfer(fe, &msg, 1);
6118c2ecf20Sopenharmony_ci	if (rc < 0)
6128c2ecf20Sopenharmony_ci		goto err;
6138c2ecf20Sopenharmony_ci
6148c2ecf20Sopenharmony_ci	/* correct CP value */
6158c2ecf20Sopenharmony_ci	buf[0] = 0x30;
6168c2ecf20Sopenharmony_ci	buf[1] = 0x10 + frequency_map[i].scr;
6178c2ecf20Sopenharmony_ci	rc = tuner_transfer(fe, &msg, 1);
6188c2ecf20Sopenharmony_ci	if (rc < 0)
6198c2ecf20Sopenharmony_ci		goto err;
6208c2ecf20Sopenharmony_ci
6218c2ecf20Sopenharmony_ci	msleep(163);
6228c2ecf20Sopenharmony_ci	buf[0] = 0xc0;
6238c2ecf20Sopenharmony_ci	buf[1] = 0x39;  // lpsel, for 6MHz + 2
6248c2ecf20Sopenharmony_ci	rc = tuner_transfer(fe, &msg, 1);
6258c2ecf20Sopenharmony_ci	if (rc < 0)
6268c2ecf20Sopenharmony_ci		goto err;
6278c2ecf20Sopenharmony_ci
6288c2ecf20Sopenharmony_ci	msleep(3);
6298c2ecf20Sopenharmony_ci	/* freeze AGC1 */
6308c2ecf20Sopenharmony_ci	buf[0] = 0x50;
6318c2ecf20Sopenharmony_ci	buf[1] = 0x4f + (frequency_map[i].gc3 << 4);
6328c2ecf20Sopenharmony_ci	rc = tuner_transfer(fe, &msg, 1);
6338c2ecf20Sopenharmony_ci	if (rc < 0)
6348c2ecf20Sopenharmony_ci		goto err;
6358c2ecf20Sopenharmony_ci
6368c2ecf20Sopenharmony_ci	priv->frequency = c->frequency;
6378c2ecf20Sopenharmony_ci	priv->bandwidth = c->bandwidth_hz;
6388c2ecf20Sopenharmony_ci
6398c2ecf20Sopenharmony_ci	return 0;
6408c2ecf20Sopenharmony_ci
6418c2ecf20Sopenharmony_cierr:
6428c2ecf20Sopenharmony_ci	printk(KERN_ERR "%s: could not write to tuner at addr: 0x%02x\n",
6438c2ecf20Sopenharmony_ci	       __func__, priv->i2c_addr << 1);
6448c2ecf20Sopenharmony_ci	return rc;
6458c2ecf20Sopenharmony_ci}
6468c2ecf20Sopenharmony_ci
6478c2ecf20Sopenharmony_ci
6488c2ecf20Sopenharmony_cistatic int tda827xa_set_analog_params(struct dvb_frontend *fe,
6498c2ecf20Sopenharmony_ci				      struct analog_parameters *params)
6508c2ecf20Sopenharmony_ci{
6518c2ecf20Sopenharmony_ci	unsigned char tuner_reg[11];
6528c2ecf20Sopenharmony_ci	u32 N;
6538c2ecf20Sopenharmony_ci	int i;
6548c2ecf20Sopenharmony_ci	struct tda827x_priv *priv = fe->tuner_priv;
6558c2ecf20Sopenharmony_ci	struct i2c_msg msg = { .addr = priv->i2c_addr, .flags = 0,
6568c2ecf20Sopenharmony_ci			       .buf = tuner_reg, .len = sizeof(tuner_reg) };
6578c2ecf20Sopenharmony_ci	unsigned int freq = params->frequency;
6588c2ecf20Sopenharmony_ci
6598c2ecf20Sopenharmony_ci	tda827x_set_std(fe, params);
6608c2ecf20Sopenharmony_ci
6618c2ecf20Sopenharmony_ci	tda827xa_lna_gain(fe, 1, params);
6628c2ecf20Sopenharmony_ci	msleep(10);
6638c2ecf20Sopenharmony_ci
6648c2ecf20Sopenharmony_ci	if (params->mode == V4L2_TUNER_RADIO)
6658c2ecf20Sopenharmony_ci		freq = freq / 1000;
6668c2ecf20Sopenharmony_ci
6678c2ecf20Sopenharmony_ci	N = freq + priv->sgIF;
6688c2ecf20Sopenharmony_ci
6698c2ecf20Sopenharmony_ci	i = 0;
6708c2ecf20Sopenharmony_ci	while (tda827xa_analog[i].lomax < N * 62500) {
6718c2ecf20Sopenharmony_ci		if (tda827xa_analog[i + 1].lomax == 0)
6728c2ecf20Sopenharmony_ci			break;
6738c2ecf20Sopenharmony_ci		i++;
6748c2ecf20Sopenharmony_ci	}
6758c2ecf20Sopenharmony_ci
6768c2ecf20Sopenharmony_ci	N = N << tda827xa_analog[i].spd;
6778c2ecf20Sopenharmony_ci
6788c2ecf20Sopenharmony_ci	tuner_reg[0] = 0;
6798c2ecf20Sopenharmony_ci	tuner_reg[1] = (unsigned char)(N>>8);
6808c2ecf20Sopenharmony_ci	tuner_reg[2] = (unsigned char) N;
6818c2ecf20Sopenharmony_ci	tuner_reg[3] = 0;
6828c2ecf20Sopenharmony_ci	tuner_reg[4] = 0x16;
6838c2ecf20Sopenharmony_ci	tuner_reg[5] = (tda827xa_analog[i].spd << 5) +
6848c2ecf20Sopenharmony_ci		       (tda827xa_analog[i].svco << 3) +
6858c2ecf20Sopenharmony_ci			tda827xa_analog[i].sbs;
6868c2ecf20Sopenharmony_ci	tuner_reg[6] = 0x8b + (tda827xa_analog[i].gc3 << 4);
6878c2ecf20Sopenharmony_ci	tuner_reg[7] = 0x1c;
6888c2ecf20Sopenharmony_ci	tuner_reg[8] = 4;
6898c2ecf20Sopenharmony_ci	tuner_reg[9] = 0x20;
6908c2ecf20Sopenharmony_ci	tuner_reg[10] = 0x00;
6918c2ecf20Sopenharmony_ci	msg.len = 11;
6928c2ecf20Sopenharmony_ci	tuner_transfer(fe, &msg, 1);
6938c2ecf20Sopenharmony_ci
6948c2ecf20Sopenharmony_ci	tuner_reg[0] = 0x90;
6958c2ecf20Sopenharmony_ci	tuner_reg[1] = 0xff;
6968c2ecf20Sopenharmony_ci	tuner_reg[2] = 0xe0;
6978c2ecf20Sopenharmony_ci	tuner_reg[3] = 0;
6988c2ecf20Sopenharmony_ci	tuner_reg[4] = 0x99 + (priv->lpsel << 1);
6998c2ecf20Sopenharmony_ci	msg.len = 5;
7008c2ecf20Sopenharmony_ci	tuner_transfer(fe, &msg, 1);
7018c2ecf20Sopenharmony_ci
7028c2ecf20Sopenharmony_ci	tuner_reg[0] = 0xa0;
7038c2ecf20Sopenharmony_ci	tuner_reg[1] = 0xc0;
7048c2ecf20Sopenharmony_ci	msg.len = 2;
7058c2ecf20Sopenharmony_ci	tuner_transfer(fe, &msg, 1);
7068c2ecf20Sopenharmony_ci
7078c2ecf20Sopenharmony_ci	tuner_reg[0] = 0x30;
7088c2ecf20Sopenharmony_ci	tuner_reg[1] = 0x10 + tda827xa_analog[i].scr;
7098c2ecf20Sopenharmony_ci	tuner_transfer(fe, &msg, 1);
7108c2ecf20Sopenharmony_ci
7118c2ecf20Sopenharmony_ci	msg.flags = I2C_M_RD;
7128c2ecf20Sopenharmony_ci	tuner_transfer(fe, &msg, 1);
7138c2ecf20Sopenharmony_ci	msg.flags = 0;
7148c2ecf20Sopenharmony_ci	tuner_reg[1] >>= 4;
7158c2ecf20Sopenharmony_ci	dprintk("AGC2 gain is: %d\n", tuner_reg[1]);
7168c2ecf20Sopenharmony_ci	if (tuner_reg[1] < 1)
7178c2ecf20Sopenharmony_ci		tda827xa_lna_gain(fe, 0, params);
7188c2ecf20Sopenharmony_ci
7198c2ecf20Sopenharmony_ci	msleep(100);
7208c2ecf20Sopenharmony_ci	tuner_reg[0] = 0x60;
7218c2ecf20Sopenharmony_ci	tuner_reg[1] = 0x3c;
7228c2ecf20Sopenharmony_ci	tuner_transfer(fe, &msg, 1);
7238c2ecf20Sopenharmony_ci
7248c2ecf20Sopenharmony_ci	msleep(163);
7258c2ecf20Sopenharmony_ci	tuner_reg[0] = 0x50;
7268c2ecf20Sopenharmony_ci	tuner_reg[1] = 0x8f + (tda827xa_analog[i].gc3 << 4);
7278c2ecf20Sopenharmony_ci	tuner_transfer(fe, &msg, 1);
7288c2ecf20Sopenharmony_ci
7298c2ecf20Sopenharmony_ci	tuner_reg[0] = 0x80;
7308c2ecf20Sopenharmony_ci	tuner_reg[1] = 0x28;
7318c2ecf20Sopenharmony_ci	tuner_transfer(fe, &msg, 1);
7328c2ecf20Sopenharmony_ci
7338c2ecf20Sopenharmony_ci	tuner_reg[0] = 0xb0;
7348c2ecf20Sopenharmony_ci	tuner_reg[1] = 0x01;
7358c2ecf20Sopenharmony_ci	tuner_transfer(fe, &msg, 1);
7368c2ecf20Sopenharmony_ci
7378c2ecf20Sopenharmony_ci	tuner_reg[0] = 0xc0;
7388c2ecf20Sopenharmony_ci	tuner_reg[1] = 0x19 + (priv->lpsel << 1);
7398c2ecf20Sopenharmony_ci	tuner_transfer(fe, &msg, 1);
7408c2ecf20Sopenharmony_ci
7418c2ecf20Sopenharmony_ci	priv->frequency = params->frequency;
7428c2ecf20Sopenharmony_ci
7438c2ecf20Sopenharmony_ci	return 0;
7448c2ecf20Sopenharmony_ci}
7458c2ecf20Sopenharmony_ci
7468c2ecf20Sopenharmony_cistatic void tda827xa_agcf(struct dvb_frontend *fe)
7478c2ecf20Sopenharmony_ci{
7488c2ecf20Sopenharmony_ci	struct tda827x_priv *priv = fe->tuner_priv;
7498c2ecf20Sopenharmony_ci	unsigned char data[] = {0x80, 0x2c};
7508c2ecf20Sopenharmony_ci	struct i2c_msg msg = {.addr = priv->i2c_addr, .flags = 0,
7518c2ecf20Sopenharmony_ci			      .buf = data, .len = 2};
7528c2ecf20Sopenharmony_ci	tuner_transfer(fe, &msg, 1);
7538c2ecf20Sopenharmony_ci}
7548c2ecf20Sopenharmony_ci
7558c2ecf20Sopenharmony_ci/* ------------------------------------------------------------------ */
7568c2ecf20Sopenharmony_ci
7578c2ecf20Sopenharmony_cistatic void tda827x_release(struct dvb_frontend *fe)
7588c2ecf20Sopenharmony_ci{
7598c2ecf20Sopenharmony_ci	kfree(fe->tuner_priv);
7608c2ecf20Sopenharmony_ci	fe->tuner_priv = NULL;
7618c2ecf20Sopenharmony_ci}
7628c2ecf20Sopenharmony_ci
7638c2ecf20Sopenharmony_cistatic int tda827x_get_frequency(struct dvb_frontend *fe, u32 *frequency)
7648c2ecf20Sopenharmony_ci{
7658c2ecf20Sopenharmony_ci	struct tda827x_priv *priv = fe->tuner_priv;
7668c2ecf20Sopenharmony_ci	*frequency = priv->frequency;
7678c2ecf20Sopenharmony_ci	return 0;
7688c2ecf20Sopenharmony_ci}
7698c2ecf20Sopenharmony_ci
7708c2ecf20Sopenharmony_cistatic int tda827x_get_bandwidth(struct dvb_frontend *fe, u32 *bandwidth)
7718c2ecf20Sopenharmony_ci{
7728c2ecf20Sopenharmony_ci	struct tda827x_priv *priv = fe->tuner_priv;
7738c2ecf20Sopenharmony_ci	*bandwidth = priv->bandwidth;
7748c2ecf20Sopenharmony_ci	return 0;
7758c2ecf20Sopenharmony_ci}
7768c2ecf20Sopenharmony_ci
7778c2ecf20Sopenharmony_cistatic int tda827x_init(struct dvb_frontend *fe)
7788c2ecf20Sopenharmony_ci{
7798c2ecf20Sopenharmony_ci	struct tda827x_priv *priv = fe->tuner_priv;
7808c2ecf20Sopenharmony_ci	dprintk("%s:\n", __func__);
7818c2ecf20Sopenharmony_ci	if (priv->cfg && priv->cfg->init)
7828c2ecf20Sopenharmony_ci		priv->cfg->init(fe);
7838c2ecf20Sopenharmony_ci
7848c2ecf20Sopenharmony_ci	return 0;
7858c2ecf20Sopenharmony_ci}
7868c2ecf20Sopenharmony_ci
7878c2ecf20Sopenharmony_cistatic int tda827x_probe_version(struct dvb_frontend *fe);
7888c2ecf20Sopenharmony_ci
7898c2ecf20Sopenharmony_cistatic int tda827x_initial_init(struct dvb_frontend *fe)
7908c2ecf20Sopenharmony_ci{
7918c2ecf20Sopenharmony_ci	int ret;
7928c2ecf20Sopenharmony_ci	ret = tda827x_probe_version(fe);
7938c2ecf20Sopenharmony_ci	if (ret)
7948c2ecf20Sopenharmony_ci		return ret;
7958c2ecf20Sopenharmony_ci	return fe->ops.tuner_ops.init(fe);
7968c2ecf20Sopenharmony_ci}
7978c2ecf20Sopenharmony_ci
7988c2ecf20Sopenharmony_cistatic int tda827x_initial_sleep(struct dvb_frontend *fe)
7998c2ecf20Sopenharmony_ci{
8008c2ecf20Sopenharmony_ci	int ret;
8018c2ecf20Sopenharmony_ci	ret = tda827x_probe_version(fe);
8028c2ecf20Sopenharmony_ci	if (ret)
8038c2ecf20Sopenharmony_ci		return ret;
8048c2ecf20Sopenharmony_ci	return fe->ops.tuner_ops.sleep(fe);
8058c2ecf20Sopenharmony_ci}
8068c2ecf20Sopenharmony_ci
8078c2ecf20Sopenharmony_cistatic const struct dvb_tuner_ops tda827xo_tuner_ops = {
8088c2ecf20Sopenharmony_ci	.info = {
8098c2ecf20Sopenharmony_ci		.name = "Philips TDA827X",
8108c2ecf20Sopenharmony_ci		.frequency_min_hz  =  55 * MHz,
8118c2ecf20Sopenharmony_ci		.frequency_max_hz  = 860 * MHz,
8128c2ecf20Sopenharmony_ci		.frequency_step_hz = 250 * kHz
8138c2ecf20Sopenharmony_ci	},
8148c2ecf20Sopenharmony_ci	.release = tda827x_release,
8158c2ecf20Sopenharmony_ci	.init = tda827x_initial_init,
8168c2ecf20Sopenharmony_ci	.sleep = tda827x_initial_sleep,
8178c2ecf20Sopenharmony_ci	.set_params = tda827xo_set_params,
8188c2ecf20Sopenharmony_ci	.set_analog_params = tda827xo_set_analog_params,
8198c2ecf20Sopenharmony_ci	.get_frequency = tda827x_get_frequency,
8208c2ecf20Sopenharmony_ci	.get_bandwidth = tda827x_get_bandwidth,
8218c2ecf20Sopenharmony_ci};
8228c2ecf20Sopenharmony_ci
8238c2ecf20Sopenharmony_cistatic const struct dvb_tuner_ops tda827xa_tuner_ops = {
8248c2ecf20Sopenharmony_ci	.info = {
8258c2ecf20Sopenharmony_ci		.name = "Philips TDA827XA",
8268c2ecf20Sopenharmony_ci		.frequency_min_hz  =  44 * MHz,
8278c2ecf20Sopenharmony_ci		.frequency_max_hz  = 906 * MHz,
8288c2ecf20Sopenharmony_ci		.frequency_step_hz = 62500
8298c2ecf20Sopenharmony_ci	},
8308c2ecf20Sopenharmony_ci	.release = tda827x_release,
8318c2ecf20Sopenharmony_ci	.init = tda827x_init,
8328c2ecf20Sopenharmony_ci	.sleep = tda827xa_sleep,
8338c2ecf20Sopenharmony_ci	.set_params = tda827xa_set_params,
8348c2ecf20Sopenharmony_ci	.set_analog_params = tda827xa_set_analog_params,
8358c2ecf20Sopenharmony_ci	.get_frequency = tda827x_get_frequency,
8368c2ecf20Sopenharmony_ci	.get_bandwidth = tda827x_get_bandwidth,
8378c2ecf20Sopenharmony_ci};
8388c2ecf20Sopenharmony_ci
8398c2ecf20Sopenharmony_cistatic int tda827x_probe_version(struct dvb_frontend *fe)
8408c2ecf20Sopenharmony_ci{
8418c2ecf20Sopenharmony_ci	u8 data;
8428c2ecf20Sopenharmony_ci	int rc;
8438c2ecf20Sopenharmony_ci	struct tda827x_priv *priv = fe->tuner_priv;
8448c2ecf20Sopenharmony_ci	struct i2c_msg msg = { .addr = priv->i2c_addr, .flags = I2C_M_RD,
8458c2ecf20Sopenharmony_ci			       .buf = &data, .len = 1 };
8468c2ecf20Sopenharmony_ci
8478c2ecf20Sopenharmony_ci	rc = tuner_transfer(fe, &msg, 1);
8488c2ecf20Sopenharmony_ci
8498c2ecf20Sopenharmony_ci	if (rc < 0) {
8508c2ecf20Sopenharmony_ci		printk("%s: could not read from tuner at addr: 0x%02x\n",
8518c2ecf20Sopenharmony_ci		       __func__, msg.addr << 1);
8528c2ecf20Sopenharmony_ci		return rc;
8538c2ecf20Sopenharmony_ci	}
8548c2ecf20Sopenharmony_ci	if ((data & 0x3c) == 0) {
8558c2ecf20Sopenharmony_ci		dprintk("tda827x tuner found\n");
8568c2ecf20Sopenharmony_ci		fe->ops.tuner_ops.init  = tda827x_init;
8578c2ecf20Sopenharmony_ci		fe->ops.tuner_ops.sleep = tda827xo_sleep;
8588c2ecf20Sopenharmony_ci		if (priv->cfg)
8598c2ecf20Sopenharmony_ci			priv->cfg->agcf = tda827xo_agcf;
8608c2ecf20Sopenharmony_ci	} else {
8618c2ecf20Sopenharmony_ci		dprintk("tda827xa tuner found\n");
8628c2ecf20Sopenharmony_ci		memcpy(&fe->ops.tuner_ops, &tda827xa_tuner_ops, sizeof(struct dvb_tuner_ops));
8638c2ecf20Sopenharmony_ci		if (priv->cfg)
8648c2ecf20Sopenharmony_ci			priv->cfg->agcf = tda827xa_agcf;
8658c2ecf20Sopenharmony_ci	}
8668c2ecf20Sopenharmony_ci	return 0;
8678c2ecf20Sopenharmony_ci}
8688c2ecf20Sopenharmony_ci
8698c2ecf20Sopenharmony_cistruct dvb_frontend *tda827x_attach(struct dvb_frontend *fe, int addr,
8708c2ecf20Sopenharmony_ci				    struct i2c_adapter *i2c,
8718c2ecf20Sopenharmony_ci				    struct tda827x_config *cfg)
8728c2ecf20Sopenharmony_ci{
8738c2ecf20Sopenharmony_ci	struct tda827x_priv *priv = NULL;
8748c2ecf20Sopenharmony_ci
8758c2ecf20Sopenharmony_ci	dprintk("%s:\n", __func__);
8768c2ecf20Sopenharmony_ci	priv = kzalloc(sizeof(struct tda827x_priv), GFP_KERNEL);
8778c2ecf20Sopenharmony_ci	if (priv == NULL)
8788c2ecf20Sopenharmony_ci		return NULL;
8798c2ecf20Sopenharmony_ci
8808c2ecf20Sopenharmony_ci	priv->i2c_addr = addr;
8818c2ecf20Sopenharmony_ci	priv->i2c_adap = i2c;
8828c2ecf20Sopenharmony_ci	priv->cfg = cfg;
8838c2ecf20Sopenharmony_ci	memcpy(&fe->ops.tuner_ops, &tda827xo_tuner_ops, sizeof(struct dvb_tuner_ops));
8848c2ecf20Sopenharmony_ci	fe->tuner_priv = priv;
8858c2ecf20Sopenharmony_ci
8868c2ecf20Sopenharmony_ci	dprintk("type set to %s\n", fe->ops.tuner_ops.info.name);
8878c2ecf20Sopenharmony_ci
8888c2ecf20Sopenharmony_ci	return fe;
8898c2ecf20Sopenharmony_ci}
8908c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(tda827x_attach);
8918c2ecf20Sopenharmony_ci
8928c2ecf20Sopenharmony_ciMODULE_DESCRIPTION("DVB TDA827x driver");
8938c2ecf20Sopenharmony_ciMODULE_AUTHOR("Hartmut Hackmann <hartmut.hackmann@t-online.de>");
8948c2ecf20Sopenharmony_ciMODULE_AUTHOR("Michael Krufky <mkrufky@linuxtv.org>");
8958c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL");
896