From patchwork Thu Jul 9 04:06:32 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Antti Palosaari X-Patchwork-Id: 6753021 Return-Path: X-Original-To: patchwork-linux-media@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork2.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.136]) by patchwork2.web.kernel.org (Postfix) with ESMTP id C323DC05AC for ; Thu, 9 Jul 2015 04:07:16 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 9B1BD20663 for ; Thu, 9 Jul 2015 04:07:15 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 25A7420694 for ; Thu, 9 Jul 2015 04:07:14 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751413AbbGIEHM (ORCPT ); Thu, 9 Jul 2015 00:07:12 -0400 Received: from mail.kapsi.fi ([217.30.184.167]:34791 "EHLO mail.kapsi.fi" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751351AbbGIEHB (ORCPT ); Thu, 9 Jul 2015 00:07:01 -0400 Received: from 85-23-164-218.bb.dnainternet.fi ([85.23.164.218] helo=localhost.localdomain.localdomain) by mail.kapsi.fi with esmtpsa (TLS1.2:DHE_RSA_AES_256_CBC_SHA256:256) (Exim 4.80) (envelope-from ) id 1ZD36t-0002AB-8H; Thu, 09 Jul 2015 07:06:55 +0300 From: Antti Palosaari To: linux-media@vger.kernel.org Cc: Antti Palosaari Subject: [PATCH 12/12] tda10071: implement DVBv5 statistics Date: Thu, 9 Jul 2015 07:06:32 +0300 Message-Id: <1436414792-9716-12-git-send-email-crope@iki.fi> X-Mailer: git-send-email 2.4.3 In-Reply-To: <1436414792-9716-1-git-send-email-crope@iki.fi> References: <1436414792-9716-1-git-send-email-crope@iki.fi> X-SA-Exim-Connect-IP: 85.23.164.218 X-SA-Exim-Mail-From: crope@iki.fi X-SA-Exim-Scanned: No (on mail.kapsi.fi); SAEximRunCond expanded to false Sender: linux-media-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-media@vger.kernel.org X-Spam-Status: No, score=-7.6 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_HI, RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP Implement DVBv5 CNR, signal strength, BER and block errors. Wrap legacy DVBv3 statistics to DVBv5 internally. Signed-off-by: Antti Palosaari --- drivers/media/dvb-frontends/tda10071.c | 258 ++++++++++++++-------------- drivers/media/dvb-frontends/tda10071_priv.h | 7 +- 2 files changed, 135 insertions(+), 130 deletions(-) diff --git a/drivers/media/dvb-frontends/tda10071.c b/drivers/media/dvb-frontends/tda10071.c index c661b74..9f930cf 100644 --- a/drivers/media/dvb-frontends/tda10071.c +++ b/drivers/media/dvb-frontends/tda10071.c @@ -380,8 +380,11 @@ static int tda10071_read_status(struct dvb_frontend *fe, enum fe_status *status) { struct tda10071_dev *dev = fe->demodulator_priv; struct i2c_client *client = dev->client; + struct dtv_frontend_properties *c = &fe->dtv_property_cache; + struct tda10071_cmd cmd; int ret; unsigned int uitmp; + u8 buf[8]; *status = 0; @@ -404,71 +407,105 @@ static int tda10071_read_status(struct dvb_frontend *fe, enum fe_status *status) dev->fe_status = *status; - return ret; -error: - dev_dbg(&client->dev, "failed=%d\n", ret); - return ret; -} + /* signal strength */ + if (dev->fe_status & FE_HAS_SIGNAL) { + cmd.args[0] = CMD_GET_AGCACC; + cmd.args[1] = 0; + cmd.len = 2; + ret = tda10071_cmd_execute(dev, &cmd); + if (ret) + goto error; -static int tda10071_read_snr(struct dvb_frontend *fe, u16 *snr) -{ - struct tda10071_dev *dev = fe->demodulator_priv; - struct i2c_client *client = dev->client; - int ret; - u8 buf[2]; + /* input power estimate dBm */ + ret = regmap_read(dev->regmap, 0x50, &uitmp); + if (ret) + goto error; - if (!dev->warm || !(dev->fe_status & FE_HAS_LOCK)) { - *snr = 0; - ret = 0; - goto error; + c->strength.stat[0].scale = FE_SCALE_DECIBEL; + c->strength.stat[0].svalue = (int) (uitmp - 256) * 1000; + } else { + c->strength.stat[0].scale = FE_SCALE_NOT_AVAILABLE; } - ret = regmap_bulk_read(dev->regmap, 0x3a, buf, 2); - if (ret) - goto error; + /* CNR */ + if (dev->fe_status & FE_HAS_VITERBI) { + /* Es/No */ + ret = regmap_bulk_read(dev->regmap, 0x3a, buf, 2); + if (ret) + goto error; - /* Es/No dBx10 */ - *snr = buf[0] << 8 | buf[1]; + c->cnr.stat[0].scale = FE_SCALE_DECIBEL; + c->cnr.stat[0].svalue = (buf[0] << 8 | buf[1] << 0) * 100; + } else { + c->cnr.stat[0].scale = FE_SCALE_NOT_AVAILABLE; + } - return ret; -error: - dev_dbg(&client->dev, "failed=%d\n", ret); - return ret; -} + /* UCB/PER/BER */ + if (dev->fe_status & FE_HAS_LOCK) { + /* TODO: report total bits/packets */ + u8 delivery_system, reg, len; -static int tda10071_read_signal_strength(struct dvb_frontend *fe, u16 *strength) -{ - struct tda10071_dev *dev = fe->demodulator_priv; - struct i2c_client *client = dev->client; - struct tda10071_cmd cmd; - int ret; - unsigned int uitmp; + switch (dev->delivery_system) { + case SYS_DVBS: + reg = 0x4c; + len = 8; + delivery_system = 1; + break; + case SYS_DVBS2: + reg = 0x4d; + len = 4; + delivery_system = 0; + break; + default: + ret = -EINVAL; + goto error; + } - if (!dev->warm || !(dev->fe_status & FE_HAS_LOCK)) { - *strength = 0; - ret = 0; - goto error; - } + ret = regmap_read(dev->regmap, reg, &uitmp); + if (ret) + goto error; - cmd.args[0] = CMD_GET_AGCACC; - cmd.args[1] = 0; - cmd.len = 2; - ret = tda10071_cmd_execute(dev, &cmd); - if (ret) - goto error; + if (dev->meas_count == uitmp) { + dev_dbg(&client->dev, "meas not ready=%02x\n", uitmp); + ret = 0; + goto error; + } else { + dev->meas_count = uitmp; + } - /* input power estimate dBm */ - ret = regmap_read(dev->regmap, 0x50, &uitmp); - if (ret) - goto error; + cmd.args[0] = CMD_BER_UPDATE_COUNTERS; + cmd.args[1] = 0; + cmd.args[2] = delivery_system; + cmd.len = 3; + ret = tda10071_cmd_execute(dev, &cmd); + if (ret) + goto error; - if (uitmp < 181) - uitmp = 181; /* -75 dBm */ - else if (uitmp > 236) - uitmp = 236; /* -20 dBm */ + ret = regmap_bulk_read(dev->regmap, cmd.len, buf, len); + if (ret) + goto error; - /* scale value to 0x0000-0xffff */ - *strength = (uitmp-181) * 0xffff / (236-181); + if (dev->delivery_system == SYS_DVBS) { + dev->dvbv3_ber = buf[0] << 24 | buf[1] << 16 | + buf[2] << 8 | buf[3] << 0; + dev->post_bit_error += buf[0] << 24 | buf[1] << 16 | + buf[2] << 8 | buf[3] << 0; + c->post_bit_error.stat[0].scale = FE_SCALE_COUNTER; + c->post_bit_error.stat[0].uvalue = dev->post_bit_error; + dev->block_error += buf[4] << 8 | buf[5] << 0; + c->block_error.stat[0].scale = FE_SCALE_COUNTER; + c->block_error.stat[0].uvalue = dev->block_error; + } else { + dev->dvbv3_ber = buf[0] << 8 | buf[1] << 0; + dev->post_bit_error += buf[0] << 8 | buf[1] << 0; + c->post_bit_error.stat[0].scale = FE_SCALE_COUNTER; + c->post_bit_error.stat[0].uvalue = dev->post_bit_error; + c->block_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE; + } + } else { + c->post_bit_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE; + c->block_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE; + } return ret; error: @@ -476,94 +513,50 @@ error: return ret; } -static int tda10071_read_ber(struct dvb_frontend *fe, u32 *ber) +static int tda10071_read_snr(struct dvb_frontend *fe, u16 *snr) { - struct tda10071_dev *dev = fe->demodulator_priv; - struct i2c_client *client = dev->client; - struct tda10071_cmd cmd; - int ret, i, len; - unsigned int uitmp; - u8 reg, buf[8]; - - if (!dev->warm || !(dev->fe_status & FE_HAS_LOCK)) { - *ber = dev->ber = 0; - ret = 0; - goto error; - } + struct dtv_frontend_properties *c = &fe->dtv_property_cache; - switch (dev->delivery_system) { - case SYS_DVBS: - reg = 0x4c; - len = 8; - i = 1; - break; - case SYS_DVBS2: - reg = 0x4d; - len = 4; - i = 0; - break; - default: - *ber = dev->ber = 0; - return 0; - } + if (c->cnr.stat[0].scale == FE_SCALE_DECIBEL) + *snr = div_s64(c->cnr.stat[0].svalue, 100); + else + *snr = 0; + return 0; +} - ret = regmap_read(dev->regmap, reg, &uitmp); - if (ret) - goto error; +static int tda10071_read_signal_strength(struct dvb_frontend *fe, u16 *strength) +{ + struct dtv_frontend_properties *c = &fe->dtv_property_cache; + unsigned int uitmp; - if (dev->meas_count[i] == uitmp) { - dev_dbg(&client->dev, "meas not ready=%02x\n", uitmp); - *ber = dev->ber; - return 0; + if (c->strength.stat[0].scale == FE_SCALE_DECIBEL) { + uitmp = c->strength.stat[0].svalue / 1000 + 256; + uitmp = clamp(uitmp, 181U, 236U); /* -75dBm - -20dBm */ + /* scale value to 0x0000-0xffff */ + *strength = (uitmp-181) * 0xffff / (236-181); } else { - dev->meas_count[i] = uitmp; + *strength = 0; } + return 0; +} - cmd.args[0] = CMD_BER_UPDATE_COUNTERS; - cmd.args[1] = 0; - cmd.args[2] = i; - cmd.len = 3; - ret = tda10071_cmd_execute(dev, &cmd); - if (ret) - goto error; - - ret = regmap_bulk_read(dev->regmap, cmd.len, buf, len); - if (ret) - goto error; - - if (dev->delivery_system == SYS_DVBS) { - *ber = (buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | buf[3]; - dev->ucb += (buf[4] << 8) | buf[5]; - } else { - *ber = (buf[0] << 8) | buf[1]; - } - dev->ber = *ber; +static int tda10071_read_ber(struct dvb_frontend *fe, u32 *ber) +{ + struct tda10071_dev *dev = fe->demodulator_priv; - return ret; -error: - dev_dbg(&client->dev, "failed=%d\n", ret); - return ret; + *ber = dev->dvbv3_ber; + return 0; } static int tda10071_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks) { - struct tda10071_dev *dev = fe->demodulator_priv; - struct i2c_client *client = dev->client; - int ret = 0; + struct dtv_frontend_properties *c = &fe->dtv_property_cache; - if (!dev->warm || !(dev->fe_status & FE_HAS_LOCK)) { + if (c->block_error.stat[0].scale == FE_SCALE_COUNTER) + *ucblocks = c->block_error.stat[0].uvalue; + else *ucblocks = 0; - goto error; - } - - /* UCB is updated when BER is read. Assume BER is read anyway. */ - - *ucblocks = dev->ucb; - - return ret; -error: - dev_dbg(&client->dev, "failed=%d\n", ret); - return ret; + return 0; } static int tda10071_set_frontend(struct dvb_frontend *fe) @@ -773,6 +766,7 @@ static int tda10071_init(struct dvb_frontend *fe) { struct tda10071_dev *dev = fe->demodulator_priv; struct i2c_client *client = dev->client; + struct dtv_frontend_properties *c = &fe->dtv_property_cache; struct tda10071_cmd cmd; int ret, i, len, remaining, fw_size; unsigned int uitmp; @@ -1038,6 +1032,16 @@ static int tda10071_init(struct dvb_frontend *fe) goto error; } + /* init stats here in order signal app which stats are supported */ + c->strength.len = 1; + c->strength.stat[0].scale = FE_SCALE_NOT_AVAILABLE; + c->cnr.len = 1; + c->cnr.stat[0].scale = FE_SCALE_NOT_AVAILABLE; + c->post_bit_error.len = 1; + c->post_bit_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE; + c->block_error.len = 1; + c->block_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE; + return ret; error_release_firmware: release_firmware(fw); diff --git a/drivers/media/dvb-frontends/tda10071_priv.h b/drivers/media/dvb-frontends/tda10071_priv.h index cf5b433..b9c3601 100644 --- a/drivers/media/dvb-frontends/tda10071_priv.h +++ b/drivers/media/dvb-frontends/tda10071_priv.h @@ -38,12 +38,13 @@ struct tda10071_dev { u8 pll_multiplier; u8 tuner_i2c_addr; - u8 meas_count[2]; - u32 ber; - u32 ucb; + u8 meas_count; + u32 dvbv3_ber; enum fe_status fe_status; enum fe_delivery_system delivery_system; bool warm; /* FW running */ + u64 post_bit_error; + u64 block_error; }; static struct tda10071_modcod {