diff options
Diffstat (limited to 'drivers/media/dvb/frontends/tda10023.c')
-rw-r--r-- | drivers/media/dvb/frontends/tda10023.c | 103 |
1 files changed, 70 insertions, 33 deletions
diff --git a/drivers/media/dvb/frontends/tda10023.c b/drivers/media/dvb/frontends/tda10023.c index a3c34eecdee9..ca1e0d54b69a 100644 --- a/drivers/media/dvb/frontends/tda10023.c +++ b/drivers/media/dvb/frontends/tda10023.c | |||
@@ -298,42 +298,80 @@ static int tda10023_init (struct dvb_frontend *fe) | |||
298 | return 0; | 298 | return 0; |
299 | } | 299 | } |
300 | 300 | ||
301 | static int tda10023_set_parameters (struct dvb_frontend *fe, | 301 | struct qam_params { |
302 | struct dvb_frontend_parameters *p) | 302 | u8 qam, lockthr, mseth, aref, agcrefnyq, eragnyq_thd; |
303 | }; | ||
304 | |||
305 | static int tda10023_set_parameters(struct dvb_frontend *fe) | ||
303 | { | 306 | { |
307 | struct dtv_frontend_properties *c = &fe->dtv_property_cache; | ||
308 | u32 delsys = c->delivery_system; | ||
309 | unsigned qam = c->modulation; | ||
310 | bool is_annex_c; | ||
304 | struct tda10023_state* state = fe->demodulator_priv; | 311 | struct tda10023_state* state = fe->demodulator_priv; |
305 | 312 | static const struct qam_params qam_params[] = { | |
306 | static int qamvals[6][6] = { | 313 | /* Modulation QAM LOCKTHR MSETH AREF AGCREFNYQ ERAGCNYQ_THD */ |
307 | // QAM LOCKTHR MSETH AREF AGCREFNYQ ERAGCNYQ_THD | 314 | [QPSK] = { (5<<2), 0x78, 0x8c, 0x96, 0x78, 0x4c }, |
308 | { (5<<2), 0x78, 0x8c, 0x96, 0x78, 0x4c }, // 4 QAM | 315 | [QAM_16] = { (0<<2), 0x87, 0xa2, 0x91, 0x8c, 0x57 }, |
309 | { (0<<2), 0x87, 0xa2, 0x91, 0x8c, 0x57 }, // 16 QAM | 316 | [QAM_32] = { (1<<2), 0x64, 0x74, 0x96, 0x8c, 0x57 }, |
310 | { (1<<2), 0x64, 0x74, 0x96, 0x8c, 0x57 }, // 32 QAM | 317 | [QAM_64] = { (2<<2), 0x46, 0x43, 0x6a, 0x6a, 0x44 }, |
311 | { (2<<2), 0x46, 0x43, 0x6a, 0x6a, 0x44 }, // 64 QAM | 318 | [QAM_128] = { (3<<2), 0x36, 0x34, 0x7e, 0x78, 0x4c }, |
312 | { (3<<2), 0x36, 0x34, 0x7e, 0x78, 0x4c }, // 128 QAM | 319 | [QAM_256] = { (4<<2), 0x26, 0x23, 0x6c, 0x5c, 0x3c }, |
313 | { (4<<2), 0x26, 0x23, 0x6c, 0x5c, 0x3c }, // 256 QAM | ||
314 | }; | 320 | }; |
315 | 321 | ||
316 | int qam = p->u.qam.modulation; | 322 | switch (delsys) { |
323 | case SYS_DVBC_ANNEX_A: | ||
324 | is_annex_c = false; | ||
325 | break; | ||
326 | case SYS_DVBC_ANNEX_C: | ||
327 | is_annex_c = true; | ||
328 | break; | ||
329 | default: | ||
330 | return -EINVAL; | ||
331 | } | ||
317 | 332 | ||
318 | if (qam < 0 || qam > 5) | 333 | /* |
334 | * gcc optimizes the code bellow the same way as it would code: | ||
335 | * "if (qam > 5) return -EINVAL;" | ||
336 | * Yet, the code is clearer, as it shows what QAM standards are | ||
337 | * supported by the driver, and avoids the usage of magic numbers on | ||
338 | * it. | ||
339 | */ | ||
340 | switch (qam) { | ||
341 | case QPSK: | ||
342 | case QAM_16: | ||
343 | case QAM_32: | ||
344 | case QAM_64: | ||
345 | case QAM_128: | ||
346 | case QAM_256: | ||
347 | break; | ||
348 | default: | ||
319 | return -EINVAL; | 349 | return -EINVAL; |
350 | } | ||
320 | 351 | ||
321 | if (fe->ops.tuner_ops.set_params) { | 352 | if (fe->ops.tuner_ops.set_params) { |
322 | fe->ops.tuner_ops.set_params(fe, p); | 353 | fe->ops.tuner_ops.set_params(fe); |
323 | if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0); | 354 | if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0); |
324 | } | 355 | } |
325 | 356 | ||
326 | tda10023_set_symbolrate (state, p->u.qam.symbol_rate); | 357 | tda10023_set_symbolrate(state, c->symbol_rate); |
327 | tda10023_writereg (state, 0x05, qamvals[qam][1]); | 358 | tda10023_writereg(state, 0x05, qam_params[qam].lockthr); |
328 | tda10023_writereg (state, 0x08, qamvals[qam][2]); | 359 | tda10023_writereg(state, 0x08, qam_params[qam].mseth); |
329 | tda10023_writereg (state, 0x09, qamvals[qam][3]); | 360 | tda10023_writereg(state, 0x09, qam_params[qam].aref); |
330 | tda10023_writereg (state, 0xb4, qamvals[qam][4]); | 361 | tda10023_writereg(state, 0xb4, qam_params[qam].agcrefnyq); |
331 | tda10023_writereg (state, 0xb6, qamvals[qam][5]); | 362 | tda10023_writereg(state, 0xb6, qam_params[qam].eragnyq_thd); |
332 | 363 | #if 0 | |
333 | // tda10023_writereg (state, 0x04, (p->inversion?0x12:0x32)); | 364 | tda10023_writereg(state, 0x04, (c->inversion ? 0x12 : 0x32)); |
334 | // tda10023_writebit (state, 0x04, 0x60, (p->inversion?0:0x20)); | 365 | tda10023_writebit(state, 0x04, 0x60, (c->inversion ? 0 : 0x20)); |
335 | tda10023_writebit (state, 0x04, 0x40, 0x40); | 366 | #endif |
336 | tda10023_setup_reg0 (state, qamvals[qam][0]); | 367 | tda10023_writebit(state, 0x04, 0x40, 0x40); |
368 | |||
369 | if (is_annex_c) | ||
370 | tda10023_writebit(state, 0x3d, 0xfc, 0x03); | ||
371 | else | ||
372 | tda10023_writebit(state, 0x3d, 0xfc, 0x02); | ||
373 | |||
374 | tda10023_setup_reg0(state, qam_params[qam].qam); | ||
337 | 375 | ||
338 | return 0; | 376 | return 0; |
339 | } | 377 | } |
@@ -418,8 +456,9 @@ static int tda10023_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks) | |||
418 | return 0; | 456 | return 0; |
419 | } | 457 | } |
420 | 458 | ||
421 | static int tda10023_get_frontend(struct dvb_frontend* fe, struct dvb_frontend_parameters *p) | 459 | static int tda10023_get_frontend(struct dvb_frontend *fe) |
422 | { | 460 | { |
461 | struct dtv_frontend_properties *p = &fe->dtv_property_cache; | ||
423 | struct tda10023_state* state = fe->demodulator_priv; | 462 | struct tda10023_state* state = fe->demodulator_priv; |
424 | int sync,inv; | 463 | int sync,inv; |
425 | s8 afc = 0; | 464 | s8 afc = 0; |
@@ -433,17 +472,17 @@ static int tda10023_get_frontend(struct dvb_frontend* fe, struct dvb_frontend_pa | |||
433 | printk(sync & 2 ? "DVB: TDA10023(%d): AFC (%d) %dHz\n" : | 472 | printk(sync & 2 ? "DVB: TDA10023(%d): AFC (%d) %dHz\n" : |
434 | "DVB: TDA10023(%d): [AFC (%d) %dHz]\n", | 473 | "DVB: TDA10023(%d): [AFC (%d) %dHz]\n", |
435 | state->frontend.dvb->num, afc, | 474 | state->frontend.dvb->num, afc, |
436 | -((s32)p->u.qam.symbol_rate * afc) >> 10); | 475 | -((s32)p->symbol_rate * afc) >> 10); |
437 | } | 476 | } |
438 | 477 | ||
439 | p->inversion = (inv&0x20?0:1); | 478 | p->inversion = (inv&0x20?0:1); |
440 | p->u.qam.modulation = ((state->reg0 >> 2) & 7) + QAM_16; | 479 | p->modulation = ((state->reg0 >> 2) & 7) + QAM_16; |
441 | 480 | ||
442 | p->u.qam.fec_inner = FEC_NONE; | 481 | p->fec_inner = FEC_NONE; |
443 | p->frequency = ((p->frequency + 31250) / 62500) * 62500; | 482 | p->frequency = ((p->frequency + 31250) / 62500) * 62500; |
444 | 483 | ||
445 | if (sync & 2) | 484 | if (sync & 2) |
446 | p->frequency -= ((s32)p->u.qam.symbol_rate * afc) >> 10; | 485 | p->frequency -= ((s32)p->symbol_rate * afc) >> 10; |
447 | 486 | ||
448 | return 0; | 487 | return 0; |
449 | } | 488 | } |
@@ -534,10 +573,9 @@ error: | |||
534 | } | 573 | } |
535 | 574 | ||
536 | static struct dvb_frontend_ops tda10023_ops = { | 575 | static struct dvb_frontend_ops tda10023_ops = { |
537 | 576 | .delsys = { SYS_DVBC_ANNEX_A, SYS_DVBC_ANNEX_C }, | |
538 | .info = { | 577 | .info = { |
539 | .name = "Philips TDA10023 DVB-C", | 578 | .name = "Philips TDA10023 DVB-C", |
540 | .type = FE_QAM, | ||
541 | .frequency_stepsize = 62500, | 579 | .frequency_stepsize = 62500, |
542 | .frequency_min = 47000000, | 580 | .frequency_min = 47000000, |
543 | .frequency_max = 862000000, | 581 | .frequency_max = 862000000, |
@@ -557,7 +595,6 @@ static struct dvb_frontend_ops tda10023_ops = { | |||
557 | 595 | ||
558 | .set_frontend = tda10023_set_parameters, | 596 | .set_frontend = tda10023_set_parameters, |
559 | .get_frontend = tda10023_get_frontend, | 597 | .get_frontend = tda10023_get_frontend, |
560 | |||
561 | .read_status = tda10023_read_status, | 598 | .read_status = tda10023_read_status, |
562 | .read_ber = tda10023_read_ber, | 599 | .read_ber = tda10023_read_ber, |
563 | .read_signal_strength = tda10023_read_signal_strength, | 600 | .read_signal_strength = tda10023_read_signal_strength, |