diff options
-rw-r--r-- | drivers/media/dvb/frontends/tda10021.c | 49 |
1 files changed, 45 insertions, 4 deletions
diff --git a/drivers/media/dvb/frontends/tda10021.c b/drivers/media/dvb/frontends/tda10021.c index cd9952ed295b..2518c5a33225 100644 --- a/drivers/media/dvb/frontends/tda10021.c +++ b/drivers/media/dvb/frontends/tda10021.c | |||
@@ -231,6 +231,11 @@ struct qam_params { | |||
231 | static int tda10021_set_parameters (struct dvb_frontend *fe, | 231 | static int tda10021_set_parameters (struct dvb_frontend *fe, |
232 | struct dvb_frontend_parameters *p) | 232 | struct dvb_frontend_parameters *p) |
233 | { | 233 | { |
234 | struct dtv_frontend_properties *c = &fe->dtv_property_cache; | ||
235 | u32 delsys = c->delivery_system; | ||
236 | unsigned qam = c->modulation; | ||
237 | bool is_annex_c; | ||
238 | u32 reg0x3d; | ||
234 | struct tda10021_state* state = fe->demodulator_priv; | 239 | struct tda10021_state* state = fe->demodulator_priv; |
235 | static const struct qam_params qam_params[] = { | 240 | static const struct qam_params qam_params[] = { |
236 | /* Modulation Conf AGCref LTHR MSETH AREF */ | 241 | /* Modulation Conf AGCref LTHR MSETH AREF */ |
@@ -241,7 +246,17 @@ static int tda10021_set_parameters (struct dvb_frontend *fe, | |||
241 | [QAM_128] = { 0x0c, 0x78, 0x36, 0x34, 0x7e }, | 246 | [QAM_128] = { 0x0c, 0x78, 0x36, 0x34, 0x7e }, |
242 | [QAM_256] = { 0x10, 0x5c, 0x26, 0x23, 0x6b }, | 247 | [QAM_256] = { 0x10, 0x5c, 0x26, 0x23, 0x6b }, |
243 | }; | 248 | }; |
244 | int qam = p->u.qam.modulation; | 249 | |
250 | switch (delsys) { | ||
251 | case SYS_DVBC_ANNEX_A: | ||
252 | is_annex_c = false; | ||
253 | break; | ||
254 | case SYS_DVBC_ANNEX_C: | ||
255 | is_annex_c = true; | ||
256 | break; | ||
257 | default: | ||
258 | return -EINVAL; | ||
259 | } | ||
245 | 260 | ||
246 | /* | 261 | /* |
247 | * gcc optimizes the code bellow the same way as it would code: | 262 | * gcc optimizes the code bellow the same way as it would code: |
@@ -262,7 +277,7 @@ static int tda10021_set_parameters (struct dvb_frontend *fe, | |||
262 | return -EINVAL; | 277 | return -EINVAL; |
263 | } | 278 | } |
264 | 279 | ||
265 | if (p->inversion != INVERSION_ON && p->inversion != INVERSION_OFF) | 280 | if (c->inversion != INVERSION_ON && c->inversion != INVERSION_OFF) |
266 | return -EINVAL; | 281 | return -EINVAL; |
267 | 282 | ||
268 | //printk("tda10021: set frequency to %d qam=%d symrate=%d\n", p->frequency,qam,p->u.qam.symbol_rate); | 283 | //printk("tda10021: set frequency to %d qam=%d symrate=%d\n", p->frequency,qam,p->u.qam.symbol_rate); |
@@ -272,14 +287,24 @@ static int tda10021_set_parameters (struct dvb_frontend *fe, | |||
272 | if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0); | 287 | if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0); |
273 | } | 288 | } |
274 | 289 | ||
275 | tda10021_set_symbolrate(state, p->u.qam.symbol_rate); | 290 | tda10021_set_symbolrate(state, c->symbol_rate); |
276 | _tda10021_writereg(state, 0x34, state->pwm); | 291 | _tda10021_writereg(state, 0x34, state->pwm); |
277 | 292 | ||
278 | _tda10021_writereg(state, 0x01, qam_params[qam].agcref); | 293 | _tda10021_writereg(state, 0x01, qam_params[qam].agcref); |
279 | _tda10021_writereg(state, 0x05, qam_params[qam].lthr); | 294 | _tda10021_writereg(state, 0x05, qam_params[qam].lthr); |
280 | _tda10021_writereg(state, 0x08, qam_params[qam].mseth); | 295 | _tda10021_writereg(state, 0x08, qam_params[qam].mseth); |
281 | _tda10021_writereg(state, 0x09, qam_params[qam].aref); | 296 | _tda10021_writereg(state, 0x09, qam_params[qam].aref); |
282 | tda10021_setup_reg0(state, qam_params[qam].conf, p->inversion); | 297 | |
298 | /* | ||
299 | * Bit 0 == 0 means roll-off = 0.15 (Annex A) | ||
300 | * == 1 means roll-off = 0.13 (Annex C) | ||
301 | */ | ||
302 | reg0x3d = tda10021_readreg (state, 0x3d); | ||
303 | if (is_annex_c) | ||
304 | _tda10021_writereg (state, 0x3d, 0x01 | reg0x3d); | ||
305 | else | ||
306 | _tda10021_writereg (state, 0x3d, 0xfe & reg0x3d); | ||
307 | tda10021_setup_reg0(state, qam_params[qam].conf, c->inversion); | ||
283 | 308 | ||
284 | return 0; | 309 | return 0; |
285 | } | 310 | } |
@@ -458,6 +483,21 @@ error: | |||
458 | return NULL; | 483 | return NULL; |
459 | } | 484 | } |
460 | 485 | ||
486 | static int tda10021_get_property(struct dvb_frontend *fe, | ||
487 | struct dtv_property *p) | ||
488 | { | ||
489 | switch (p->cmd) { | ||
490 | case DTV_ENUM_DELSYS: | ||
491 | p->u.buffer.data[0] = SYS_DVBC_ANNEX_A; | ||
492 | p->u.buffer.data[1] = SYS_DVBC_ANNEX_C; | ||
493 | p->u.buffer.len = 2; | ||
494 | break; | ||
495 | default: | ||
496 | break; | ||
497 | } | ||
498 | return 0; | ||
499 | } | ||
500 | |||
461 | static struct dvb_frontend_ops tda10021_ops = { | 501 | static struct dvb_frontend_ops tda10021_ops = { |
462 | 502 | ||
463 | .info = { | 503 | .info = { |
@@ -486,6 +526,7 @@ static struct dvb_frontend_ops tda10021_ops = { | |||
486 | 526 | ||
487 | .set_frontend = tda10021_set_parameters, | 527 | .set_frontend = tda10021_set_parameters, |
488 | .get_frontend = tda10021_get_frontend, | 528 | .get_frontend = tda10021_get_frontend, |
529 | .get_property = tda10021_get_property, | ||
489 | 530 | ||
490 | .read_status = tda10021_read_status, | 531 | .read_status = tda10021_read_status, |
491 | .read_ber = tda10021_read_ber, | 532 | .read_ber = tda10021_read_ber, |