2 * NXP TDA18212HN silicon tuner driver
4 * Copyright (C) 2011 Antti Palosaari <crope@iki.fi>
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.
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.
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.
22 #include <linux/regmap.h>
25 struct tda18212_config cfg
;
26 struct i2c_client
*client
;
27 struct regmap
*regmap
;
32 static int tda18212_set_params(struct dvb_frontend
*fe
)
34 struct tda18212_dev
*dev
= fe
->tuner_priv
;
35 struct dtv_frontend_properties
*c
= &fe
->dtv_property_cache
;
49 static const u8 bw_params
[][3] = {
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 },
63 dev_dbg(&dev
->client
->dev
,
64 "delivery_system=%d frequency=%d bandwidth_hz=%d\n",
65 c
->delivery_system
, c
->frequency
,
68 if (fe
->ops
.i2c_gate_ctrl
)
69 fe
->ops
.i2c_gate_ctrl(fe
, 1); /* open I2C-gate */
71 switch (c
->delivery_system
) {
73 if_khz
= dev
->cfg
.if_atsc_vsb
;
76 case SYS_DVBC_ANNEX_B
:
77 if_khz
= dev
->cfg
.if_atsc_qam
;
81 switch (c
->bandwidth_hz
) {
83 if_khz
= dev
->cfg
.if_dvbt_6
;
87 if_khz
= dev
->cfg
.if_dvbt_7
;
91 if_khz
= dev
->cfg
.if_dvbt_8
;
100 switch (c
->bandwidth_hz
) {
102 if_khz
= dev
->cfg
.if_dvbt2_6
;
106 if_khz
= dev
->cfg
.if_dvbt2_7
;
110 if_khz
= dev
->cfg
.if_dvbt2_8
;
118 case SYS_DVBC_ANNEX_A
:
119 case SYS_DVBC_ANNEX_C
:
120 if_khz
= dev
->cfg
.if_dvbc
;
128 ret
= regmap_write(dev
->regmap
, 0x23, bw_params
[i
][2]);
132 ret
= regmap_write(dev
->regmap
, 0x06, 0x00);
136 ret
= regmap_write(dev
->regmap
, 0x0f, bw_params
[i
][0]);
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;
149 ret
= regmap_bulk_write(dev
->regmap
, 0x12, buf
, sizeof(buf
));
153 /* actual IF rounded as it is on register */
154 dev
->if_frequency
= buf
[3] * 50 * 1000;
157 if (fe
->ops
.i2c_gate_ctrl
)
158 fe
->ops
.i2c_gate_ctrl(fe
, 0); /* close I2C-gate */
163 dev_dbg(&dev
->client
->dev
, "failed=%d\n", ret
);
167 static int tda18212_get_if_frequency(struct dvb_frontend
*fe
, u32
*frequency
)
169 struct tda18212_dev
*dev
= fe
->tuner_priv
;
171 *frequency
= dev
->if_frequency
;
176 static const struct dvb_tuner_ops tda18212_tuner_ops
= {
178 .name
= "NXP TDA18212",
180 .frequency_min_hz
= 48 * MHz
,
181 .frequency_max_hz
= 864 * MHz
,
182 .frequency_step_hz
= 1 * kHz
,
185 .set_params
= tda18212_set_params
,
186 .get_if_frequency
= tda18212_get_if_frequency
,
189 static int tda18212_probe(struct i2c_client
*client
,
190 const struct i2c_device_id
*id
)
192 struct tda18212_config
*cfg
= client
->dev
.platform_data
;
193 struct dvb_frontend
*fe
= cfg
->fe
;
194 struct tda18212_dev
*dev
;
196 unsigned int chip_id
;
198 static const struct regmap_config regmap_config
= {
203 dev
= kzalloc(sizeof(*dev
), GFP_KERNEL
);
206 dev_err(&client
->dev
, "kzalloc() failed\n");
210 memcpy(&dev
->cfg
, cfg
, sizeof(struct tda18212_config
));
211 dev
->client
= client
;
212 dev
->regmap
= devm_regmap_init_i2c(client
, ®map_config
);
213 if (IS_ERR(dev
->regmap
)) {
214 ret
= PTR_ERR(dev
->regmap
);
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 */
222 ret
= regmap_read(dev
->regmap
, 0x00, &chip_id
);
223 dev_dbg(&dev
->client
->dev
, "chip_id=%02x\n", chip_id
);
225 if (fe
->ops
.i2c_gate_ctrl
)
226 fe
->ops
.i2c_gate_ctrl(fe
, 0); /* close I2C-gate */
233 version
= "M"; /* master */
236 version
= "S"; /* slave */
243 dev_info(&dev
->client
->dev
,
244 "NXP TDA18212HN/%s successfully identified\n", version
);
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
);
253 dev_dbg(&client
->dev
, "failed=%d\n", ret
);
258 static int tda18212_remove(struct i2c_client
*client
)
260 struct tda18212_dev
*dev
= i2c_get_clientdata(client
);
261 struct dvb_frontend
*fe
= dev
->cfg
.fe
;
263 dev_dbg(&client
->dev
, "\n");
265 memset(&fe
->ops
.tuner_ops
, 0, sizeof(struct dvb_tuner_ops
));
266 fe
->tuner_priv
= NULL
;
272 static const struct i2c_device_id tda18212_id
[] = {
276 MODULE_DEVICE_TABLE(i2c
, tda18212_id
);
278 static struct i2c_driver tda18212_driver
= {
282 .probe
= tda18212_probe
,
283 .remove
= tda18212_remove
,
284 .id_table
= tda18212_id
,
287 module_i2c_driver(tda18212_driver
);
289 MODULE_DESCRIPTION("NXP TDA18212HN silicon tuner driver");
290 MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>");
291 MODULE_LICENSE("GPL");