diff options
author | Mauro Carvalho Chehab <mchehab@redhat.com> | 2013-03-20 07:21:52 -0400 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2013-03-21 09:27:05 -0400 |
commit | 59a7a23c4755f12757fe17234c693188a9e6bcf5 (patch) | |
tree | e202191ff14e7876c0548d6e6397354a592c49de | |
parent | 8f3741e02831d1181be9ca0ea711dd0c8d7f8a7b (diff) |
[media] drxk: use a better calculus for RF strength
The AZ6007 driver released by Terratec has a better way to
estimate the signal strength, at CtrlSigStrength(). Port it
to the driver.
It should be noticed that there are two parameters there that
are tuner-specific.
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
-rw-r--r-- | drivers/media/dvb-frontends/drxk_hard.c | 126 |
1 files changed, 109 insertions, 17 deletions
diff --git a/drivers/media/dvb-frontends/drxk_hard.c b/drivers/media/dvb-frontends/drxk_hard.c index 8c4de7cc4500..6e250533b628 100644 --- a/drivers/media/dvb-frontends/drxk_hard.c +++ b/drivers/media/dvb-frontends/drxk_hard.c | |||
@@ -6390,6 +6390,107 @@ static int drxk_set_parameters(struct dvb_frontend *fe) | |||
6390 | return 0; | 6390 | return 0; |
6391 | } | 6391 | } |
6392 | 6392 | ||
6393 | static int get_strength(struct drxk_state *state, u64 *strength) | ||
6394 | { | ||
6395 | int status; | ||
6396 | struct SCfgAgc rfAgc, ifAgc; | ||
6397 | u32 totalGain = 0; | ||
6398 | u32 atten = 0; | ||
6399 | u32 agcRange = 0; | ||
6400 | u16 scu_lvl = 0; | ||
6401 | u16 scu_coc = 0; | ||
6402 | /* FIXME: those are part of the tuner presets */ | ||
6403 | u16 tunerRfGain = 50; /* Default value on az6007 driver */ | ||
6404 | u16 tunerIfGain = 40; /* Default value on az6007 driver */ | ||
6405 | |||
6406 | *strength = 0; | ||
6407 | |||
6408 | if (IsDVBT(state)) { | ||
6409 | rfAgc = state->m_dvbtRfAgcCfg; | ||
6410 | ifAgc = state->m_dvbtIfAgcCfg; | ||
6411 | } else if (IsQAM(state)) { | ||
6412 | rfAgc = state->m_qamRfAgcCfg; | ||
6413 | ifAgc = state->m_qamIfAgcCfg; | ||
6414 | } else { | ||
6415 | rfAgc = state->m_atvRfAgcCfg; | ||
6416 | ifAgc = state->m_atvIfAgcCfg; | ||
6417 | } | ||
6418 | |||
6419 | if (rfAgc.ctrlMode == DRXK_AGC_CTRL_AUTO) { | ||
6420 | /* SCU outputLevel */ | ||
6421 | status = read16(state, SCU_RAM_AGC_RF_IACCU_HI__A, &scu_lvl); | ||
6422 | if (status < 0) | ||
6423 | return status; | ||
6424 | |||
6425 | /* SCU c.o.c. */ | ||
6426 | read16(state, SCU_RAM_AGC_RF_IACCU_HI_CO__A, &scu_coc); | ||
6427 | if (status < 0) | ||
6428 | return status; | ||
6429 | |||
6430 | if (((u32) scu_lvl + (u32) scu_coc) < 0xffff) | ||
6431 | rfAgc.outputLevel = scu_lvl + scu_coc; | ||
6432 | else | ||
6433 | rfAgc.outputLevel = 0xffff; | ||
6434 | |||
6435 | /* Take RF gain into account */ | ||
6436 | totalGain += tunerRfGain; | ||
6437 | |||
6438 | /* clip output value */ | ||
6439 | if (rfAgc.outputLevel < rfAgc.minOutputLevel) | ||
6440 | rfAgc.outputLevel = rfAgc.minOutputLevel; | ||
6441 | if (rfAgc.outputLevel > rfAgc.maxOutputLevel) | ||
6442 | rfAgc.outputLevel = rfAgc.maxOutputLevel; | ||
6443 | |||
6444 | agcRange = (u32) (rfAgc.maxOutputLevel - rfAgc.minOutputLevel); | ||
6445 | if (agcRange > 0) { | ||
6446 | atten += 100UL * | ||
6447 | ((u32)(tunerRfGain)) * | ||
6448 | ((u32)(rfAgc.outputLevel - rfAgc.minOutputLevel)) | ||
6449 | / agcRange; | ||
6450 | } | ||
6451 | } | ||
6452 | |||
6453 | if (ifAgc.ctrlMode == DRXK_AGC_CTRL_AUTO) { | ||
6454 | status = read16(state, SCU_RAM_AGC_IF_IACCU_HI__A, | ||
6455 | &ifAgc.outputLevel); | ||
6456 | if (status < 0) | ||
6457 | return status; | ||
6458 | |||
6459 | status = read16(state, SCU_RAM_AGC_INGAIN_TGT_MIN__A, | ||
6460 | &ifAgc.top); | ||
6461 | if (status < 0) | ||
6462 | return status; | ||
6463 | |||
6464 | /* Take IF gain into account */ | ||
6465 | totalGain += (u32) tunerIfGain; | ||
6466 | |||
6467 | /* clip output value */ | ||
6468 | if (ifAgc.outputLevel < ifAgc.minOutputLevel) | ||
6469 | ifAgc.outputLevel = ifAgc.minOutputLevel; | ||
6470 | if (ifAgc.outputLevel > ifAgc.maxOutputLevel) | ||
6471 | ifAgc.outputLevel = ifAgc.maxOutputLevel; | ||
6472 | |||
6473 | agcRange = (u32) (ifAgc.maxOutputLevel - ifAgc.minOutputLevel); | ||
6474 | if (agcRange > 0) { | ||
6475 | atten += 100UL * | ||
6476 | ((u32)(tunerIfGain)) * | ||
6477 | ((u32)(ifAgc.outputLevel - ifAgc.minOutputLevel)) | ||
6478 | / agcRange; | ||
6479 | } | ||
6480 | } | ||
6481 | |||
6482 | /* | ||
6483 | * Convert to 0..65535 scale. | ||
6484 | * If it can't be measured (AGC is disabled), just show 100%. | ||
6485 | */ | ||
6486 | if (totalGain > 0) | ||
6487 | *strength = (65535UL * atten / totalGain); | ||
6488 | else | ||
6489 | *strength = 65535; | ||
6490 | |||
6491 | return 0; | ||
6492 | } | ||
6493 | |||
6393 | static int drxk_get_stats(struct dvb_frontend *fe) | 6494 | static int drxk_get_stats(struct dvb_frontend *fe) |
6394 | { | 6495 | { |
6395 | struct dtv_frontend_properties *c = &fe->dtv_property_cache; | 6496 | struct dtv_frontend_properties *c = &fe->dtv_property_cache; |
@@ -6404,7 +6505,7 @@ static int drxk_get_stats(struct dvb_frontend *fe) | |||
6404 | u32 pre_bit_count; | 6505 | u32 pre_bit_count; |
6405 | u32 pkt_count; | 6506 | u32 pkt_count; |
6406 | u32 pkt_error_count; | 6507 | u32 pkt_error_count; |
6407 | s32 cnr, gain; | 6508 | s32 cnr; |
6408 | 6509 | ||
6409 | if (state->m_DrxkState == DRXK_NO_DEV) | 6510 | if (state->m_DrxkState == DRXK_NO_DEV) |
6410 | return -ENODEV; | 6511 | return -ENODEV; |
@@ -6421,6 +6522,13 @@ static int drxk_get_stats(struct dvb_frontend *fe) | |||
6421 | if (stat == DEMOD_LOCK) | 6522 | if (stat == DEMOD_LOCK) |
6422 | state->fe_status |= 0x07; | 6523 | state->fe_status |= 0x07; |
6423 | 6524 | ||
6525 | /* | ||
6526 | * Estimate signal strength from AGC | ||
6527 | */ | ||
6528 | get_strength(state, &c->strength.stat[0].uvalue); | ||
6529 | c->strength.stat[0].scale = FE_SCALE_RELATIVE; | ||
6530 | |||
6531 | |||
6424 | if (stat >= DEMOD_LOCK) { | 6532 | if (stat >= DEMOD_LOCK) { |
6425 | GetSignalToNoise(state, &cnr); | 6533 | GetSignalToNoise(state, &cnr); |
6426 | c->cnr.stat[0].svalue = cnr * 100; | 6534 | c->cnr.stat[0].svalue = cnr * 100; |
@@ -6500,22 +6608,6 @@ static int drxk_get_stats(struct dvb_frontend *fe) | |||
6500 | c->post_bit_count.stat[0].scale = FE_SCALE_COUNTER; | 6608 | c->post_bit_count.stat[0].scale = FE_SCALE_COUNTER; |
6501 | c->post_bit_count.stat[0].uvalue += post_bit_count; | 6609 | c->post_bit_count.stat[0].uvalue += post_bit_count; |
6502 | 6610 | ||
6503 | /* | ||
6504 | * Read AGC gain | ||
6505 | * | ||
6506 | * IFgain = (IQM_AF_AGC_IF__A * 26.75) (nA) | ||
6507 | */ | ||
6508 | status = read16(state, IQM_AF_AGC_IF__A, ®16); | ||
6509 | if (status < 0) { | ||
6510 | printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__); | ||
6511 | return status; | ||
6512 | } | ||
6513 | gain = 2675 * (reg16 - DRXK_AGC_DAC_OFFSET) / 100; | ||
6514 | |||
6515 | /* FIXME: it makes sense to fix the scale here to dBm */ | ||
6516 | c->strength.stat[0].scale = FE_SCALE_RELATIVE; | ||
6517 | c->strength.stat[0].uvalue = gain; | ||
6518 | |||
6519 | error: | 6611 | error: |
6520 | return status; | 6612 | return status; |
6521 | } | 6613 | } |