1/*
2 * NXP TDA18212HN silicon tuner driver
3 *
4 * Copyright (C) 2011 Antti Palosaari <crope@iki.fi>
5 *
6 *    This program is free software; you can redistribute it and/or modify
7 *    it under the terms of the GNU General Public License as published by
8 *    the Free Software Foundation; either version 2 of the License, or
9 *    (at your option) any later version.
10 *
11 *    This program is distributed in the hope that it will be useful,
12 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
13 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 *    GNU General Public License for more details.
15 *
16 *    You should have received a copy of the GNU General Public License along
17 *    with this program; if not, write to the Free Software Foundation, Inc.,
18 *    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19 */
20
21#include "tda18212.h"
22#include <linux/regmap.h>
23
24struct tda18212_dev {
25	struct tda18212_config cfg;
26	struct i2c_client *client;
27	struct regmap *regmap;
28
29	u32 if_frequency;
30};
31
32static int tda18212_set_params(struct dvb_frontend *fe)
33{
34	struct tda18212_dev *dev = fe->tuner_priv;
35	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
36	int ret, i;
37	u32 if_khz;
38	u8 buf[9];
39	#define DVBT_6   0
40	#define DVBT_7   1
41	#define DVBT_8   2
42	#define DVBT2_6  3
43	#define DVBT2_7  4
44	#define DVBT2_8  5
45	#define DVBC_6   6
46	#define DVBC_8   7
47	#define ATSC_VSB 8
48	#define ATSC_QAM 9
49	static const u8 bw_params[][3] = {
50		     /* reg:   0f    13    23 */
51		[DVBT_6]  = { 0xb3, 0x20, 0x03 },
52		[DVBT_7]  = { 0xb3, 0x31, 0x01 },
53		[DVBT_8]  = { 0xb3, 0x22, 0x01 },
54		[DVBT2_6] = { 0xbc, 0x20, 0x03 },
55		[DVBT2_7] = { 0xbc, 0x72, 0x03 },
56		[DVBT2_8] = { 0xbc, 0x22, 0x01 },
57		[DVBC_6]  = { 0x92, 0x50, 0x03 },
58		[DVBC_8]  = { 0x92, 0x53, 0x03 },
59		[ATSC_VSB] = { 0x7d, 0x20, 0x63 },
60		[ATSC_QAM] = { 0x7d, 0x20, 0x63 },
61	};
62
63	dev_dbg(&dev->client->dev,
64			"delivery_system=%d frequency=%d bandwidth_hz=%d\n",
65			c->delivery_system, c->frequency,
66			c->bandwidth_hz);
67
68	if (fe->ops.i2c_gate_ctrl)
69		fe->ops.i2c_gate_ctrl(fe, 1); /* open I2C-gate */
70
71	switch (c->delivery_system) {
72	case SYS_ATSC:
73		if_khz = dev->cfg.if_atsc_vsb;
74		i = ATSC_VSB;
75		break;
76	case SYS_DVBC_ANNEX_B:
77		if_khz = dev->cfg.if_atsc_qam;
78		i = ATSC_QAM;
79		break;
80	case SYS_DVBT:
81		switch (c->bandwidth_hz) {
82		case 6000000:
83			if_khz = dev->cfg.if_dvbt_6;
84			i = DVBT_6;
85			break;
86		case 7000000:
87			if_khz = dev->cfg.if_dvbt_7;
88			i = DVBT_7;
89			break;
90		case 8000000:
91			if_khz = dev->cfg.if_dvbt_8;
92			i = DVBT_8;
93			break;
94		default:
95			ret = -EINVAL;
96			goto error;
97		}
98		break;
99	case SYS_DVBT2:
100		switch (c->bandwidth_hz) {
101		case 6000000:
102			if_khz = dev->cfg.if_dvbt2_6;
103			i = DVBT2_6;
104			break;
105		case 7000000:
106			if_khz = dev->cfg.if_dvbt2_7;
107			i = DVBT2_7;
108			break;
109		case 8000000:
110			if_khz = dev->cfg.if_dvbt2_8;
111			i = DVBT2_8;
112			break;
113		default:
114			ret = -EINVAL;
115			goto error;
116		}
117		break;
118	case SYS_DVBC_ANNEX_A:
119	case SYS_DVBC_ANNEX_C:
120		if_khz = dev->cfg.if_dvbc;
121		i = DVBC_8;
122		break;
123	default:
124		ret = -EINVAL;
125		goto error;
126	}
127
128	ret = regmap_write(dev->regmap, 0x23, bw_params[i][2]);
129	if (ret)
130		goto error;
131
132	ret = regmap_write(dev->regmap, 0x06, 0x00);
133	if (ret)
134		goto error;
135
136	ret = regmap_write(dev->regmap, 0x0f, bw_params[i][0]);
137	if (ret)
138		goto error;
139
140	buf[0] = 0x02;
141	buf[1] = bw_params[i][1];
142	buf[2] = 0x03; /* default value */
143	buf[3] = DIV_ROUND_CLOSEST(if_khz, 50);
144	buf[4] = ((c->frequency / 1000) >> 16) & 0xff;
145	buf[5] = ((c->frequency / 1000) >>  8) & 0xff;
146	buf[6] = ((c->frequency / 1000) >>  0) & 0xff;
147	buf[7] = 0xc1;
148	buf[8] = 0x01;
149	ret = regmap_bulk_write(dev->regmap, 0x12, buf, sizeof(buf));
150	if (ret)
151		goto error;
152
153	/* actual IF rounded as it is on register */
154	dev->if_frequency = buf[3] * 50 * 1000;
155
156exit:
157	if (fe->ops.i2c_gate_ctrl)
158		fe->ops.i2c_gate_ctrl(fe, 0); /* close I2C-gate */
159
160	return ret;
161
162error:
163	dev_dbg(&dev->client->dev, "failed=%d\n", ret);
164	goto exit;
165}
166
167static int tda18212_get_if_frequency(struct dvb_frontend *fe, u32 *frequency)
168{
169	struct tda18212_dev *dev = fe->tuner_priv;
170
171	*frequency = dev->if_frequency;
172
173	return 0;
174}
175
176static const struct dvb_tuner_ops tda18212_tuner_ops = {
177	.info = {
178		.name           = "NXP TDA18212",
179
180		.frequency_min  =  48000000,
181		.frequency_max  = 864000000,
182		.frequency_step =      1000,
183	},
184
185	.set_params    = tda18212_set_params,
186	.get_if_frequency = tda18212_get_if_frequency,
187};
188
189static int tda18212_probe(struct i2c_client *client,
190		const struct i2c_device_id *id)
191{
192	struct tda18212_config *cfg = client->dev.platform_data;
193	struct dvb_frontend *fe = cfg->fe;
194	struct tda18212_dev *dev;
195	int ret;
196	unsigned int chip_id;
197	char *version;
198	static const struct regmap_config regmap_config = {
199		.reg_bits = 8,
200		.val_bits = 8,
201	};
202
203	dev = kzalloc(sizeof(*dev), GFP_KERNEL);
204	if (dev == NULL) {
205		ret = -ENOMEM;
206		dev_err(&client->dev, "kzalloc() failed\n");
207		goto err;
208	}
209
210	memcpy(&dev->cfg, cfg, sizeof(struct tda18212_config));
211	dev->client = client;
212	dev->regmap = devm_regmap_init_i2c(client, &regmap_config);
213	if (IS_ERR(dev->regmap)) {
214		ret = PTR_ERR(dev->regmap);
215		goto err;
216	}
217
218	/* check if the tuner is there */
219	if (fe->ops.i2c_gate_ctrl)
220		fe->ops.i2c_gate_ctrl(fe, 1); /* open I2C-gate */
221
222	ret = regmap_read(dev->regmap, 0x00, &chip_id);
223	dev_dbg(&dev->client->dev, "chip_id=%02x\n", chip_id);
224
225	if (fe->ops.i2c_gate_ctrl)
226		fe->ops.i2c_gate_ctrl(fe, 0); /* close I2C-gate */
227
228	if (ret)
229		goto err;
230
231	switch (chip_id) {
232	case 0xc7:
233		version = "M"; /* master */
234		break;
235	case 0x47:
236		version = "S"; /* slave */
237		break;
238	default:
239		ret = -ENODEV;
240		goto err;
241	}
242
243	dev_info(&dev->client->dev,
244			"NXP TDA18212HN/%s successfully identified\n", version);
245
246	fe->tuner_priv = dev;
247	memcpy(&fe->ops.tuner_ops, &tda18212_tuner_ops,
248			sizeof(struct dvb_tuner_ops));
249	i2c_set_clientdata(client, dev);
250
251	return 0;
252err:
253	dev_dbg(&client->dev, "failed=%d\n", ret);
254	kfree(dev);
255	return ret;
256}
257
258static int tda18212_remove(struct i2c_client *client)
259{
260	struct tda18212_dev *dev = i2c_get_clientdata(client);
261	struct dvb_frontend *fe = dev->cfg.fe;
262
263	dev_dbg(&client->dev, "\n");
264
265	memset(&fe->ops.tuner_ops, 0, sizeof(struct dvb_tuner_ops));
266	fe->tuner_priv = NULL;
267	kfree(dev);
268
269	return 0;
270}
271
272static const struct i2c_device_id tda18212_id[] = {
273	{"tda18212", 0},
274	{}
275};
276MODULE_DEVICE_TABLE(i2c, tda18212_id);
277
278static struct i2c_driver tda18212_driver = {
279	.driver = {
280		.owner	= THIS_MODULE,
281		.name	= "tda18212",
282	},
283	.probe		= tda18212_probe,
284	.remove		= tda18212_remove,
285	.id_table	= tda18212_id,
286};
287
288module_i2c_driver(tda18212_driver);
289
290MODULE_DESCRIPTION("NXP TDA18212HN silicon tuner driver");
291MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>");
292MODULE_LICENSE("GPL");
293