aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/dvb/frontends/tda10021.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/media/dvb/frontends/tda10021.c')
-rw-r--r--drivers/media/dvb/frontends/tda10021.c111
1 files changed, 75 insertions, 36 deletions
diff --git a/drivers/media/dvb/frontends/tda10021.c b/drivers/media/dvb/frontends/tda10021.c
index 6ca533ea0f0..1bff7f457e1 100644
--- a/drivers/media/dvb/frontends/tda10021.c
+++ b/drivers/media/dvb/frontends/tda10021.c
@@ -224,47 +224,86 @@ static int tda10021_init (struct dvb_frontend *fe)
224 return 0; 224 return 0;
225} 225}
226 226
227static int tda10021_set_parameters (struct dvb_frontend *fe, 227struct qam_params {
228 struct dvb_frontend_parameters *p) 228 u8 conf, agcref, lthr, mseth, aref;
229};
230
231static int tda10021_set_parameters(struct dvb_frontend *fe)
229{ 232{
233 struct dtv_frontend_properties *c = &fe->dtv_property_cache;
234 u32 delsys = c->delivery_system;
235 unsigned qam = c->modulation;
236 bool is_annex_c;
237 u32 reg0x3d;
230 struct tda10021_state* state = fe->demodulator_priv; 238 struct tda10021_state* state = fe->demodulator_priv;
239 static const struct qam_params qam_params[] = {
240 /* Modulation Conf AGCref LTHR MSETH AREF */
241 [QPSK] = { 0x14, 0x78, 0x78, 0x8c, 0x96 },
242 [QAM_16] = { 0x00, 0x8c, 0x87, 0xa2, 0x91 },
243 [QAM_32] = { 0x04, 0x8c, 0x64, 0x74, 0x96 },
244 [QAM_64] = { 0x08, 0x6a, 0x46, 0x43, 0x6a },
245 [QAM_128] = { 0x0c, 0x78, 0x36, 0x34, 0x7e },
246 [QAM_256] = { 0x10, 0x5c, 0x26, 0x23, 0x6b },
247 };
248
249 switch (delsys) {
250 case SYS_DVBC_ANNEX_A:
251 is_annex_c = false;
252 break;
253 case SYS_DVBC_ANNEX_C:
254 is_annex_c = true;
255 break;
256 default:
257 return -EINVAL;
258 }
231 259
232 //table for QAM4-QAM256 ready QAM4 QAM16 QAM32 QAM64 QAM128 QAM256 260 /*
233 //CONF 261 * gcc optimizes the code bellow the same way as it would code:
234 static const u8 reg0x00 [] = { 0x14, 0x00, 0x04, 0x08, 0x0c, 0x10 }; 262 * "if (qam > 5) return -EINVAL;"
235 //AGCREF value 263 * Yet, the code is clearer, as it shows what QAM standards are
236 static const u8 reg0x01 [] = { 0x78, 0x8c, 0x8c, 0x6a, 0x78, 0x5c }; 264 * supported by the driver, and avoids the usage of magic numbers on
237 //LTHR value 265 * it.
238 static const u8 reg0x05 [] = { 0x78, 0x87, 0x64, 0x46, 0x36, 0x26 }; 266 */
239 //MSETH 267 switch (qam) {
240 static const u8 reg0x08 [] = { 0x8c, 0xa2, 0x74, 0x43, 0x34, 0x23 }; 268 case QPSK:
241 //AREF 269 case QAM_16:
242 static const u8 reg0x09 [] = { 0x96, 0x91, 0x96, 0x6a, 0x7e, 0x6b }; 270 case QAM_32:
243 271 case QAM_64:
244 int qam = p->u.qam.modulation; 272 case QAM_128:
245 273 case QAM_256:
246 if (qam < 0 || qam > 5) 274 break;
275 default:
247 return -EINVAL; 276 return -EINVAL;
277 }
248 278
249 if (p->inversion != INVERSION_ON && p->inversion != INVERSION_OFF) 279 if (c->inversion != INVERSION_ON && c->inversion != INVERSION_OFF)
250 return -EINVAL; 280 return -EINVAL;
251 281
252 //printk("tda10021: set frequency to %d qam=%d symrate=%d\n", p->frequency,qam,p->u.qam.symbol_rate); 282 /*printk("tda10021: set frequency to %d qam=%d symrate=%d\n", p->frequency,qam,p->symbol_rate);*/
253 283
254 if (fe->ops.tuner_ops.set_params) { 284 if (fe->ops.tuner_ops.set_params) {
255 fe->ops.tuner_ops.set_params(fe, p); 285 fe->ops.tuner_ops.set_params(fe);
256 if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0); 286 if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0);
257 } 287 }
258 288
259 tda10021_set_symbolrate (state, p->u.qam.symbol_rate); 289 tda10021_set_symbolrate(state, c->symbol_rate);
260 _tda10021_writereg (state, 0x34, state->pwm); 290 _tda10021_writereg(state, 0x34, state->pwm);
261 291
262 _tda10021_writereg (state, 0x01, reg0x01[qam]); 292 _tda10021_writereg(state, 0x01, qam_params[qam].agcref);
263 _tda10021_writereg (state, 0x05, reg0x05[qam]); 293 _tda10021_writereg(state, 0x05, qam_params[qam].lthr);
264 _tda10021_writereg (state, 0x08, reg0x08[qam]); 294 _tda10021_writereg(state, 0x08, qam_params[qam].mseth);
265 _tda10021_writereg (state, 0x09, reg0x09[qam]); 295 _tda10021_writereg(state, 0x09, qam_params[qam].aref);
266 296
267 tda10021_setup_reg0 (state, reg0x00[qam], p->inversion); 297 /*
298 * Bit 0 == 0 means roll-off = 0.15 (Annex A)
299 * == 1 means roll-off = 0.13 (Annex C)
300 */
301 reg0x3d = tda10021_readreg (state, 0x3d);
302 if (is_annex_c)
303 _tda10021_writereg (state, 0x3d, 0x01 | reg0x3d);
304 else
305 _tda10021_writereg (state, 0x3d, 0xfe & reg0x3d);
306 tda10021_setup_reg0(state, qam_params[qam].conf, c->inversion);
268 307
269 return 0; 308 return 0;
270} 309}
@@ -347,8 +386,9 @@ static int tda10021_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks)
347 return 0; 386 return 0;
348} 387}
349 388
350static int tda10021_get_frontend(struct dvb_frontend* fe, struct dvb_frontend_parameters *p) 389static int tda10021_get_frontend(struct dvb_frontend *fe)
351{ 390{
391 struct dtv_frontend_properties *p = &fe->dtv_property_cache;
352 struct tda10021_state* state = fe->demodulator_priv; 392 struct tda10021_state* state = fe->demodulator_priv;
353 int sync; 393 int sync;
354 s8 afc = 0; 394 s8 afc = 0;
@@ -360,17 +400,17 @@ static int tda10021_get_frontend(struct dvb_frontend* fe, struct dvb_frontend_pa
360 printk(sync & 2 ? "DVB: TDA10021(%d): AFC (%d) %dHz\n" : 400 printk(sync & 2 ? "DVB: TDA10021(%d): AFC (%d) %dHz\n" :
361 "DVB: TDA10021(%d): [AFC (%d) %dHz]\n", 401 "DVB: TDA10021(%d): [AFC (%d) %dHz]\n",
362 state->frontend.dvb->num, afc, 402 state->frontend.dvb->num, afc,
363 -((s32)p->u.qam.symbol_rate * afc) >> 10); 403 -((s32)p->symbol_rate * afc) >> 10);
364 } 404 }
365 405
366 p->inversion = ((state->reg0 & 0x20) == 0x20) ^ (state->config->invert != 0) ? INVERSION_ON : INVERSION_OFF; 406 p->inversion = ((state->reg0 & 0x20) == 0x20) ^ (state->config->invert != 0) ? INVERSION_ON : INVERSION_OFF;
367 p->u.qam.modulation = ((state->reg0 >> 2) & 7) + QAM_16; 407 p->modulation = ((state->reg0 >> 2) & 7) + QAM_16;
368 408
369 p->u.qam.fec_inner = FEC_NONE; 409 p->fec_inner = FEC_NONE;
370 p->frequency = ((p->frequency + 31250) / 62500) * 62500; 410 p->frequency = ((p->frequency + 31250) / 62500) * 62500;
371 411
372 if (sync & 2) 412 if (sync & 2)
373 p->frequency -= ((s32)p->u.qam.symbol_rate * afc) >> 10; 413 p->frequency -= ((s32)p->symbol_rate * afc) >> 10;
374 414
375 return 0; 415 return 0;
376} 416}
@@ -444,10 +484,9 @@ error:
444} 484}
445 485
446static struct dvb_frontend_ops tda10021_ops = { 486static struct dvb_frontend_ops tda10021_ops = {
447 487 .delsys = { SYS_DVBC_ANNEX_A, SYS_DVBC_ANNEX_C },
448 .info = { 488 .info = {
449 .name = "Philips TDA10021 DVB-C", 489 .name = "Philips TDA10021 DVB-C",
450 .type = FE_QAM,
451 .frequency_stepsize = 62500, 490 .frequency_stepsize = 62500,
452 .frequency_min = 47000000, 491 .frequency_min = 47000000,
453 .frequency_max = 862000000, 492 .frequency_max = 862000000,