aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/tuners/si2157.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/media/tuners/si2157.c')
-rw-r--r--drivers/media/tuners/si2157.c86
1 files changed, 52 insertions, 34 deletions
diff --git a/drivers/media/tuners/si2157.c b/drivers/media/tuners/si2157.c
index 6c53edb73a63..cf97142e01e6 100644
--- a/drivers/media/tuners/si2157.c
+++ b/drivers/media/tuners/si2157.c
@@ -1,5 +1,5 @@
1/* 1/*
2 * Silicon Labs Si2157/2158 silicon tuner driver 2 * Silicon Labs Si2147/2157/2158 silicon tuner driver
3 * 3 *
4 * Copyright (C) 2014 Antti Palosaari <crope@iki.fi> 4 * Copyright (C) 2014 Antti Palosaari <crope@iki.fi>
5 * 5 *
@@ -55,8 +55,7 @@ static int si2157_cmd_execute(struct si2157 *s, struct si2157_cmd *cmd)
55 break; 55 break;
56 } 56 }
57 57
58 dev_dbg(&s->client->dev, "%s: cmd execution took %d ms\n", 58 dev_dbg(&s->client->dev, "cmd execution took %d ms\n",
59 __func__,
60 jiffies_to_msecs(jiffies) - 59 jiffies_to_msecs(jiffies) -
61 (jiffies_to_msecs(timeout) - TIMEOUT)); 60 (jiffies_to_msecs(timeout) - TIMEOUT));
62 61
@@ -75,7 +74,7 @@ err_mutex_unlock:
75 74
76 return 0; 75 return 0;
77err: 76err:
78 dev_dbg(&s->client->dev, "%s: failed=%d\n", __func__, ret); 77 dev_dbg(&s->client->dev, "failed=%d\n", ret);
79 return ret; 78 return ret;
80} 79}
81 80
@@ -88,9 +87,12 @@ static int si2157_init(struct dvb_frontend *fe)
88 u8 *fw_file; 87 u8 *fw_file;
89 unsigned int chip_id; 88 unsigned int chip_id;
90 89
91 dev_dbg(&s->client->dev, "%s:\n", __func__); 90 dev_dbg(&s->client->dev, "\n");
92 91
93 /* configure? */ 92 if (s->fw_loaded)
93 goto warm;
94
95 /* power up */
94 memcpy(cmd.args, "\xc0\x00\x0c\x00\x00\x01\x01\x01\x01\x01\x01\x02\x00\x00\x01", 15); 96 memcpy(cmd.args, "\xc0\x00\x0c\x00\x00\x01\x01\x01\x01\x01\x01\x02\x00\x00\x01", 15);
95 cmd.wlen = 15; 97 cmd.wlen = 15;
96 cmd.rlen = 1; 98 cmd.rlen = 1;
@@ -111,45 +113,47 @@ static int si2157_init(struct dvb_frontend *fe)
111 113
112 #define SI2158_A20 ('A' << 24 | 58 << 16 | '2' << 8 | '0' << 0) 114 #define SI2158_A20 ('A' << 24 | 58 << 16 | '2' << 8 | '0' << 0)
113 #define SI2157_A30 ('A' << 24 | 57 << 16 | '3' << 8 | '0' << 0) 115 #define SI2157_A30 ('A' << 24 | 57 << 16 | '3' << 8 | '0' << 0)
116 #define SI2147_A30 ('A' << 24 | 47 << 16 | '3' << 8 | '0' << 0)
114 117
115 switch (chip_id) { 118 switch (chip_id) {
116 case SI2158_A20: 119 case SI2158_A20:
117 fw_file = SI2158_A20_FIRMWARE; 120 fw_file = SI2158_A20_FIRMWARE;
118 break; 121 break;
119 case SI2157_A30: 122 case SI2157_A30:
123 case SI2147_A30:
120 goto skip_fw_download; 124 goto skip_fw_download;
121 break; 125 break;
122 default: 126 default:
123 dev_err(&s->client->dev, 127 dev_err(&s->client->dev,
124 "%s: unkown chip version Si21%d-%c%c%c\n", 128 "unknown chip version Si21%d-%c%c%c\n",
125 KBUILD_MODNAME, cmd.args[2], cmd.args[1], 129 cmd.args[2], cmd.args[1],
126 cmd.args[3], cmd.args[4]); 130 cmd.args[3], cmd.args[4]);
127 ret = -EINVAL; 131 ret = -EINVAL;
128 goto err; 132 goto err;
129 } 133 }
130 134
131 /* cold state - try to download firmware */ 135 /* cold state - try to download firmware */
132 dev_info(&s->client->dev, "%s: found a '%s' in cold state\n", 136 dev_info(&s->client->dev, "found a '%s' in cold state\n",
133 KBUILD_MODNAME, si2157_ops.info.name); 137 si2157_ops.info.name);
134 138
135 /* request the firmware, this will block and timeout */ 139 /* request the firmware, this will block and timeout */
136 ret = request_firmware(&fw, fw_file, &s->client->dev); 140 ret = request_firmware(&fw, fw_file, &s->client->dev);
137 if (ret) { 141 if (ret) {
138 dev_err(&s->client->dev, "%s: firmware file '%s' not found\n", 142 dev_err(&s->client->dev, "firmware file '%s' not found\n",
139 KBUILD_MODNAME, fw_file); 143 fw_file);
140 goto err; 144 goto err;
141 } 145 }
142 146
143 /* firmware should be n chunks of 17 bytes */ 147 /* firmware should be n chunks of 17 bytes */
144 if (fw->size % 17 != 0) { 148 if (fw->size % 17 != 0) {
145 dev_err(&s->client->dev, "%s: firmware file '%s' is invalid\n", 149 dev_err(&s->client->dev, "firmware file '%s' is invalid\n",
146 KBUILD_MODNAME, fw_file); 150 fw_file);
147 ret = -EINVAL; 151 ret = -EINVAL;
148 goto err; 152 goto err;
149 } 153 }
150 154
151 dev_info(&s->client->dev, "%s: downloading firmware from file '%s'\n", 155 dev_info(&s->client->dev, "downloading firmware from file '%s'\n",
152 KBUILD_MODNAME, fw_file); 156 fw_file);
153 157
154 for (remaining = fw->size; remaining > 0; remaining -= 17) { 158 for (remaining = fw->size; remaining > 0; remaining -= 17) {
155 len = fw->data[fw->size - remaining]; 159 len = fw->data[fw->size - remaining];
@@ -159,8 +163,8 @@ static int si2157_init(struct dvb_frontend *fe)
159 ret = si2157_cmd_execute(s, &cmd); 163 ret = si2157_cmd_execute(s, &cmd);
160 if (ret) { 164 if (ret) {
161 dev_err(&s->client->dev, 165 dev_err(&s->client->dev,
162 "%s: firmware download failed=%d\n", 166 "firmware download failed=%d\n",
163 KBUILD_MODNAME, ret); 167 ret);
164 goto err; 168 goto err;
165 } 169 }
166 } 170 }
@@ -177,14 +181,17 @@ skip_fw_download:
177 if (ret) 181 if (ret)
178 goto err; 182 goto err;
179 183
180 s->active = true; 184 s->fw_loaded = true;
181 185
186warm:
187 s->active = true;
182 return 0; 188 return 0;
189
183err: 190err:
184 if (fw) 191 if (fw)
185 release_firmware(fw); 192 release_firmware(fw);
186 193
187 dev_dbg(&s->client->dev, "%s: failed=%d\n", __func__, ret); 194 dev_dbg(&s->client->dev, "failed=%d\n", ret);
188 return ret; 195 return ret;
189} 196}
190 197
@@ -194,20 +201,21 @@ static int si2157_sleep(struct dvb_frontend *fe)
194 int ret; 201 int ret;
195 struct si2157_cmd cmd; 202 struct si2157_cmd cmd;
196 203
197 dev_dbg(&s->client->dev, "%s:\n", __func__); 204 dev_dbg(&s->client->dev, "\n");
198 205
199 s->active = false; 206 s->active = false;
200 207
201 memcpy(cmd.args, "\x13", 1); 208 /* standby */
202 cmd.wlen = 1; 209 memcpy(cmd.args, "\x16\x00", 2);
203 cmd.rlen = 0; 210 cmd.wlen = 2;
211 cmd.rlen = 1;
204 ret = si2157_cmd_execute(s, &cmd); 212 ret = si2157_cmd_execute(s, &cmd);
205 if (ret) 213 if (ret)
206 goto err; 214 goto err;
207 215
208 return 0; 216 return 0;
209err: 217err:
210 dev_dbg(&s->client->dev, "%s: failed=%d\n", __func__, ret); 218 dev_dbg(&s->client->dev, "failed=%d\n", ret);
211 return ret; 219 return ret;
212} 220}
213 221
@@ -220,8 +228,8 @@ static int si2157_set_params(struct dvb_frontend *fe)
220 u8 bandwidth, delivery_system; 228 u8 bandwidth, delivery_system;
221 229
222 dev_dbg(&s->client->dev, 230 dev_dbg(&s->client->dev,
223 "%s: delivery_system=%d frequency=%u bandwidth_hz=%u\n", 231 "delivery_system=%d frequency=%u bandwidth_hz=%u\n",
224 __func__, c->delivery_system, c->frequency, 232 c->delivery_system, c->frequency,
225 c->bandwidth_hz); 233 c->bandwidth_hz);
226 234
227 if (!s->active) { 235 if (!s->active) {
@@ -239,6 +247,9 @@ static int si2157_set_params(struct dvb_frontend *fe)
239 bandwidth = 0x0f; 247 bandwidth = 0x0f;
240 248
241 switch (c->delivery_system) { 249 switch (c->delivery_system) {
250 case SYS_ATSC:
251 delivery_system = 0x00;
252 break;
242 case SYS_DVBT: 253 case SYS_DVBT:
243 case SYS_DVBT2: /* it seems DVB-T and DVB-T2 both are 0x20 here */ 254 case SYS_DVBT2: /* it seems DVB-T and DVB-T2 both are 0x20 here */
244 delivery_system = 0x20; 255 delivery_system = 0x20;
@@ -256,7 +267,14 @@ static int si2157_set_params(struct dvb_frontend *fe)
256 if (s->inversion) 267 if (s->inversion)
257 cmd.args[5] = 0x01; 268 cmd.args[5] = 0x01;
258 cmd.wlen = 6; 269 cmd.wlen = 6;
259 cmd.rlen = 1; 270 cmd.rlen = 4;
271 ret = si2157_cmd_execute(s, &cmd);
272 if (ret)
273 goto err;
274
275 memcpy(cmd.args, "\x14\x00\x02\x07\x01\x00", 6);
276 cmd.wlen = 6;
277 cmd.rlen = 4;
260 ret = si2157_cmd_execute(s, &cmd); 278 ret = si2157_cmd_execute(s, &cmd);
261 if (ret) 279 if (ret)
262 goto err; 280 goto err;
@@ -275,7 +293,7 @@ static int si2157_set_params(struct dvb_frontend *fe)
275 293
276 return 0; 294 return 0;
277err: 295err:
278 dev_dbg(&s->client->dev, "%s: failed=%d\n", __func__, ret); 296 dev_dbg(&s->client->dev, "failed=%d\n", ret);
279 return ret; 297 return ret;
280} 298}
281 299
@@ -310,13 +328,14 @@ static int si2157_probe(struct i2c_client *client,
310 s = kzalloc(sizeof(struct si2157), GFP_KERNEL); 328 s = kzalloc(sizeof(struct si2157), GFP_KERNEL);
311 if (!s) { 329 if (!s) {
312 ret = -ENOMEM; 330 ret = -ENOMEM;
313 dev_err(&client->dev, "%s: kzalloc() failed\n", KBUILD_MODNAME); 331 dev_err(&client->dev, "kzalloc() failed\n");
314 goto err; 332 goto err;
315 } 333 }
316 334
317 s->client = client; 335 s->client = client;
318 s->fe = cfg->fe; 336 s->fe = cfg->fe;
319 s->inversion = cfg->inversion; 337 s->inversion = cfg->inversion;
338 s->fw_loaded = false;
320 mutex_init(&s->i2c_mutex); 339 mutex_init(&s->i2c_mutex);
321 340
322 /* check if the tuner is there */ 341 /* check if the tuner is there */
@@ -333,11 +352,10 @@ static int si2157_probe(struct i2c_client *client,
333 i2c_set_clientdata(client, s); 352 i2c_set_clientdata(client, s);
334 353
335 dev_info(&s->client->dev, 354 dev_info(&s->client->dev,
336 "%s: Silicon Labs Si2157/Si2158 successfully attached\n", 355 "Silicon Labs Si2157/Si2158 successfully attached\n");
337 KBUILD_MODNAME);
338 return 0; 356 return 0;
339err: 357err:
340 dev_dbg(&client->dev, "%s: failed=%d\n", __func__, ret); 358 dev_dbg(&client->dev, "failed=%d\n", ret);
341 kfree(s); 359 kfree(s);
342 360
343 return ret; 361 return ret;
@@ -348,7 +366,7 @@ static int si2157_remove(struct i2c_client *client)
348 struct si2157 *s = i2c_get_clientdata(client); 366 struct si2157 *s = i2c_get_clientdata(client);
349 struct dvb_frontend *fe = s->fe; 367 struct dvb_frontend *fe = s->fe;
350 368
351 dev_dbg(&client->dev, "%s:\n", __func__); 369 dev_dbg(&client->dev, "\n");
352 370
353 memset(&fe->ops.tuner_ops, 0, sizeof(struct dvb_tuner_ops)); 371 memset(&fe->ops.tuner_ops, 0, sizeof(struct dvb_tuner_ops));
354 fe->tuner_priv = NULL; 372 fe->tuner_priv = NULL;