diff options
Diffstat (limited to 'drivers/media/dvb/frontends/or51132.c')
-rw-r--r-- | drivers/media/dvb/frontends/or51132.c | 157 |
1 files changed, 101 insertions, 56 deletions
diff --git a/drivers/media/dvb/frontends/or51132.c b/drivers/media/dvb/frontends/or51132.c index 80e0f28127b7..d20ab30c1e83 100644 --- a/drivers/media/dvb/frontends/or51132.c +++ b/drivers/media/dvb/frontends/or51132.c | |||
@@ -54,7 +54,6 @@ static int debug; | |||
54 | struct or51132_state | 54 | struct or51132_state |
55 | { | 55 | { |
56 | struct i2c_adapter* i2c; | 56 | struct i2c_adapter* i2c; |
57 | struct dvb_frontend_ops ops; | ||
58 | 57 | ||
59 | /* Configuration settings */ | 58 | /* Configuration settings */ |
60 | const struct or51132_config* config; | 59 | const struct or51132_config* config; |
@@ -106,9 +105,8 @@ static int or51132_load_firmware (struct dvb_frontend* fe, const struct firmware | |||
106 | { | 105 | { |
107 | struct or51132_state* state = fe->demodulator_priv; | 106 | struct or51132_state* state = fe->demodulator_priv; |
108 | static u8 run_buf[] = {0x7F,0x01}; | 107 | static u8 run_buf[] = {0x7F,0x01}; |
109 | static u8 get_ver_buf[] = {0x04,0x00,0x30,0x00,0x00}; | 108 | u8 rec_buf[8]; |
110 | u8 rec_buf[14]; | 109 | u8 cmd_buf[3]; |
111 | u8 cmd_buf[14]; | ||
112 | u32 firmwareAsize, firmwareBsize; | 110 | u32 firmwareAsize, firmwareBsize; |
113 | int i,ret; | 111 | int i,ret; |
114 | 112 | ||
@@ -157,7 +155,6 @@ static int or51132_load_firmware (struct dvb_frontend* fe, const struct firmware | |||
157 | cmd_buf[0] = 0x10; | 155 | cmd_buf[0] = 0x10; |
158 | cmd_buf[1] = 0x10; | 156 | cmd_buf[1] = 0x10; |
159 | cmd_buf[2] = 0x00; | 157 | cmd_buf[2] = 0x00; |
160 | cmd_buf[3] = 0x00; | ||
161 | msleep(20); /* 20ms */ | 158 | msleep(20); /* 20ms */ |
162 | if ((ret = i2c_writebytes(state,state->config->demod_address, | 159 | if ((ret = i2c_writebytes(state,state->config->demod_address, |
163 | cmd_buf,3))) { | 160 | cmd_buf,3))) { |
@@ -167,8 +164,6 @@ static int or51132_load_firmware (struct dvb_frontend* fe, const struct firmware | |||
167 | 164 | ||
168 | cmd_buf[0] = 0x04; | 165 | cmd_buf[0] = 0x04; |
169 | cmd_buf[1] = 0x17; | 166 | cmd_buf[1] = 0x17; |
170 | cmd_buf[2] = 0x00; | ||
171 | cmd_buf[3] = 0x00; | ||
172 | msleep(20); /* 20ms */ | 167 | msleep(20); /* 20ms */ |
173 | if ((ret = i2c_writebytes(state,state->config->demod_address, | 168 | if ((ret = i2c_writebytes(state,state->config->demod_address, |
174 | cmd_buf,2))) { | 169 | cmd_buf,2))) { |
@@ -178,8 +173,6 @@ static int or51132_load_firmware (struct dvb_frontend* fe, const struct firmware | |||
178 | 173 | ||
179 | cmd_buf[0] = 0x00; | 174 | cmd_buf[0] = 0x00; |
180 | cmd_buf[1] = 0x00; | 175 | cmd_buf[1] = 0x00; |
181 | cmd_buf[2] = 0x00; | ||
182 | cmd_buf[3] = 0x00; | ||
183 | msleep(20); /* 20ms */ | 176 | msleep(20); /* 20ms */ |
184 | if ((ret = i2c_writebytes(state,state->config->demod_address, | 177 | if ((ret = i2c_writebytes(state,state->config->demod_address, |
185 | cmd_buf,2))) { | 178 | cmd_buf,2))) { |
@@ -189,7 +182,11 @@ static int or51132_load_firmware (struct dvb_frontend* fe, const struct firmware | |||
189 | 182 | ||
190 | for(i=0;i<4;i++) { | 183 | for(i=0;i<4;i++) { |
191 | msleep(20); /* 20ms */ | 184 | msleep(20); /* 20ms */ |
192 | get_ver_buf[4] = i+1; | 185 | /* Once upon a time, this command might have had something |
186 | to do with getting the firmware version, but it's | ||
187 | not used anymore: | ||
188 | {0x04,0x00,0x30,0x00,i+1} */ | ||
189 | /* Read 8 bytes, two bytes at a time */ | ||
193 | if ((ret = i2c_readbytes(state,state->config->demod_address, | 190 | if ((ret = i2c_readbytes(state,state->config->demod_address, |
194 | &rec_buf[i*2],2))) { | 191 | &rec_buf[i*2],2))) { |
195 | printk(KERN_WARNING | 192 | printk(KERN_WARNING |
@@ -208,7 +205,6 @@ static int or51132_load_firmware (struct dvb_frontend* fe, const struct firmware | |||
208 | cmd_buf[0] = 0x10; | 205 | cmd_buf[0] = 0x10; |
209 | cmd_buf[1] = 0x00; | 206 | cmd_buf[1] = 0x00; |
210 | cmd_buf[2] = 0x00; | 207 | cmd_buf[2] = 0x00; |
211 | cmd_buf[3] = 0x00; | ||
212 | msleep(20); /* 20ms */ | 208 | msleep(20); /* 20ms */ |
213 | if ((ret = i2c_writebytes(state,state->config->demod_address, | 209 | if ((ret = i2c_writebytes(state,state->config->demod_address, |
214 | cmd_buf,3))) { | 210 | cmd_buf,3))) { |
@@ -243,7 +239,7 @@ static int or51132_sleep(struct dvb_frontend* fe) | |||
243 | static int or51132_setmode(struct dvb_frontend* fe) | 239 | static int or51132_setmode(struct dvb_frontend* fe) |
244 | { | 240 | { |
245 | struct or51132_state* state = fe->demodulator_priv; | 241 | struct or51132_state* state = fe->demodulator_priv; |
246 | unsigned char cmd_buf[4]; | 242 | unsigned char cmd_buf[3]; |
247 | 243 | ||
248 | dprintk("setmode %d\n",(int)state->current_modulation); | 244 | dprintk("setmode %d\n",(int)state->current_modulation); |
249 | /* set operation mode in Receiver 1 register; */ | 245 | /* set operation mode in Receiver 1 register; */ |
@@ -263,7 +259,6 @@ static int or51132_setmode(struct dvb_frontend* fe) | |||
263 | default: | 259 | default: |
264 | printk("setmode:Modulation set to unsupported value\n"); | 260 | printk("setmode:Modulation set to unsupported value\n"); |
265 | }; | 261 | }; |
266 | cmd_buf[3] = 0x00; | ||
267 | if (i2c_writebytes(state,state->config->demod_address, | 262 | if (i2c_writebytes(state,state->config->demod_address, |
268 | cmd_buf,3)) { | 263 | cmd_buf,3)) { |
269 | printk(KERN_WARNING "or51132: set_mode error 1\n"); | 264 | printk(KERN_WARNING "or51132: set_mode error 1\n"); |
@@ -301,7 +296,6 @@ static int or51132_setmode(struct dvb_frontend* fe) | |||
301 | default: | 296 | default: |
302 | printk("setmode: Modulation set to unsupported value\n"); | 297 | printk("setmode: Modulation set to unsupported value\n"); |
303 | }; | 298 | }; |
304 | cmd_buf[3] = 0x00; | ||
305 | msleep(20); /* 20ms */ | 299 | msleep(20); /* 20ms */ |
306 | if (i2c_writebytes(state,state->config->demod_address, | 300 | if (i2c_writebytes(state,state->config->demod_address, |
307 | cmd_buf,3)) { | 301 | cmd_buf,3)) { |
@@ -313,52 +307,65 @@ static int or51132_setmode(struct dvb_frontend* fe) | |||
313 | return 0; | 307 | return 0; |
314 | } | 308 | } |
315 | 309 | ||
310 | /* Some modulations use the same firmware. This classifies modulations | ||
311 | by the firmware they use. */ | ||
312 | #define MOD_FWCLASS_UNKNOWN 0 | ||
313 | #define MOD_FWCLASS_VSB 1 | ||
314 | #define MOD_FWCLASS_QAM 2 | ||
315 | static int modulation_fw_class(fe_modulation_t modulation) | ||
316 | { | ||
317 | switch(modulation) { | ||
318 | case VSB_8: | ||
319 | return MOD_FWCLASS_VSB; | ||
320 | case QAM_AUTO: | ||
321 | case QAM_64: | ||
322 | case QAM_256: | ||
323 | return MOD_FWCLASS_QAM; | ||
324 | default: | ||
325 | return MOD_FWCLASS_UNKNOWN; | ||
326 | } | ||
327 | } | ||
328 | |||
316 | static int or51132_set_parameters(struct dvb_frontend* fe, | 329 | static int or51132_set_parameters(struct dvb_frontend* fe, |
317 | struct dvb_frontend_parameters *param) | 330 | struct dvb_frontend_parameters *param) |
318 | { | 331 | { |
319 | int ret; | 332 | int ret; |
320 | u8 buf[4]; | ||
321 | struct or51132_state* state = fe->demodulator_priv; | 333 | struct or51132_state* state = fe->demodulator_priv; |
322 | const struct firmware *fw; | 334 | const struct firmware *fw; |
323 | 335 | const char *fwname; | |
324 | /* Change only if we are actually changing the modulation */ | 336 | int clock_mode; |
325 | if (state->current_modulation != param->u.vsb.modulation) { | 337 | |
326 | switch(param->u.vsb.modulation) { | 338 | /* Upload new firmware only if we need a different one */ |
327 | case VSB_8: | 339 | if (modulation_fw_class(state->current_modulation) != |
340 | modulation_fw_class(param->u.vsb.modulation)) { | ||
341 | switch(modulation_fw_class(param->u.vsb.modulation)) { | ||
342 | case MOD_FWCLASS_VSB: | ||
328 | dprintk("set_parameters VSB MODE\n"); | 343 | dprintk("set_parameters VSB MODE\n"); |
329 | printk("or51132: Waiting for firmware upload(%s)...\n", | 344 | fwname = OR51132_VSB_FIRMWARE; |
330 | OR51132_VSB_FIRMWARE); | 345 | |
331 | ret = request_firmware(&fw, OR51132_VSB_FIRMWARE, | ||
332 | &state->i2c->dev); | ||
333 | if (ret){ | ||
334 | printk(KERN_WARNING "or51132: No firmware up" | ||
335 | "loaded(timeout or file not found?)\n"); | ||
336 | return ret; | ||
337 | } | ||
338 | /* Set non-punctured clock for VSB */ | 346 | /* Set non-punctured clock for VSB */ |
339 | state->config->set_ts_params(fe, 0); | 347 | clock_mode = 0; |
340 | break; | 348 | break; |
341 | case QAM_AUTO: | 349 | case MOD_FWCLASS_QAM: |
342 | case QAM_64: | ||
343 | case QAM_256: | ||
344 | dprintk("set_parameters QAM MODE\n"); | 350 | dprintk("set_parameters QAM MODE\n"); |
345 | printk("or51132: Waiting for firmware upload(%s)...\n", | 351 | fwname = OR51132_QAM_FIRMWARE; |
346 | OR51132_QAM_FIRMWARE); | 352 | |
347 | ret = request_firmware(&fw, OR51132_QAM_FIRMWARE, | ||
348 | &state->i2c->dev); | ||
349 | if (ret){ | ||
350 | printk(KERN_WARNING "or51132: No firmware up" | ||
351 | "loaded(timeout or file not found?)\n"); | ||
352 | return ret; | ||
353 | } | ||
354 | /* Set punctured clock for QAM */ | 353 | /* Set punctured clock for QAM */ |
355 | state->config->set_ts_params(fe, 1); | 354 | clock_mode = 1; |
356 | break; | 355 | break; |
357 | default: | 356 | default: |
358 | printk("or51132:Modulation type(%d) UNSUPPORTED\n", | 357 | printk("or51132: Modulation type(%d) UNSUPPORTED\n", |
359 | param->u.vsb.modulation); | 358 | param->u.vsb.modulation); |
360 | return -1; | 359 | return -1; |
361 | }; | 360 | } |
361 | printk("or51132: Waiting for firmware upload(%s)...\n", | ||
362 | fwname); | ||
363 | ret = request_firmware(&fw, fwname, &state->i2c->dev); | ||
364 | if (ret) { | ||
365 | printk(KERN_WARNING "or51132: No firmware up" | ||
366 | "loaded(timeout or file not found?)\n"); | ||
367 | return ret; | ||
368 | } | ||
362 | ret = or51132_load_firmware(fe, fw); | 369 | ret = or51132_load_firmware(fe, fw); |
363 | release_firmware(fw); | 370 | release_firmware(fw); |
364 | if (ret) { | 371 | if (ret) { |
@@ -367,18 +374,18 @@ static int or51132_set_parameters(struct dvb_frontend* fe, | |||
367 | return ret; | 374 | return ret; |
368 | } | 375 | } |
369 | printk("or51132: Firmware upload complete.\n"); | 376 | printk("or51132: Firmware upload complete.\n"); |
370 | 377 | state->config->set_ts_params(fe, clock_mode); | |
378 | } | ||
379 | /* Change only if we are actually changing the modulation */ | ||
380 | if (state->current_modulation != param->u.vsb.modulation) { | ||
371 | state->current_modulation = param->u.vsb.modulation; | 381 | state->current_modulation = param->u.vsb.modulation; |
372 | or51132_setmode(fe); | 382 | or51132_setmode(fe); |
373 | } | 383 | } |
374 | 384 | ||
375 | dvb_pll_configure(state->config->pll_desc, buf, | 385 | if (fe->ops.tuner_ops.set_params) { |
376 | param->frequency, 0); | 386 | fe->ops.tuner_ops.set_params(fe, param); |
377 | dprintk("set_parameters tuner bytes: 0x%02x 0x%02x " | 387 | if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0); |
378 | "0x%02x 0x%02x\n",buf[0],buf[1],buf[2],buf[3]); | 388 | } |
379 | if (i2c_writebytes(state, state->config->pll_address ,buf, 4)) | ||
380 | printk(KERN_WARNING "or51132: set_parameters error " | ||
381 | "writing to tuner\n"); | ||
382 | 389 | ||
383 | /* Set to current mode */ | 390 | /* Set to current mode */ |
384 | or51132_setmode(fe); | 391 | or51132_setmode(fe); |
@@ -388,6 +395,44 @@ static int or51132_set_parameters(struct dvb_frontend* fe, | |||
388 | return 0; | 395 | return 0; |
389 | } | 396 | } |
390 | 397 | ||
398 | static int or51132_get_parameters(struct dvb_frontend* fe, | ||
399 | struct dvb_frontend_parameters *param) | ||
400 | { | ||
401 | struct or51132_state* state = fe->demodulator_priv; | ||
402 | u8 buf[2]; | ||
403 | |||
404 | /* Receiver Status */ | ||
405 | buf[0]=0x04; | ||
406 | buf[1]=0x00; | ||
407 | msleep(30); /* 30ms */ | ||
408 | if (i2c_writebytes(state,state->config->demod_address,buf,2)) { | ||
409 | printk(KERN_WARNING "or51132: get_parameters write error\n"); | ||
410 | return -EREMOTEIO; | ||
411 | } | ||
412 | msleep(30); /* 30ms */ | ||
413 | if (i2c_readbytes(state,state->config->demod_address,buf,2)) { | ||
414 | printk(KERN_WARNING "or51132: get_parameters read error\n"); | ||
415 | return -EREMOTEIO; | ||
416 | } | ||
417 | switch(buf[0]) { | ||
418 | case 0x06: param->u.vsb.modulation = VSB_8; break; | ||
419 | case 0x43: param->u.vsb.modulation = QAM_64; break; | ||
420 | case 0x45: param->u.vsb.modulation = QAM_256; break; | ||
421 | default: | ||
422 | printk(KERN_WARNING "or51132: unknown status 0x%02x\n", | ||
423 | buf[0]); | ||
424 | return -EREMOTEIO; | ||
425 | } | ||
426 | |||
427 | /* FIXME: Read frequency from frontend, take AFC into account */ | ||
428 | param->frequency = state->current_frequency; | ||
429 | |||
430 | /* FIXME: How to read inversion setting? Receiver 6 register? */ | ||
431 | param->inversion = INVERSION_AUTO; | ||
432 | |||
433 | return 0; | ||
434 | } | ||
435 | |||
391 | static int or51132_read_status(struct dvb_frontend* fe, fe_status_t* status) | 436 | static int or51132_read_status(struct dvb_frontend* fe, fe_status_t* status) |
392 | { | 437 | { |
393 | struct or51132_state* state = fe->demodulator_priv; | 438 | struct or51132_state* state = fe->demodulator_priv; |
@@ -572,12 +617,11 @@ struct dvb_frontend* or51132_attach(const struct or51132_config* config, | |||
572 | /* Setup the state */ | 617 | /* Setup the state */ |
573 | state->config = config; | 618 | state->config = config; |
574 | state->i2c = i2c; | 619 | state->i2c = i2c; |
575 | memcpy(&state->ops, &or51132_ops, sizeof(struct dvb_frontend_ops)); | ||
576 | state->current_frequency = -1; | 620 | state->current_frequency = -1; |
577 | state->current_modulation = -1; | 621 | state->current_modulation = -1; |
578 | 622 | ||
579 | /* Create dvb_frontend */ | 623 | /* Create dvb_frontend */ |
580 | state->frontend.ops = &state->ops; | 624 | memcpy(&state->frontend.ops, &or51132_ops, sizeof(struct dvb_frontend_ops)); |
581 | state->frontend.demodulator_priv = state; | 625 | state->frontend.demodulator_priv = state; |
582 | return &state->frontend; | 626 | return &state->frontend; |
583 | 627 | ||
@@ -590,7 +634,7 @@ static struct dvb_frontend_ops or51132_ops = { | |||
590 | 634 | ||
591 | .info = { | 635 | .info = { |
592 | .name = "Oren OR51132 VSB/QAM Frontend", | 636 | .name = "Oren OR51132 VSB/QAM Frontend", |
593 | .type = FE_ATSC, | 637 | .type = FE_ATSC, |
594 | .frequency_min = 44000000, | 638 | .frequency_min = 44000000, |
595 | .frequency_max = 958000000, | 639 | .frequency_max = 958000000, |
596 | .frequency_stepsize = 166666, | 640 | .frequency_stepsize = 166666, |
@@ -606,6 +650,7 @@ static struct dvb_frontend_ops or51132_ops = { | |||
606 | .sleep = or51132_sleep, | 650 | .sleep = or51132_sleep, |
607 | 651 | ||
608 | .set_frontend = or51132_set_parameters, | 652 | .set_frontend = or51132_set_parameters, |
653 | .get_frontend = or51132_get_parameters, | ||
609 | .get_tune_settings = or51132_get_tune_settings, | 654 | .get_tune_settings = or51132_get_tune_settings, |
610 | 655 | ||
611 | .read_status = or51132_read_status, | 656 | .read_status = or51132_read_status, |