diff options
Diffstat (limited to 'drivers/media/tuners/tua9001.c')
-rw-r--r-- | drivers/media/tuners/tua9001.c | 331 |
1 files changed, 160 insertions, 171 deletions
diff --git a/drivers/media/tuners/tua9001.c b/drivers/media/tuners/tua9001.c index 83a6240f64d3..d4f6ca0c4d92 100644 --- a/drivers/media/tuners/tua9001.c +++ b/drivers/media/tuners/tua9001.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Infineon TUA 9001 silicon tuner driver | 2 | * Infineon TUA9001 silicon tuner driver |
3 | * | 3 | * |
4 | * Copyright (C) 2009 Antti Palosaari <crope@iki.fi> | 4 | * Copyright (C) 2009 Antti Palosaari <crope@iki.fi> |
5 | * | 5 | * |
@@ -12,138 +12,87 @@ | |||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
14 | * GNU General Public License for more details. | 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 | */ | 15 | */ |
20 | 16 | ||
21 | #include "tua9001.h" | ||
22 | #include "tua9001_priv.h" | 17 | #include "tua9001_priv.h" |
23 | 18 | ||
24 | /* write register */ | ||
25 | static int tua9001_wr_reg(struct tua9001_priv *priv, u8 reg, u16 val) | ||
26 | { | ||
27 | int ret; | ||
28 | u8 buf[3] = { reg, (val >> 8) & 0xff, (val >> 0) & 0xff }; | ||
29 | struct i2c_msg msg[1] = { | ||
30 | { | ||
31 | .addr = priv->cfg->i2c_addr, | ||
32 | .flags = 0, | ||
33 | .len = sizeof(buf), | ||
34 | .buf = buf, | ||
35 | } | ||
36 | }; | ||
37 | |||
38 | ret = i2c_transfer(priv->i2c, msg, 1); | ||
39 | if (ret == 1) { | ||
40 | ret = 0; | ||
41 | } else { | ||
42 | dev_warn(&priv->i2c->dev, "%s: i2c wr failed=%d reg=%02x\n", | ||
43 | KBUILD_MODNAME, ret, reg); | ||
44 | ret = -EREMOTEIO; | ||
45 | } | ||
46 | |||
47 | return ret; | ||
48 | } | ||
49 | |||
50 | static int tua9001_release(struct dvb_frontend *fe) | ||
51 | { | ||
52 | struct tua9001_priv *priv = fe->tuner_priv; | ||
53 | int ret = 0; | ||
54 | |||
55 | dev_dbg(&priv->i2c->dev, "%s:\n", __func__); | ||
56 | |||
57 | if (fe->callback) | ||
58 | ret = fe->callback(priv->i2c, DVB_FRONTEND_COMPONENT_TUNER, | ||
59 | TUA9001_CMD_CEN, 0); | ||
60 | |||
61 | kfree(fe->tuner_priv); | ||
62 | fe->tuner_priv = NULL; | ||
63 | |||
64 | return ret; | ||
65 | } | ||
66 | |||
67 | static int tua9001_init(struct dvb_frontend *fe) | 19 | static int tua9001_init(struct dvb_frontend *fe) |
68 | { | 20 | { |
69 | struct tua9001_priv *priv = fe->tuner_priv; | 21 | struct tua9001_dev *dev = fe->tuner_priv; |
70 | int ret = 0; | 22 | struct i2c_client *client = dev->client; |
71 | u8 i; | 23 | int ret, i; |
72 | struct reg_val data[] = { | 24 | static const struct tua9001_reg_val data[] = { |
73 | { 0x1e, 0x6512 }, | 25 | {0x1e, 0x6512}, |
74 | { 0x25, 0xb888 }, | 26 | {0x25, 0xb888}, |
75 | { 0x39, 0x5460 }, | 27 | {0x39, 0x5460}, |
76 | { 0x3b, 0x00c0 }, | 28 | {0x3b, 0x00c0}, |
77 | { 0x3a, 0xf000 }, | 29 | {0x3a, 0xf000}, |
78 | { 0x08, 0x0000 }, | 30 | {0x08, 0x0000}, |
79 | { 0x32, 0x0030 }, | 31 | {0x32, 0x0030}, |
80 | { 0x41, 0x703a }, | 32 | {0x41, 0x703a}, |
81 | { 0x40, 0x1c78 }, | 33 | {0x40, 0x1c78}, |
82 | { 0x2c, 0x1c00 }, | 34 | {0x2c, 0x1c00}, |
83 | { 0x36, 0xc013 }, | 35 | {0x36, 0xc013}, |
84 | { 0x37, 0x6f18 }, | 36 | {0x37, 0x6f18}, |
85 | { 0x27, 0x0008 }, | 37 | {0x27, 0x0008}, |
86 | { 0x2a, 0x0001 }, | 38 | {0x2a, 0x0001}, |
87 | { 0x34, 0x0a40 }, | 39 | {0x34, 0x0a40}, |
88 | }; | 40 | }; |
89 | 41 | ||
90 | dev_dbg(&priv->i2c->dev, "%s:\n", __func__); | 42 | dev_dbg(&client->dev, "\n"); |
91 | 43 | ||
92 | if (fe->callback) { | 44 | if (fe->callback) { |
93 | ret = fe->callback(priv->i2c, DVB_FRONTEND_COMPONENT_TUNER, | 45 | ret = fe->callback(client->adapter, |
94 | TUA9001_CMD_RESETN, 0); | 46 | DVB_FRONTEND_COMPONENT_TUNER, |
95 | if (ret < 0) | 47 | TUA9001_CMD_RESETN, 0); |
48 | if (ret) | ||
96 | goto err; | 49 | goto err; |
97 | } | 50 | } |
98 | 51 | ||
99 | if (fe->ops.i2c_gate_ctrl) | ||
100 | fe->ops.i2c_gate_ctrl(fe, 1); /* open i2c-gate */ | ||
101 | |||
102 | for (i = 0; i < ARRAY_SIZE(data); i++) { | 52 | for (i = 0; i < ARRAY_SIZE(data); i++) { |
103 | ret = tua9001_wr_reg(priv, data[i].reg, data[i].val); | 53 | ret = regmap_write(dev->regmap, data[i].reg, data[i].val); |
104 | if (ret < 0) | 54 | if (ret) |
105 | goto err_i2c_gate_ctrl; | 55 | goto err; |
106 | } | 56 | } |
107 | 57 | return 0; | |
108 | err_i2c_gate_ctrl: | ||
109 | if (fe->ops.i2c_gate_ctrl) | ||
110 | fe->ops.i2c_gate_ctrl(fe, 0); /* close i2c-gate */ | ||
111 | err: | 58 | err: |
112 | if (ret < 0) | 59 | dev_dbg(&client->dev, "failed=%d\n", ret); |
113 | dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret); | ||
114 | |||
115 | return ret; | 60 | return ret; |
116 | } | 61 | } |
117 | 62 | ||
118 | static int tua9001_sleep(struct dvb_frontend *fe) | 63 | static int tua9001_sleep(struct dvb_frontend *fe) |
119 | { | 64 | { |
120 | struct tua9001_priv *priv = fe->tuner_priv; | 65 | struct tua9001_dev *dev = fe->tuner_priv; |
121 | int ret = 0; | 66 | struct i2c_client *client = dev->client; |
122 | 67 | int ret; | |
123 | dev_dbg(&priv->i2c->dev, "%s:\n", __func__); | ||
124 | |||
125 | if (fe->callback) | ||
126 | ret = fe->callback(priv->i2c, DVB_FRONTEND_COMPONENT_TUNER, | ||
127 | TUA9001_CMD_RESETN, 1); | ||
128 | 68 | ||
129 | if (ret < 0) | 69 | dev_dbg(&client->dev, "\n"); |
130 | dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret); | ||
131 | 70 | ||
71 | if (fe->callback) { | ||
72 | ret = fe->callback(client->adapter, | ||
73 | DVB_FRONTEND_COMPONENT_TUNER, | ||
74 | TUA9001_CMD_RESETN, 1); | ||
75 | if (ret) | ||
76 | goto err; | ||
77 | } | ||
78 | return 0; | ||
79 | err: | ||
80 | dev_dbg(&client->dev, "failed=%d\n", ret); | ||
132 | return ret; | 81 | return ret; |
133 | } | 82 | } |
134 | 83 | ||
135 | static int tua9001_set_params(struct dvb_frontend *fe) | 84 | static int tua9001_set_params(struct dvb_frontend *fe) |
136 | { | 85 | { |
137 | struct tua9001_priv *priv = fe->tuner_priv; | 86 | struct tua9001_dev *dev = fe->tuner_priv; |
87 | struct i2c_client *client = dev->client; | ||
138 | struct dtv_frontend_properties *c = &fe->dtv_property_cache; | 88 | struct dtv_frontend_properties *c = &fe->dtv_property_cache; |
139 | int ret = 0, i; | 89 | int ret, i; |
140 | u16 val; | 90 | u16 val; |
141 | u32 frequency; | 91 | struct tua9001_reg_val data[2]; |
142 | struct reg_val data[2]; | ||
143 | 92 | ||
144 | dev_dbg(&priv->i2c->dev, "%s: delivery_system=%d frequency=%d " \ | 93 | dev_dbg(&client->dev, |
145 | "bandwidth_hz=%d\n", __func__, | 94 | "delivery_system=%u frequency=%u bandwidth_hz=%u\n", |
146 | c->delivery_system, c->frequency, c->bandwidth_hz); | 95 | c->delivery_system, c->frequency, c->bandwidth_hz); |
147 | 96 | ||
148 | switch (c->delivery_system) { | 97 | switch (c->delivery_system) { |
149 | case SYS_DVBT: | 98 | case SYS_DVBT: |
@@ -172,70 +121,54 @@ static int tua9001_set_params(struct dvb_frontend *fe) | |||
172 | 121 | ||
173 | data[0].reg = 0x04; | 122 | data[0].reg = 0x04; |
174 | data[0].val = val; | 123 | data[0].val = val; |
175 | |||
176 | frequency = (c->frequency - 150000000); | ||
177 | frequency /= 100; | ||
178 | frequency *= 48; | ||
179 | frequency /= 10000; | ||
180 | |||
181 | data[1].reg = 0x1f; | 124 | data[1].reg = 0x1f; |
182 | data[1].val = frequency; | 125 | data[1].val = div_u64((u64) (c->frequency - 150000000) * 48, 1000000); |
183 | |||
184 | if (fe->ops.i2c_gate_ctrl) | ||
185 | fe->ops.i2c_gate_ctrl(fe, 1); /* open i2c-gate */ | ||
186 | 126 | ||
187 | if (fe->callback) { | 127 | if (fe->callback) { |
188 | ret = fe->callback(priv->i2c, DVB_FRONTEND_COMPONENT_TUNER, | 128 | ret = fe->callback(client->adapter, |
189 | TUA9001_CMD_RXEN, 0); | 129 | DVB_FRONTEND_COMPONENT_TUNER, |
190 | if (ret < 0) | 130 | TUA9001_CMD_RXEN, 0); |
191 | goto err_i2c_gate_ctrl; | 131 | if (ret) |
132 | goto err; | ||
192 | } | 133 | } |
193 | 134 | ||
194 | for (i = 0; i < ARRAY_SIZE(data); i++) { | 135 | for (i = 0; i < ARRAY_SIZE(data); i++) { |
195 | ret = tua9001_wr_reg(priv, data[i].reg, data[i].val); | 136 | ret = regmap_write(dev->regmap, data[i].reg, data[i].val); |
196 | if (ret < 0) | 137 | if (ret) |
197 | goto err_i2c_gate_ctrl; | 138 | goto err; |
198 | } | 139 | } |
199 | 140 | ||
200 | if (fe->callback) { | 141 | if (fe->callback) { |
201 | ret = fe->callback(priv->i2c, DVB_FRONTEND_COMPONENT_TUNER, | 142 | ret = fe->callback(client->adapter, |
202 | TUA9001_CMD_RXEN, 1); | 143 | DVB_FRONTEND_COMPONENT_TUNER, |
203 | if (ret < 0) | 144 | TUA9001_CMD_RXEN, 1); |
204 | goto err_i2c_gate_ctrl; | 145 | if (ret) |
146 | goto err; | ||
205 | } | 147 | } |
206 | 148 | return 0; | |
207 | err_i2c_gate_ctrl: | ||
208 | if (fe->ops.i2c_gate_ctrl) | ||
209 | fe->ops.i2c_gate_ctrl(fe, 0); /* close i2c-gate */ | ||
210 | err: | 149 | err: |
211 | if (ret < 0) | 150 | dev_dbg(&client->dev, "failed=%d\n", ret); |
212 | dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret); | ||
213 | |||
214 | return ret; | 151 | return ret; |
215 | } | 152 | } |
216 | 153 | ||
217 | static int tua9001_get_if_frequency(struct dvb_frontend *fe, u32 *frequency) | 154 | static int tua9001_get_if_frequency(struct dvb_frontend *fe, u32 *frequency) |
218 | { | 155 | { |
219 | struct tua9001_priv *priv = fe->tuner_priv; | 156 | struct tua9001_dev *dev = fe->tuner_priv; |
157 | struct i2c_client *client = dev->client; | ||
220 | 158 | ||
221 | dev_dbg(&priv->i2c->dev, "%s:\n", __func__); | 159 | dev_dbg(&client->dev, "\n"); |
222 | 160 | ||
223 | *frequency = 0; /* Zero-IF */ | 161 | *frequency = 0; /* Zero-IF */ |
224 | |||
225 | return 0; | 162 | return 0; |
226 | } | 163 | } |
227 | 164 | ||
228 | static const struct dvb_tuner_ops tua9001_tuner_ops = { | 165 | static const struct dvb_tuner_ops tua9001_tuner_ops = { |
229 | .info = { | 166 | .info = { |
230 | .name = "Infineon TUA 9001", | 167 | .name = "Infineon TUA9001", |
231 | |||
232 | .frequency_min = 170000000, | 168 | .frequency_min = 170000000, |
233 | .frequency_max = 862000000, | 169 | .frequency_max = 862000000, |
234 | .frequency_step = 0, | ||
235 | }, | 170 | }, |
236 | 171 | ||
237 | .release = tua9001_release, | ||
238 | |||
239 | .init = tua9001_init, | 172 | .init = tua9001_init, |
240 | .sleep = tua9001_sleep, | 173 | .sleep = tua9001_sleep, |
241 | .set_params = tua9001_set_params, | 174 | .set_params = tua9001_set_params, |
@@ -243,52 +176,108 @@ static const struct dvb_tuner_ops tua9001_tuner_ops = { | |||
243 | .get_if_frequency = tua9001_get_if_frequency, | 176 | .get_if_frequency = tua9001_get_if_frequency, |
244 | }; | 177 | }; |
245 | 178 | ||
246 | struct dvb_frontend *tua9001_attach(struct dvb_frontend *fe, | 179 | static int tua9001_probe(struct i2c_client *client, |
247 | struct i2c_adapter *i2c, struct tua9001_config *cfg) | 180 | const struct i2c_device_id *id) |
248 | { | 181 | { |
249 | struct tua9001_priv *priv = NULL; | 182 | struct tua9001_dev *dev; |
183 | struct tua9001_platform_data *pdata = client->dev.platform_data; | ||
184 | struct dvb_frontend *fe = pdata->dvb_frontend; | ||
250 | int ret; | 185 | int ret; |
186 | static const struct regmap_config regmap_config = { | ||
187 | .reg_bits = 8, | ||
188 | .val_bits = 16, | ||
189 | }; | ||
251 | 190 | ||
252 | priv = kzalloc(sizeof(struct tua9001_priv), GFP_KERNEL); | 191 | dev = kzalloc(sizeof(*dev), GFP_KERNEL); |
253 | if (priv == NULL) | 192 | if (!dev) { |
254 | return NULL; | 193 | ret = -ENOMEM; |
194 | goto err; | ||
195 | } | ||
255 | 196 | ||
256 | priv->cfg = cfg; | 197 | dev->fe = pdata->dvb_frontend; |
257 | priv->i2c = i2c; | 198 | dev->client = client; |
199 | dev->regmap = devm_regmap_init_i2c(client, ®map_config); | ||
200 | if (IS_ERR(dev->regmap)) { | ||
201 | ret = PTR_ERR(dev->regmap); | ||
202 | goto err_kfree; | ||
203 | } | ||
258 | 204 | ||
259 | if (fe->callback) { | 205 | if (fe->callback) { |
260 | ret = fe->callback(priv->i2c, DVB_FRONTEND_COMPONENT_TUNER, | 206 | ret = fe->callback(client->adapter, |
261 | TUA9001_CMD_CEN, 1); | 207 | DVB_FRONTEND_COMPONENT_TUNER, |
262 | if (ret < 0) | 208 | TUA9001_CMD_CEN, 1); |
263 | goto err; | 209 | if (ret) |
264 | 210 | goto err_kfree; | |
265 | ret = fe->callback(priv->i2c, DVB_FRONTEND_COMPONENT_TUNER, | 211 | |
266 | TUA9001_CMD_RXEN, 0); | 212 | ret = fe->callback(client->adapter, |
267 | if (ret < 0) | 213 | DVB_FRONTEND_COMPONENT_TUNER, |
268 | goto err; | 214 | TUA9001_CMD_RXEN, 0); |
269 | 215 | if (ret) | |
270 | ret = fe->callback(priv->i2c, DVB_FRONTEND_COMPONENT_TUNER, | 216 | goto err_kfree; |
271 | TUA9001_CMD_RESETN, 1); | 217 | |
272 | if (ret < 0) | 218 | ret = fe->callback(client->adapter, |
273 | goto err; | 219 | DVB_FRONTEND_COMPONENT_TUNER, |
220 | TUA9001_CMD_RESETN, 1); | ||
221 | if (ret) | ||
222 | goto err_kfree; | ||
274 | } | 223 | } |
275 | 224 | ||
276 | dev_info(&priv->i2c->dev, | 225 | fe->tuner_priv = dev; |
277 | "%s: Infineon TUA 9001 successfully attached\n", | ||
278 | KBUILD_MODNAME); | ||
279 | |||
280 | memcpy(&fe->ops.tuner_ops, &tua9001_tuner_ops, | 226 | memcpy(&fe->ops.tuner_ops, &tua9001_tuner_ops, |
281 | sizeof(struct dvb_tuner_ops)); | 227 | sizeof(struct dvb_tuner_ops)); |
228 | i2c_set_clientdata(client, dev); | ||
282 | 229 | ||
283 | fe->tuner_priv = priv; | 230 | dev_info(&client->dev, "Infineon TUA9001 successfully attached\n"); |
284 | return fe; | 231 | return 0; |
232 | err_kfree: | ||
233 | kfree(dev); | ||
285 | err: | 234 | err: |
286 | dev_dbg(&i2c->dev, "%s: failed=%d\n", __func__, ret); | 235 | dev_dbg(&client->dev, "failed=%d\n", ret); |
287 | kfree(priv); | 236 | return ret; |
288 | return NULL; | 237 | } |
238 | |||
239 | static int tua9001_remove(struct i2c_client *client) | ||
240 | { | ||
241 | struct tua9001_dev *dev = i2c_get_clientdata(client); | ||
242 | struct dvb_frontend *fe = dev->fe; | ||
243 | int ret; | ||
244 | |||
245 | dev_dbg(&client->dev, "\n"); | ||
246 | |||
247 | if (fe->callback) { | ||
248 | ret = fe->callback(client->adapter, | ||
249 | DVB_FRONTEND_COMPONENT_TUNER, | ||
250 | TUA9001_CMD_CEN, 0); | ||
251 | if (ret) | ||
252 | goto err_kfree; | ||
253 | } | ||
254 | kfree(dev); | ||
255 | return 0; | ||
256 | err_kfree: | ||
257 | kfree(dev); | ||
258 | dev_dbg(&client->dev, "failed=%d\n", ret); | ||
259 | return ret; | ||
289 | } | 260 | } |
290 | EXPORT_SYMBOL(tua9001_attach); | ||
291 | 261 | ||
292 | MODULE_DESCRIPTION("Infineon TUA 9001 silicon tuner driver"); | 262 | static const struct i2c_device_id tua9001_id_table[] = { |
263 | {"tua9001", 0}, | ||
264 | {} | ||
265 | }; | ||
266 | MODULE_DEVICE_TABLE(i2c, tua9001_id_table); | ||
267 | |||
268 | static struct i2c_driver tua9001_driver = { | ||
269 | .driver = { | ||
270 | .owner = THIS_MODULE, | ||
271 | .name = "tua9001", | ||
272 | .suppress_bind_attrs = true, | ||
273 | }, | ||
274 | .probe = tua9001_probe, | ||
275 | .remove = tua9001_remove, | ||
276 | .id_table = tua9001_id_table, | ||
277 | }; | ||
278 | |||
279 | module_i2c_driver(tua9001_driver); | ||
280 | |||
281 | MODULE_DESCRIPTION("Infineon TUA9001 silicon tuner driver"); | ||
293 | MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>"); | 282 | MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>"); |
294 | MODULE_LICENSE("GPL"); | 283 | MODULE_LICENSE("GPL"); |