From patchwork Fri Oct 13 06:11:57 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Yasunari.Takiguchi@sony.com X-Patchwork-Id: 10003505 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id 4127860216 for ; Fri, 13 Oct 2017 06:08:53 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 32EE128F8A for ; Fri, 13 Oct 2017 06:08:53 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 2764228FB5; Fri, 13 Oct 2017 06:08:53 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-6.9 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,RCVD_IN_DNSWL_HI autolearn=unavailable version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 7AE2928F8A for ; Fri, 13 Oct 2017 06:08:51 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753830AbdJMGIj (ORCPT ); Fri, 13 Oct 2017 02:08:39 -0400 Received: from mail-dm3nam03on0122.outbound.protection.outlook.com ([104.47.41.122]:45025 "EHLO NAM03-DM3-obe.outbound.protection.outlook.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1751373AbdJMGIh (ORCPT ); Fri, 13 Oct 2017 02:08:37 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=Sony.onmicrosoft.com; s=selector1-Sony-onmicrosoft-com; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version; bh=m2ky56S40Sj6/SjyiCw27w8yJcvTdBTSJqGLXRPY3es=; b=KMSjLkuGU2Xfgq0jYBQ4oHzUWPWFJrobmXmFSPMfzmdK4VIM6wobZ1787FkOd4l9ApylfLJp07Hsa9pXtPaHNuxTQmzCzsf/Bbu7/C5XM/uarioJwhSBAxhoLwnmJICnhNDF9EqohUTTPtHxIkuZVJCgNZGtbqcGAS9ESh61wYM= Received: from BY2PR13CA0017.namprd13.prod.outlook.com (10.162.223.27) by BLUPR13MB0451.namprd13.prod.outlook.com (10.163.219.29) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384_P256) id 15.20.77.5; Fri, 13 Oct 2017 06:08:34 +0000 Received: from BL2NAM02FT063.eop-nam02.prod.protection.outlook.com (2a01:111:f400:7e46::209) by BY2PR13CA0017.outlook.office365.com (2a01:111:e400:52d1::27) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384) id 15.20.156.2 via Frontend Transport; Fri, 13 Oct 2017 06:08:34 +0000 Authentication-Results: spf=pass (sender IP is 117.103.190.44) smtp.mailfrom=sony.com; vger.kernel.org; dkim=none (message not signed) header.d=none;vger.kernel.org; dmarc=bestguesspass action=none header.from=sony.com; Received-SPF: Pass (protection.outlook.com: domain of sony.com designates 117.103.190.44 as permitted sender) receiver=protection.outlook.com; client-ip=117.103.190.44; helo=jp.sony.com; Received: from jp.sony.com (117.103.190.44) by BL2NAM02FT063.mail.protection.outlook.com (10.152.77.121) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384_P384) id 15.20.77.10 via Frontend Transport; Fri, 13 Oct 2017 06:08:33 +0000 Received: from JPYOKXHT108.jp.sony.com (117.103.191.55) by JPYOKXEG104.jp.sony.com (117.103.190.44) with Microsoft SMTP Server (TLS) id 14.3.361.1; Fri, 13 Oct 2017 06:08:23 +0000 Received: from localhost.localdomain (43.25.41.74) by JPYOKXHT108.jp.sony.com (117.103.191.55) with Microsoft SMTP Server (TLS) id 14.3.361.1; Fri, 13 Oct 2017 06:08:23 +0000 From: To: , , CC: , , Yasunari Takiguchi , Masayuki Yamamoto , Hideki Nozawa , "Kota Yonezawa" , Toshihiko Matsumoto , Satoshi Watanabe Subject: [PATCH v4 09/12] [media] cxd2880: Add DVB-T monitor functions Date: Fri, 13 Oct 2017 15:11:57 +0900 Message-ID: <20171013061157.21784-1-Yasunari.Takiguchi@sony.com> X-Mailer: git-send-email 2.13.0 In-Reply-To: <20171013054635.20946-1-Yasunari.Takiguchi@sony.com> References: <20171013054635.20946-1-Yasunari.Takiguchi@sony.com> MIME-Version: 1.0 X-Originating-IP: [43.25.41.74] X-EOPAttributedMessage: 0 X-MS-Office365-Filtering-HT: Tenant X-Forefront-Antispam-Report: CIP:117.103.190.44; IPV:NLI; CTRY:JP; EFV:NLI; SFV:NSPM; SFS:(10019020)(6009001)(376002)(346002)(39860400002)(2980300002)(438002)(189002)(199003)(16526018)(316002)(106002)(50226002)(5003940100001)(47776003)(2201001)(49486002)(106466001)(356003)(189998001)(3846002)(6116002)(8676002)(16586007)(8936002)(36756003)(110136005)(54906003)(2876002)(50986999)(7636002)(86152003)(53946003)(6306002)(7736002)(305945005)(1076002)(2950100002)(66066001)(246002)(86362001)(575784001)(5660300001)(76176999)(6666003)(478600001)(4326008)(2906002)(39060400002)(48376002)(72206003)(50466002)(107886003)(461764006)(2004002); DIR:OUT; SFP:1102; SCL:1; SRVR:BLUPR13MB0451; H:jp.sony.com; FPR:; SPF:Pass; PTR:jpyokxeg104.jp.sony.com; MX:1; A:1; LANG:en; X-Microsoft-Exchange-Diagnostics: 1; BL2NAM02FT063; 1:Ugb5ZInLUTQ2T5nhZF3xDKFxRXz2MaYk6wbthEIWNKri02KL3CC13dTviF7KW5mXLpBgYJ139xXmKdXrzAw2VqYC5//VNYm/+JjHmF7YlJwOn4mc7NiqXo+cd81LQVz1 X-MS-PublicTrafficType: Email X-MS-Office365-Filtering-Correlation-Id: 26dbe730-1a3b-4627-5d03-08d51200d5e2 X-Microsoft-Antispam: UriScan:; BCL:0; PCL:0; RULEID:(22001)(2017030254152)(8251501002)(2017052603199)(201703131423075)(201703031133081)(201702281549075); SRVR:BLUPR13MB0451; X-Microsoft-Exchange-Diagnostics: 1; BLUPR13MB0451; 3:ZmlKkLmpC02dFFNnjwxv4YLdEGiGe4NvgAiPeqauIfGvbt+Py7J2i6yGr3MLCqXI813ePNECK6FI+nkG6KZLejYv2ipJAFya8tFAoWo+CaAqJgoakEufNtQDNaTbAbg8mIuAnyv4ZXw37y6LzQ+/9iDKaSCTnjclxSUElfMwDNab6uUgPajdr0RoiqsaC3NO2Husfqs51eemkDczhbpUxe1GavD5x0uVKaiqAC+uqQezgaZVHWPmQMgwxAg6oePIGaahzFAqnB0eDfA5PCNIWjVQyGxrLFLdTPklwMWjajIhLR8J7QMR9DK9KyRyLa+EXv3/LCGEkGErnnSJbb5cKgbE5XbW7+UEu4YV6vTXBlE=; 25:6eBZOCxduzBf+zQSez40H0Yvj8m8re71LwVRgk7EhLWJ8d2MyEd+9tL0uSfKXZEQXZDNLL8zCryZDHIr1XHkJLlxE0ut/5uW1IfuxEbO12gyVVwgQl2Y5hI76bkI6ZWzO9hiVlA8GkD74CEZIo84lvjAhe+VnBTvMm0iYOSm5dzT3HiKD+WguVYnLPIDlIzrbu6ERR0RTYUMspWngE9IfrbXhKWx/CgTKueF/TSYWFyszqje1rVOSUt0yIaNAFvz6Rqqixg+n1fsdP2lQPUL7l24/oDDOMT0OSX7YAil+NYcgQ7s4icpT5tOAorSUhk5EO5Y02sAqshBdSYUPffg5Q== X-MS-TrafficTypeDiagnostic: BLUPR13MB0451: X-Microsoft-Exchange-Diagnostics: 1; BLUPR13MB0451; 31:m4tNVvHGzp18MrvoK9IRlfccg9R+EvXynKMuAZWeAKRlkaLIvnvi72SDdQWwYbDmRe6/RuMbtZ47kZ3A6H/unhaFzE5FQjn7ZKEdvxSIMfoY7ZYGHvcyquWe3m4NsXcJMpTVLXqBnklZB0TYAJyUynj1cGuUSay3T4fnRPQICdsly9r9A8TyKHrHLvUN1NMVaGlQiilwcHMkYifRzyGhq88LHT4+971ccrqwBi93BqA=; 20:C+zhploL56jevZagEfVXd5XHWv7iYdc8mG6NUokOEMe8mjvj7n6wO0VXKZs9BTPWDxgcrVF0FqoVHMUxOj+Pi7+1q8O3vPMuhBD4BfGBcZtIX/YR64gZ116mpOWsj4y8tcl4EAQOKWr+u0ECcKmYnNddQ0bbtYt4pDToyVAGb8Oph0hUbhQWYSgHddBwcUbB037/NJIOisgViPqNuG45iwrR73omGwshzqQDonVdkFQ8Ba4b0KPwAATZdovO02ySuECsggnCk8pj7j3GpQORMpqPNf0F/N+rkNP5eSSxKZMwFLepyKWzrDNyoH23D7m9TSVVmiIQCFaz/+2IbClSjvT2o5gBr7QoA2BVmeZLr4uHhzJKdwfwlTCZNm4z5F+EH9719pesa4TuGrb7JQUb7X892pODbvkAxun9U6XG8N0mQgkt0DIRpRvn4SQcaMTbAqjgFRQYyYvR07HD2LzVFNUMpuzBK0tfsaf7gpzHm/+RMGui/XIMScFiTvy1LCtB X-Exchange-Antispam-Report-Test: UriScan:(250305191791016)(182409339516656)(22074186197030); X-Microsoft-Antispam-PRVS: X-Exchange-Antispam-Report-CFA-Test: BCL:0; PCL:0; RULEID:(100000700101)(100105000095)(100000701101)(100105300095)(100000702101)(100105100095)(6040450)(2401047)(8121501046)(5005006)(3002001)(100000703101)(100105400095)(93006095)(93004095)(10201501046)(6055026)(6041248)(20161123558100)(20161123560025)(20161123564025)(20161123562025)(20161123555025)(201703131423075)(201702281528075)(201703061421075)(201703061406153)(6072148)(201708071742011)(100000704101)(100105200095)(100000705101)(100105500095); SRVR:BLUPR13MB0451; BCL:0; PCL:0; RULEID:(100000800101)(100110000095)(100000801101)(100110300095)(100000802101)(100110100095)(100000803101)(100110400095)(100000804101)(100110200095)(100000805101)(100110500095); SRVR:BLUPR13MB0451; X-Microsoft-Exchange-Diagnostics: 1; BLUPR13MB0451; 4:FTAxWi8hoXb0neVAITrOak/s4XHvnEgnxNL1Jy7u+cmyG/PbvPmS33uSaPwIuhsEKlJXPdiewLJUrKxNmvlBOyVlfKZvVQWknVthDsEfCaWj6QS9BDPc/vA6vAPHmGY+jzXR7dMrW1an2F2MLL8jLe0tX0fzJ/SKhzmrqhyy+o1BvJ5MRrnEqahCs5dLYTJ5Eu3yeaEaYOa82VEHAji3CT0uGzxqBT419DjbwrYln+mu52HusiM4zas9azQpxfhK6OKUSQzgVLKOjHQq9VLbYNVFZpo0ZKESRVKzdZx6rUZHbvBuExmLgEIhIu2X2yg1SUHrgn+7wzDBpwo6znZyVSGNbtHMealKuz4RWkfq7GTSd8Hq+5UUEJ7t2BKcRfUP X-Forefront-PRVS: 04599F3534 X-Microsoft-Exchange-Diagnostics: =?us-ascii?Q?1; BLUPR13MB0451; 23:Q8iWkOs/zU/SkM4QhG3Ed6E8JI4kehtLOKJCM3wxl?= =?us-ascii?Q?/d0Q/gkjNLlULRKLR6H0/DVrYk72LCjAixniIZs/qQv3mmXDJ7oc6TrxB5xZ?= =?us-ascii?Q?sqqfXIbcluLvceTch38XRYDC8M4WRnJOL5PBvqIFGptCQ7/WSGIdcz1rT9Bp?= =?us-ascii?Q?jzYmQKo0ygQRjwdK4Mxq6V4fSFGKtrlVWfj/vFc5MJI7KsffxSrnAwAFBUrH?= =?us-ascii?Q?hUq09CSGBh7vNrn7GHrHsO1dAozq28gvHjSCX3F7hUn+Fvgq/rCfdOH9fjcJ?= =?us-ascii?Q?BsPQ4dN5lp+7OwmVA57E/u/ZKfqYu/1c3AwQEmapfMBpBXY3nAxxl4ylgjGM?= =?us-ascii?Q?Q4WokuCDmF+SWyA6SmygA+V2mVzwUfxLlmlsXA2DH/R31s25nEWZxH+U98WK?= =?us-ascii?Q?zA7mQ6QkgHVg0IOeADeGLMu3RDpEkCWtJhhx9dPHPkY7T3PdnJ7SK2YPSn/T?= =?us-ascii?Q?G17zf157wEi0hNOjAWxMpRyc6KMBLua7jwn5mA6rydW+XkHmFhNVY7JtAFHl?= =?us-ascii?Q?UuB04od4tshUZfY6kglSJcHZsjmWoq95khCEiEfH+ogkVStIwD0pesImn0Tb?= =?us-ascii?Q?vDnsT7LGeet21GF3yQWo1lrxOFUkXa8d16NFcAe/TV8o0Em4GbCCWfZs9Klq?= =?us-ascii?Q?QwgR6inm9DhxiJRAq1QmbV88/ElK9O4NPV1LV6HMJvblE1fI+S4kHHOGxLhb?= =?us-ascii?Q?nxJI5hjwwA4d2RowphuXJgDPum+U8+yoWS2OeEUYxirjgTsgEyRLYAtz45IW?= =?us-ascii?Q?BXbk/RxQZpRlhIyLE3pdyLpRL3l/x6FyiCQHdjiPzQ7icrwyES9b0M/2HqUD?= =?us-ascii?Q?ZTlSwOXHuODiyXnlYI1gx1wu7omOp7EtxpT7dVkj1IAXVnWahSjITK0y5mvP?= =?us-ascii?Q?BA73fbPfpjyIwHyJSOy7yvCoziJyh4999mPV3tUF+cQWmwfDSTcA4dlXcP0H?= =?us-ascii?Q?uWAnIdG/N9QeZ+zcCVLMXUkzSF9070hsLMhRblYWBLiy8a6C9cYqH5hreQpa?= =?us-ascii?Q?405s6p11PvZba+zb3NiAsyX4Nb9Ep6qY0Ei41uWqWtgyk9aBfAehjoT5ngi2?= =?us-ascii?Q?j3fXjsDXqfyhfMk6uiuve3i7nafsYVVKoIkYTyMwGxPR/U31wQZxZh2IwoDA?= =?us-ascii?Q?l7z0e6tTtm2pmXGN7euJyxFJusJ4VWiZrWvU5RwzfE9XgEjivPWb41rQjsIR?= =?us-ascii?Q?ygaA3jjCcpZ1Yzd6Y48xhwSuRxncgTbut9MnJJk4ZF1k5lvT833//9adH5er?= =?us-ascii?Q?CkOzVTa1dVsPL4iY50=3D?= X-Microsoft-Exchange-Diagnostics: 1; BLUPR13MB0451; 6:rcXFTLxsu46dqlCybSvudQjfj4ovvwnWuBT0oxaiRMoEtn4aY7mI6UfegzcqPiwnaZuWHisAYI5etE8AbI7JMhV5pDmCc0U54A5l111me4N8fTDz8WZHA2oFsvTQt9ApJtM000yWFWtQPOtosQiZ1hhp9sTa6Tbrqynic2rW9oUXPy/hGclZjuM6uVkzw1zKXxr2ZaeId0QlcFXlYQKkGfoYK9Thg64OvnBROyMQGUzGvQPHAyFu/N3/cVF0UlezrqcA0mFhdTxSlfA4nmFrrAZsvWOwWVEZsy0BrLKVlNgqGix0ch3n6m8E75lY4q0xbC57b/NMlXs0e5hxdLvlsQ==; 5:PVliowoAKytSn6prvEClyIcNG1nIEBAR7Y4vcTxa9KAo0wifEtJ/jnV0gIFIeEsx1tk2hWvoIJyeYHHqodgd767tYMjI46tv4Wh6FxEwPny3gqk1bulHM5ExtAN3jYgl26WoAmWwoFlGX+m47v5i9A==; 24:iizeKcng62UUWY17By1PX3vrVW9xB9m18sc6FHyj0YFBbFe7+p3L94vrBT2+HcvNfg61MAhx2fgWdQTSUoO5/aQct8bhBY6i6bR0F4ItRsw=; 7:/vEjavzO5Nt+QCrU7NzwbNCbOSm47qgFG/VCBlUvshCDsJm4j0B747hLqd2+kugzWUyQH/o31oMf74GcSLSOFAEeCfcnizZ/M1kpT2JB89MEvYMC3T/Ud6gb+iz6+3X2xZ9r8W4okoWc1kp9LqzIMQvW7Pw8rgFZD/eMxlBv/wql9+hyXNdfWUAu4LRp3jiSOzLk4W5gHEMhxXZY0RrL80ki1bJQSJxKmW8hQ0qEErM= SpamDiagnosticOutput: 1:99 SpamDiagnosticMetadata: NSPM X-OriginatorOrg: sony.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 13 Oct 2017 06:08:33.5631 (UTC) X-MS-Exchange-CrossTenant-Id: 66c65d8a-9158-4521-a2d8-664963db48e4 X-MS-Exchange-CrossTenant-OriginalAttributedTenantConnectingIp: TenantId=66c65d8a-9158-4521-a2d8-664963db48e4; Ip=[117.103.190.44]; Helo=[jp.sony.com] X-MS-Exchange-CrossTenant-FromEntityHeader: HybridOnPrem X-MS-Exchange-Transport-CrossTenantHeadersStamped: BLUPR13MB0451 Sender: linux-media-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-media@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP From: Yasunari Takiguchi Provide monitor functions (DVB-T) for the Sony CXD2880 DVB-T2/T tuner + demodulator driver. Signed-off-by: Yasunari Takiguchi Signed-off-by: Masayuki Yamamoto Signed-off-by: Hideki Nozawa Signed-off-by: Kota Yonezawa Signed-off-by: Toshihiko Matsumoto Signed-off-by: Satoshi Watanabe --- [Change list] Changes in V4 #drivers/media/dvb-frontends/cxd2880/cxd2880_integ_dvbt.c -cxd2880_integ_dvbt.c file was removed from V4. #drivers/media/dvb-frontends/cxd2880/cxd2880_integ_dvbt.h -cxd2880_integ_dvbt.h file was removed from V4. drivers/media/dvb-frontends/cxd2880/cxd2880_tnrdmd_dvbt_mon.c -removed unnecessary initialization at variable declaration -removed unnecessary brace {} -changed position of static const (to top part of the file) Changes in V3 drivers/media/dvb-frontends/cxd2880/cxd2880_integ_dvbt.c -changed CXD2880_SLEEP to usleep_range -chnaged cxd2880_atomic_set to atomic_set -modified return code -modified coding style of if() drivers/media/dvb-frontends/cxd2880/cxd2880_integ_dvbt.h -modified return code drivers/media/dvb-frontends/cxd2880/cxd2880_tnrdmd_dvbt_mon.c -removed unnecessary cast -changed cxd2880_math_log to intlog10 -changed hexadecimal code to lower case. drivers/media/dvb-frontends/cxd2880/cxd2880_tnrdmd_dvbt_mon.h -modified return code .../cxd2880/cxd2880_tnrdmd_dvbt_mon.c | 1201 ++++++++++++++++++++ .../cxd2880/cxd2880_tnrdmd_dvbt_mon.h | 106 ++ 2 files changed, 1307 insertions(+) create mode 100644 drivers/media/dvb-frontends/cxd2880/cxd2880_tnrdmd_dvbt_mon.c create mode 100644 drivers/media/dvb-frontends/cxd2880/cxd2880_tnrdmd_dvbt_mon.h diff --git a/drivers/media/dvb-frontends/cxd2880/cxd2880_tnrdmd_dvbt_mon.c b/drivers/media/dvb-frontends/cxd2880/cxd2880_tnrdmd_dvbt_mon.c new file mode 100644 index 000000000000..b00f1ac088bb --- /dev/null +++ b/drivers/media/dvb-frontends/cxd2880/cxd2880_tnrdmd_dvbt_mon.c @@ -0,0 +1,1201 @@ +/* + * cxd2880_tnrdmd_dvbt_mon.c + * Sony CXD2880 DVB-T2/T tuner + demodulator driver + * DVB-T monitor functions + * + * Copyright (C) 2016, 2017 Sony Semiconductor Solutions Corporation + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; version 2 of the License. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, see . + */ + +#include "cxd2880_tnrdmd_mon.h" +#include "cxd2880_tnrdmd_dvbt.h" +#include "cxd2880_tnrdmd_dvbt_mon.h" + +#include "dvb_math.h" + +static const int nordig_non_hdvbt_db_1000[3][5] = { + {5100, 6900, 7900, 8900, 9700}, + {10800, 13100, 14600, 15600, 16000}, + {16500, 18700, 20200, 21600, 22500} +}; + +static const int nordig_hier_hp_dvbt_db_1000[3][2][5] = { + { + {9100, 12000, 13600, 15000, 16600}, + {10900, 14100, 15700, 19400, 20600} + }, { + {6800, 9100, 10400, 11900, 12700}, + {8500, 11000, 12800, 15000, 16000} + }, { + {5800, 7900, 9100, 10300, 12100}, + {8000, 9300, 11600, 13000, 12900} + } +}; + +static const int nordig_hier_lp_dvbt_db_1000[3][2][5] = { + { + {12500, 14300, 15300, 16300, 16900}, + {16700, 19100, 20900, 22500, 23700} + }, { + {15000, 17200, 18400, 19100, 20100}, + {18500, 21200, 23600, 24700, 25900} + }, { + {19500, 21400, 22500, 23700, 24700}, + {21900, 24200, 25600, 26900, 27800} + } +}; + +static const int ref_dbm_1000[3][5] = { + {-93000, -91000, -90000, -89000, -88000}, + {-87000, -85000, -84000, -83000, -82000}, + {-82000, -80000, -78000, -77000, -76000}, +}; + +static int is_tps_locked(struct cxd2880_tnrdmd *tnr_dmd); + +int cxd2880_tnrdmd_dvbt_mon_sync_stat(struct cxd2880_tnrdmd + *tnr_dmd, u8 *sync_stat, + u8 *ts_lock_stat, + u8 *unlock_detected) +{ + u8 rdata = 0x00; + int ret; + + if ((!tnr_dmd) || (!sync_stat) || (!ts_lock_stat) || (!unlock_detected)) + return -EINVAL; + + if (tnr_dmd->state != CXD2880_TNRDMD_STATE_ACTIVE) + return -EPERM; + if (tnr_dmd->sys != CXD2880_DTV_SYS_DVBT) + return -EPERM; + + ret = tnr_dmd->io->write_reg(tnr_dmd->io, + CXD2880_IO_TGT_DMD, + 0x00, 0x0d); + if (ret) + return ret; + + ret = tnr_dmd->io->read_regs(tnr_dmd->io, + CXD2880_IO_TGT_DMD, + 0x10, &rdata, 1); + if (ret) + return ret; + + *unlock_detected = (rdata & 0x10) ? 1 : 0; + *sync_stat = rdata & 0x07; + *ts_lock_stat = (rdata & 0x20) ? 1 : 0; + + if (*sync_stat == 0x07) + return -EBUSY; + + return ret; +} + +int cxd2880_tnrdmd_dvbt_mon_sync_stat_sub(struct cxd2880_tnrdmd + *tnr_dmd, u8 *sync_stat, + u8 *unlock_detected) +{ + u8 ts_lock_stat = 0; + int ret; + + if ((!tnr_dmd) || (!sync_stat) || (!unlock_detected)) + return -EINVAL; + + if (tnr_dmd->diver_mode != CXD2880_TNRDMD_DIVERMODE_MAIN) + return -EINVAL; + + ret = + cxd2880_tnrdmd_dvbt_mon_sync_stat(tnr_dmd->diver_sub, sync_stat, + &ts_lock_stat, unlock_detected); + + return ret; +} + +int cxd2880_tnrdmd_dvbt_mon_mode_guard(struct cxd2880_tnrdmd + *tnr_dmd, + enum cxd2880_dvbt_mode + *mode, + enum cxd2880_dvbt_guard + *guard) +{ + u8 rdata = 0x00; + int ret; + + if ((!tnr_dmd) || (!mode) || (!guard)) + return -EINVAL; + + if (tnr_dmd->state != CXD2880_TNRDMD_STATE_ACTIVE) + return -EPERM; + + if (tnr_dmd->sys != CXD2880_DTV_SYS_DVBT) + return -EPERM; + + ret = slvt_freeze_reg(tnr_dmd); + if (ret) + return ret; + + ret = is_tps_locked(tnr_dmd); + if (ret) { + slvt_unfreeze_reg(tnr_dmd); + + if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_MAIN) + ret = + cxd2880_tnrdmd_dvbt_mon_mode_guard( + tnr_dmd->diver_sub, mode, guard); + + return ret; + } + + ret = tnr_dmd->io->write_reg(tnr_dmd->io, + CXD2880_IO_TGT_DMD, + 0x00, 0x0d); + if (ret) { + slvt_unfreeze_reg(tnr_dmd); + return ret; + } + + ret = tnr_dmd->io->read_regs(tnr_dmd->io, + CXD2880_IO_TGT_DMD, + 0x1b, &rdata, 1); + if (ret) { + slvt_unfreeze_reg(tnr_dmd); + return ret; + } + + slvt_unfreeze_reg(tnr_dmd); + + *mode = (enum cxd2880_dvbt_mode)((rdata >> 2) & 0x03); + *guard = (enum cxd2880_dvbt_guard)(rdata & 0x03); + + return ret; +} + +int cxd2880_tnrdmd_dvbt_mon_carrier_offset(struct cxd2880_tnrdmd + *tnr_dmd, int *offset) +{ + u8 rdata[4]; + u32 ctl_val = 0; + int ret; + + if ((!tnr_dmd) || (!offset)) + return -EINVAL; + + if (tnr_dmd->state != CXD2880_TNRDMD_STATE_ACTIVE) + return -EPERM; + + if (tnr_dmd->sys != CXD2880_DTV_SYS_DVBT) + return -EPERM; + + ret = slvt_freeze_reg(tnr_dmd); + if (ret) + return ret; + + ret = is_tps_locked(tnr_dmd); + if (ret) { + slvt_unfreeze_reg(tnr_dmd); + return ret; + } + + ret = tnr_dmd->io->write_reg(tnr_dmd->io, + CXD2880_IO_TGT_DMD, + 0x00, 0x0d); + if (ret) { + slvt_unfreeze_reg(tnr_dmd); + return ret; + } + + ret = tnr_dmd->io->read_regs(tnr_dmd->io, + CXD2880_IO_TGT_DMD, + 0x1d, rdata, 4); + if (ret) { + slvt_unfreeze_reg(tnr_dmd); + return ret; + } + + slvt_unfreeze_reg(tnr_dmd); + + ctl_val = + ((rdata[0] & 0x1f) << 24) | (rdata[1] << 16) | (rdata[2] << 8) | + (rdata[3]); + *offset = cxd2880_convert2s_complement(ctl_val, 29); + *offset = -1 * ((*offset) * tnr_dmd->bandwidth / 235); + + return ret; +} + +int cxd2880_tnrdmd_dvbt_mon_carrier_offset_sub(struct + cxd2880_tnrdmd + *tnr_dmd, + int *offset) +{ + int ret; + + if ((!tnr_dmd) || (!offset)) + return -EINVAL; + + if (tnr_dmd->diver_mode != CXD2880_TNRDMD_DIVERMODE_MAIN) + return -EINVAL; + + ret = + cxd2880_tnrdmd_dvbt_mon_carrier_offset(tnr_dmd->diver_sub, offset); + + return ret; +} + +int cxd2880_tnrdmd_dvbt_mon_pre_viterbiber(struct cxd2880_tnrdmd + *tnr_dmd, u32 *ber) +{ + u8 rdata[2]; + u32 bit_error = 0; + u32 period = 0; + u32 div = 0; + u32 Q = 0; + u32 R = 0; + int ret; + + if ((!tnr_dmd) || (!ber)) + return -EINVAL; + + if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_SUB) + return -EINVAL; + + if (tnr_dmd->state != CXD2880_TNRDMD_STATE_ACTIVE) + return -EPERM; + + if (tnr_dmd->sys != CXD2880_DTV_SYS_DVBT) + return -EPERM; + + ret = slvt_freeze_reg(tnr_dmd); + if (ret) + return ret; + + ret = tnr_dmd->io->write_reg(tnr_dmd->io, + CXD2880_IO_TGT_DMD, + 0x00, 0x10); + if (ret) { + slvt_unfreeze_reg(tnr_dmd); + return ret; + } + + ret = tnr_dmd->io->read_regs(tnr_dmd->io, + CXD2880_IO_TGT_DMD, + 0x39, rdata, 1); + if (ret) { + slvt_unfreeze_reg(tnr_dmd); + return ret; + } + + if ((rdata[0] & 0x01) == 0) { + slvt_unfreeze_reg(tnr_dmd); + return -EBUSY; + } + + ret = tnr_dmd->io->read_regs(tnr_dmd->io, + CXD2880_IO_TGT_DMD, + 0x22, rdata, 2); + if (ret) { + slvt_unfreeze_reg(tnr_dmd); + return ret; + } + + bit_error = (rdata[0] << 8) | rdata[1]; + + ret = tnr_dmd->io->read_regs(tnr_dmd->io, + CXD2880_IO_TGT_DMD, + 0x6f, rdata, 1); + if (ret) { + slvt_unfreeze_reg(tnr_dmd); + return ret; + } + + slvt_unfreeze_reg(tnr_dmd); + + period = ((rdata[0] & 0x07) == 0) ? 256 : (0x1000 << (rdata[0] & 0x07)); + + if ((period == 0) || (bit_error > period)) + return -EBUSY; + + div = period / 128; + + Q = (bit_error * 3125) / div; + R = (bit_error * 3125) % div; + + R *= 25; + Q = Q * 25 + R / div; + R = R % div; + + if (div / 2 <= R) + *ber = Q + 1; + else + *ber = Q; + + return ret; +} + +int cxd2880_tnrdmd_dvbt_mon_pre_rsber(struct cxd2880_tnrdmd + *tnr_dmd, u32 *ber) +{ + u8 rdata[3]; + u32 bit_error = 0; + u32 period_exp = 0; + u32 div = 0; + u32 Q = 0; + u32 R = 0; + int ret; + + if ((!tnr_dmd) || (!ber)) + return -EINVAL; + + if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_SUB) + return -EINVAL; + + if (tnr_dmd->state != CXD2880_TNRDMD_STATE_ACTIVE) + return -EPERM; + + if (tnr_dmd->sys != CXD2880_DTV_SYS_DVBT) + return -EPERM; + + ret = tnr_dmd->io->write_reg(tnr_dmd->io, + CXD2880_IO_TGT_DMD, + 0x00, 0x0d); + if (ret) + return ret; + + ret = tnr_dmd->io->read_regs(tnr_dmd->io, + CXD2880_IO_TGT_DMD, + 0x15, rdata, 3); + if (ret) + return ret; + + if ((rdata[0] & 0x40) == 0) + return -EBUSY; + + bit_error = ((rdata[0] & 0x3f) << 16) | (rdata[1] << 8) | rdata[2]; + + ret = tnr_dmd->io->write_reg(tnr_dmd->io, + CXD2880_IO_TGT_DMD, + 0x00, 0x10); + if (ret) + return ret; + + ret = tnr_dmd->io->read_regs(tnr_dmd->io, + CXD2880_IO_TGT_DMD, + 0x60, rdata, 1); + if (ret) + return ret; + + period_exp = (rdata[0] & 0x1f); + + if ((period_exp <= 11) && (bit_error > (1U << period_exp) * 204 * 8)) + return -EBUSY; + + if (period_exp <= 8) + div = (1U << period_exp) * 51; + else + div = (1U << 8) * 51; + + Q = (bit_error * 250) / div; + R = (bit_error * 250) % div; + + R *= 1250; + Q = Q * 1250 + R / div; + R = R % div; + + if (period_exp > 8) { + *ber = + (Q + (1 << (period_exp - 9))) >> (period_exp - 8); + } else { + if (div / 2 <= R) + *ber = Q + 1; + else + *ber = Q; + } + + return ret; +} + +int cxd2880_tnrdmd_dvbt_mon_tps_info(struct cxd2880_tnrdmd + *tnr_dmd, + struct cxd2880_dvbt_tpsinfo + *info) +{ + u8 rdata[7]; + u8 cell_id_ok = 0; + int ret; + + if ((!tnr_dmd) || (!info)) + return -EINVAL; + + if (tnr_dmd->state != CXD2880_TNRDMD_STATE_ACTIVE) + return -EPERM; + + if (tnr_dmd->sys != CXD2880_DTV_SYS_DVBT) + return -EPERM; + + ret = slvt_freeze_reg(tnr_dmd); + if (ret) + return ret; + + ret = is_tps_locked(tnr_dmd); + if (ret) { + slvt_unfreeze_reg(tnr_dmd); + + if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_MAIN) + ret = + cxd2880_tnrdmd_dvbt_mon_tps_info(tnr_dmd->diver_sub, + info); + + return ret; + } + + ret = tnr_dmd->io->write_reg(tnr_dmd->io, + CXD2880_IO_TGT_DMD, + 0x00, 0x0d); + if (ret) { + slvt_unfreeze_reg(tnr_dmd); + return ret; + } + + ret = tnr_dmd->io->read_regs(tnr_dmd->io, + CXD2880_IO_TGT_DMD, + 0x29, rdata, 7); + if (ret) { + slvt_unfreeze_reg(tnr_dmd); + return ret; + } + + ret = tnr_dmd->io->write_reg(tnr_dmd->io, + CXD2880_IO_TGT_DMD, + 0x00, 0x11); + if (ret) { + slvt_unfreeze_reg(tnr_dmd); + return ret; + } + + ret = tnr_dmd->io->read_regs(tnr_dmd->io, + CXD2880_IO_TGT_DMD, + 0xd5, &cell_id_ok, 1); + if (ret) { + slvt_unfreeze_reg(tnr_dmd); + return ret; + } + + slvt_unfreeze_reg(tnr_dmd); + + info->constellation = + (enum cxd2880_dvbt_constellation)((rdata[0] >> 6) & 0x03); + info->hierarchy = (enum cxd2880_dvbt_hierarchy)((rdata[0] >> 3) & 0x07); + info->rate_hp = (enum cxd2880_dvbt_coderate)(rdata[0] & 0x07); + info->rate_lp = (enum cxd2880_dvbt_coderate)((rdata[1] >> 5) & 0x07); + info->guard = (enum cxd2880_dvbt_guard)((rdata[1] >> 3) & 0x03); + info->mode = (enum cxd2880_dvbt_mode)((rdata[1] >> 1) & 0x03); + info->fnum = (rdata[2] >> 6) & 0x03; + info->length_indicator = rdata[2] & 0x3f; + info->cell_id = (rdata[3] << 8) | rdata[4]; + info->reserved_even = rdata[5] & 0x3f; + info->reserved_odd = rdata[6] & 0x3f; + + info->cell_id_ok = cell_id_ok & 0x01; + + return ret; +} + +int cxd2880_tnrdmd_dvbt_mon_packet_error_number(struct + cxd2880_tnrdmd + *tnr_dmd, + u32 *pen) +{ + u8 rdata[3]; + int ret; + + if ((!tnr_dmd) || (!pen)) + return -EINVAL; + + if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_SUB) + return -EINVAL; + + if (tnr_dmd->state != CXD2880_TNRDMD_STATE_ACTIVE) + return -EPERM; + + if (tnr_dmd->sys != CXD2880_DTV_SYS_DVBT) + return -EPERM; + + ret = tnr_dmd->io->write_reg(tnr_dmd->io, + CXD2880_IO_TGT_DMD, + 0x00, 0x0d); + if (ret) + return ret; + + ret = tnr_dmd->io->read_regs(tnr_dmd->io, + CXD2880_IO_TGT_DMD, + 0x26, rdata, 3); + if (ret) + return ret; + + if (!(rdata[0] & 0x01)) + return -EBUSY; + + *pen = (rdata[1] << 8) | rdata[2]; + + return ret; +} + +int cxd2880_tnrdmd_dvbt_mon_spectrum_sense(struct cxd2880_tnrdmd + *tnr_dmd, + enum + cxd2880_tnrdmd_spectrum_sense + *sense) +{ + u8 data = 0; + int ret; + + if ((!tnr_dmd) || (!sense)) + return -EINVAL; + + if (tnr_dmd->state != CXD2880_TNRDMD_STATE_ACTIVE) + return -EPERM; + + if (tnr_dmd->sys != CXD2880_DTV_SYS_DVBT) + return -EPERM; + + ret = slvt_freeze_reg(tnr_dmd); + if (ret) + return ret; + + ret = is_tps_locked(tnr_dmd); + if (ret) { + slvt_unfreeze_reg(tnr_dmd); + + if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_MAIN) + ret = cxd2880_tnrdmd_dvbt_mon_spectrum_sense( + tnr_dmd->diver_sub, sense); + + return ret; + } + + ret = tnr_dmd->io->write_reg(tnr_dmd->io, + CXD2880_IO_TGT_DMD, + 0x00, 0x0d); + if (ret) { + slvt_unfreeze_reg(tnr_dmd); + return ret; + } + + ret = tnr_dmd->io->read_regs(tnr_dmd->io, + CXD2880_IO_TGT_DMD, + 0x1c, &data, sizeof(data)); + if (ret) { + slvt_unfreeze_reg(tnr_dmd); + return ret; + } + + slvt_unfreeze_reg(tnr_dmd); + + *sense = + (data & 0x01) ? CXD2880_TNRDMD_SPECTRUM_INV : + CXD2880_TNRDMD_SPECTRUM_NORMAL; + + return ret; +} + +static int dvbt_read_snr_reg(struct cxd2880_tnrdmd *tnr_dmd, + u16 *reg_value) +{ + u8 rdata[2]; + int ret; + + if ((!tnr_dmd) || (!reg_value)) + return -EINVAL; + + ret = slvt_freeze_reg(tnr_dmd); + if (ret) + return ret; + + ret = is_tps_locked(tnr_dmd); + if (ret) { + slvt_unfreeze_reg(tnr_dmd); + return ret; + } + + ret = tnr_dmd->io->write_reg(tnr_dmd->io, + CXD2880_IO_TGT_DMD, + 0x00, 0x0d); + if (ret) { + slvt_unfreeze_reg(tnr_dmd); + return ret; + } + + ret = tnr_dmd->io->read_regs(tnr_dmd->io, + CXD2880_IO_TGT_DMD, + 0x13, rdata, 2); + if (ret) { + slvt_unfreeze_reg(tnr_dmd); + return ret; + } + + slvt_unfreeze_reg(tnr_dmd); + + *reg_value = (rdata[0] << 8) | rdata[1]; + + return ret; +} + +static int dvbt_calc_snr(struct cxd2880_tnrdmd *tnr_dmd, + u32 reg_value, int *snr) +{ + if ((!tnr_dmd) || (!snr)) + return -EINVAL; + + if (reg_value == 0) + return -EBUSY; + + if (reg_value > 4996) + reg_value = 4996; + + *snr = intlog10(reg_value) - intlog10(5350 - reg_value); + *snr = (*snr + 839) / 1678 + 28500; + + return 0; +} + +int cxd2880_tnrdmd_dvbt_mon_snr(struct cxd2880_tnrdmd *tnr_dmd, + int *snr) +{ + u16 reg_value = 0; + int ret; + + if ((!tnr_dmd) || (!snr)) + return -EINVAL; + + *snr = -1000 * 1000; + + if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_SUB) + return -EINVAL; + + if (tnr_dmd->state != CXD2880_TNRDMD_STATE_ACTIVE) + return -EPERM; + + if (tnr_dmd->sys != CXD2880_DTV_SYS_DVBT) + return -EPERM; + + if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_SINGLE) { + ret = dvbt_read_snr_reg(tnr_dmd, ®_value); + if (ret) + return ret; + + ret = dvbt_calc_snr(tnr_dmd, reg_value, snr); + if (ret) + return ret; + } else { + int snr_main = 0; + int snr_sub = 0; + + ret = + cxd2880_tnrdmd_dvbt_mon_snr_diver(tnr_dmd, snr, &snr_main, + &snr_sub); + if (ret) + return ret; + } + + return ret; +} + +int cxd2880_tnrdmd_dvbt_mon_snr_diver(struct cxd2880_tnrdmd + *tnr_dmd, int *snr, + int *snr_main, int *snr_sub) +{ + u16 reg_value = 0; + u32 reg_value_sum = 0; + int ret; + + if ((!tnr_dmd) || (!snr) || (!snr_main) || (!snr_sub)) + return -EINVAL; + + *snr = -1000 * 1000; + *snr_main = -1000 * 1000; + *snr_sub = -1000 * 1000; + + if (tnr_dmd->diver_mode != CXD2880_TNRDMD_DIVERMODE_MAIN) + return -EINVAL; + + if (tnr_dmd->state != CXD2880_TNRDMD_STATE_ACTIVE) + return -EPERM; + + if (tnr_dmd->sys != CXD2880_DTV_SYS_DVBT) + return -EPERM; + + ret = dvbt_read_snr_reg(tnr_dmd, ®_value); + if (!ret) { + ret = dvbt_calc_snr(tnr_dmd, reg_value, snr_main); + if (ret) + reg_value = 0; + } else if (ret == -EBUSY) { + reg_value = 0; + } else { + return ret; + } + + reg_value_sum += reg_value; + + ret = dvbt_read_snr_reg(tnr_dmd->diver_sub, ®_value); + if (!ret) { + ret = dvbt_calc_snr(tnr_dmd->diver_sub, reg_value, snr_sub); + if (ret) + reg_value = 0; + } else if (ret == -EBUSY) { + reg_value = 0; + } else { + return ret; + } + + reg_value_sum += reg_value; + + ret = dvbt_calc_snr(tnr_dmd, reg_value_sum, snr); + + return ret; +} + +int cxd2880_tnrdmd_dvbt_mon_sampling_offset(struct cxd2880_tnrdmd + *tnr_dmd, int *ppm) +{ + u8 ctl_val_reg[5]; + u8 nominal_rate_reg[5]; + u32 trl_ctl_val = 0; + u32 trcg_nominal_rate = 0; + int num; + int den; + s8 diff_upper = 0; + int ret; + + if ((!tnr_dmd) || (!ppm)) + return -EINVAL; + + if (tnr_dmd->state != CXD2880_TNRDMD_STATE_ACTIVE) + return -EPERM; + + if (tnr_dmd->sys != CXD2880_DTV_SYS_DVBT) + return -EPERM; + + ret = slvt_freeze_reg(tnr_dmd); + if (ret) + return ret; + + ret = is_tps_locked(tnr_dmd); + if (ret) { + slvt_unfreeze_reg(tnr_dmd); + return ret; + } + + ret = tnr_dmd->io->write_reg(tnr_dmd->io, + CXD2880_IO_TGT_DMD, + 0x00, 0x0d); + if (ret) { + slvt_unfreeze_reg(tnr_dmd); + return ret; + } + + ret = tnr_dmd->io->read_regs(tnr_dmd->io, + CXD2880_IO_TGT_DMD, + 0x21, ctl_val_reg, + sizeof(ctl_val_reg)); + if (ret) { + slvt_unfreeze_reg(tnr_dmd); + return ret; + } + + ret = tnr_dmd->io->write_reg(tnr_dmd->io, + CXD2880_IO_TGT_DMD, + 0x00, 0x04); + if (ret) { + slvt_unfreeze_reg(tnr_dmd); + return ret; + } + + ret = tnr_dmd->io->read_regs(tnr_dmd->io, + CXD2880_IO_TGT_DMD, + 0x60, nominal_rate_reg, + sizeof(nominal_rate_reg)); + if (ret) { + slvt_unfreeze_reg(tnr_dmd); + return ret; + } + + slvt_unfreeze_reg(tnr_dmd); + + diff_upper = + (ctl_val_reg[0] & 0x7f) - (nominal_rate_reg[0] & 0x7f); + + if ((diff_upper < -1) || (diff_upper > 1)) + return -EBUSY; + + trl_ctl_val = ctl_val_reg[1] << 24; + trl_ctl_val |= ctl_val_reg[2] << 16; + trl_ctl_val |= ctl_val_reg[3] << 8; + trl_ctl_val |= ctl_val_reg[4]; + + trcg_nominal_rate = nominal_rate_reg[1] << 24; + trcg_nominal_rate |= nominal_rate_reg[2] << 16; + trcg_nominal_rate |= nominal_rate_reg[3] << 8; + trcg_nominal_rate |= nominal_rate_reg[4]; + + trl_ctl_val >>= 1; + trcg_nominal_rate >>= 1; + + if (diff_upper == 1) + num = + (int)((trl_ctl_val + 0x80000000u) - + trcg_nominal_rate); + else if (diff_upper == -1) + num = + -(int)((trcg_nominal_rate + 0x80000000u) - + trl_ctl_val); + else + num = (int)(trl_ctl_val - trcg_nominal_rate); + + den = (nominal_rate_reg[0] & 0x7f) << 24; + den |= nominal_rate_reg[1] << 16; + den |= nominal_rate_reg[2] << 8; + den |= nominal_rate_reg[3]; + den = (den + (390625 / 2)) / 390625; + + den >>= 1; + + if (num >= 0) + *ppm = (num + (den / 2)) / den; + else + *ppm = (num - (den / 2)) / den; + + return ret; +} + +int cxd2880_tnrdmd_dvbt_mon_sampling_offset_sub(struct + cxd2880_tnrdmd + *tnr_dmd, int *ppm) +{ + int ret; + + if ((!tnr_dmd) || (!ppm)) + return -EINVAL; + + if (tnr_dmd->diver_mode != CXD2880_TNRDMD_DIVERMODE_MAIN) + return -EINVAL; + + ret = cxd2880_tnrdmd_dvbt_mon_sampling_offset(tnr_dmd->diver_sub, ppm); + + return ret; +} + +int cxd2880_tnrdmd_dvbt_mon_quality(struct cxd2880_tnrdmd *tnr_dmd, + u8 *quality) +{ + struct cxd2880_dvbt_tpsinfo tps; + enum cxd2880_dvbt_profile profile = CXD2880_DVBT_PROFILE_HP; + u32 ber = 0; + int sn = 0; + int sn_rel = 0; + int ber_sqi = 0; + int ret; + + if ((!tnr_dmd) || (!quality)) + return -EINVAL; + + if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_SUB) + return -EINVAL; + + if (tnr_dmd->state != CXD2880_TNRDMD_STATE_ACTIVE) + return -EPERM; + + if (tnr_dmd->sys != CXD2880_DTV_SYS_DVBT) + return -EPERM; + + ret = cxd2880_tnrdmd_dvbt_mon_tps_info(tnr_dmd, &tps); + if (ret) + return ret; + + if (tps.hierarchy != CXD2880_DVBT_HIERARCHY_NON) { + u8 data = 0; + + ret = tnr_dmd->io->write_reg(tnr_dmd->io, + CXD2880_IO_TGT_DMD, + 0x00, 0x10); + if (ret) + return ret; + + ret = tnr_dmd->io->read_regs(tnr_dmd->io, + CXD2880_IO_TGT_DMD, + 0x67, &data, 1); + if (ret) + return ret; + + profile = + ((data & 0x01) == + 0x01) ? CXD2880_DVBT_PROFILE_LP : CXD2880_DVBT_PROFILE_HP; + } + + ret = cxd2880_tnrdmd_dvbt_mon_pre_rsber(tnr_dmd, &ber); + if (ret) + return ret; + + ret = cxd2880_tnrdmd_dvbt_mon_snr(tnr_dmd, &sn); + if (ret) + return ret; + + if ((tps.constellation >= CXD2880_DVBT_CONSTELLATION_RESERVED_3) || + (tps.rate_hp >= CXD2880_DVBT_CODERATE_RESERVED_5) || + (tps.rate_lp >= CXD2880_DVBT_CODERATE_RESERVED_5) || + (tps.hierarchy > CXD2880_DVBT_HIERARCHY_4)) { + return -EPERM; + } + + if ((tps.hierarchy != CXD2880_DVBT_HIERARCHY_NON) && + (tps.constellation == CXD2880_DVBT_CONSTELLATION_QPSK)) + return -EPERM; + + if (tps.hierarchy == CXD2880_DVBT_HIERARCHY_NON) + sn_rel = + sn - + nordig_non_hdvbt_db_1000[tps.constellation][tps.rate_hp]; + else if (profile == CXD2880_DVBT_PROFILE_LP) + sn_rel = + sn - nordig_hier_lp_dvbt_db_1000[tps.hierarchy - 1] + [tps.constellation - 1] + [tps.rate_lp]; + else + sn_rel = + sn - nordig_hier_hp_dvbt_db_1000[tps.hierarchy - 1] + [tps.constellation - 1] + [tps.rate_hp]; + + if (ber > 10000) { + ber_sqi = 0; + } else if (ber > 1) { + ber_sqi = (int)((intlog10(ber) + 8388) / 16777); + ber_sqi = 20 * (7 * 1000 - (ber_sqi)) - 40 * 1000; + } else { + ber_sqi = 100 * 1000; + } + + if (sn_rel < -7 * 1000) { + *quality = 0; + } else if (sn_rel < 3 * 1000) { + int tmp_sqi = (((sn_rel - (3 * 1000)) / 10) + 1000); + *quality = + (u8)(((tmp_sqi * ber_sqi) + + (1000000 / 2)) / (1000000)) & 0xff; + } else { + *quality = (u8)((ber_sqi + 500) / 1000); + } + + if (*quality > 100) + *quality = 100; + + return ret; +} + +int cxd2880_tnrdmd_dvbt_mon_per(struct cxd2880_tnrdmd *tnr_dmd, + u32 *per) +{ + u32 packet_error = 0; + u32 period = 0; + u8 rdata[3]; + u32 div = 0; + u32 Q = 0; + u32 R = 0; + int ret; + + if ((!tnr_dmd) || (!per)) + return -EINVAL; + + if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_SUB) + return -EINVAL; + + if (tnr_dmd->state != CXD2880_TNRDMD_STATE_ACTIVE) + return -EPERM; + + if (tnr_dmd->sys != CXD2880_DTV_SYS_DVBT) + return -EPERM; + + ret = tnr_dmd->io->write_reg(tnr_dmd->io, + CXD2880_IO_TGT_DMD, + 0x00, 0x0d); + if (ret) + return ret; + + ret = tnr_dmd->io->read_regs(tnr_dmd->io, + CXD2880_IO_TGT_DMD, + 0x18, rdata, 3); + if (ret) + return ret; + + if ((rdata[0] & 0x01) == 0) + return -EBUSY; + + packet_error = (rdata[1] << 8) | rdata[2]; + + ret = tnr_dmd->io->write_reg(tnr_dmd->io, + CXD2880_IO_TGT_DMD, + 0x00, 0x10); + if (ret) + return ret; + + ret = tnr_dmd->io->read_regs(tnr_dmd->io, + CXD2880_IO_TGT_DMD, + 0x5c, rdata, 1); + if (ret) + return ret; + + period = 1U << (rdata[0] & 0x0f); + + if ((period == 0) || (packet_error > period)) + return -EBUSY; + + div = period; + + Q = (packet_error * 1000) / div; + R = (packet_error * 1000) % div; + + R *= 1000; + Q = Q * 1000 + R / div; + R = R % div; + + if ((div != 1) && (div / 2 <= R)) + *per = Q + 1; + else + *per = Q; + + return ret; +} + +static int dvbt_calc_ssi(struct cxd2880_tnrdmd *tnr_dmd, + int rf_lvl, u8 *ssi) +{ + struct cxd2880_dvbt_tpsinfo tps; + int prel; + int temp_ssi = 0; + int ret; + + if ((!tnr_dmd) || (!ssi)) + return -EINVAL; + + ret = cxd2880_tnrdmd_dvbt_mon_tps_info(tnr_dmd, &tps); + if (ret) + return ret; + + if ((tps.constellation >= CXD2880_DVBT_CONSTELLATION_RESERVED_3) || + (tps.rate_hp >= CXD2880_DVBT_CODERATE_RESERVED_5)) + return -EPERM; + + prel = rf_lvl - ref_dbm_1000[tps.constellation][tps.rate_hp]; + + if (prel < -15000) + temp_ssi = 0; + else if (prel < 0) + temp_ssi = ((2 * (prel + 15000)) + 1500) / 3000; + else if (prel < 20000) + temp_ssi = (((4 * prel) + 500) / 1000) + 10; + else if (prel < 35000) + temp_ssi = (((2 * (prel - 20000)) + 1500) / 3000) + 90; + else + temp_ssi = 100; + + *ssi = (temp_ssi > 100) ? 100 : (u8)temp_ssi; + + return ret; +} + +int cxd2880_tnrdmd_dvbt_mon_ssi(struct cxd2880_tnrdmd *tnr_dmd, + u8 *ssi) +{ + int rf_lvl = 0; + int ret; + + if ((!tnr_dmd) || (!ssi)) + return -EINVAL; + + if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_SUB) + return -EINVAL; + + if (tnr_dmd->state != CXD2880_TNRDMD_STATE_ACTIVE) + return -EPERM; + + if (tnr_dmd->sys != CXD2880_DTV_SYS_DVBT) + return -EPERM; + + ret = cxd2880_tnrdmd_mon_rf_lvl(tnr_dmd, &rf_lvl); + if (ret) + return ret; + + ret = dvbt_calc_ssi(tnr_dmd, rf_lvl, ssi); + if (ret) + return ret; + + return ret; +} + +int cxd2880_tnrdmd_dvbt_mon_ssi_sub(struct cxd2880_tnrdmd *tnr_dmd, + u8 *ssi) +{ + int rf_lvl = 0; + int ret; + + if ((!tnr_dmd) || (!ssi)) + return -EINVAL; + + if (tnr_dmd->diver_mode != CXD2880_TNRDMD_DIVERMODE_MAIN) + return -EINVAL; + + if (tnr_dmd->state != CXD2880_TNRDMD_STATE_ACTIVE) + return -EPERM; + + if (tnr_dmd->sys != CXD2880_DTV_SYS_DVBT) + return -EPERM; + + ret = cxd2880_tnrdmd_mon_rf_lvl(tnr_dmd->diver_sub, &rf_lvl); + if (ret) + return ret; + + ret = dvbt_calc_ssi(tnr_dmd, rf_lvl, ssi); + if (ret) + return ret; + + return ret; +} + +static int is_tps_locked(struct cxd2880_tnrdmd *tnr_dmd) +{ + u8 sync = 0; + u8 tslock = 0; + u8 early_unlock = 0; + int ret; + + if (!tnr_dmd) + return -EINVAL; + + ret = + cxd2880_tnrdmd_dvbt_mon_sync_stat(tnr_dmd, &sync, &tslock, + &early_unlock); + if (ret) + return ret; + + if (sync != 6) + return -EBUSY; + + return 0; +} diff --git a/drivers/media/dvb-frontends/cxd2880/cxd2880_tnrdmd_dvbt_mon.h b/drivers/media/dvb-frontends/cxd2880/cxd2880_tnrdmd_dvbt_mon.h new file mode 100644 index 000000000000..ce966270c69b --- /dev/null +++ b/drivers/media/dvb-frontends/cxd2880/cxd2880_tnrdmd_dvbt_mon.h @@ -0,0 +1,106 @@ +/* + * cxd2880_tnrdmd_dvbt_mon.h + * Sony CXD2880 DVB-T2/T tuner + demodulator driver + * DVB-T monitor interface + * + * Copyright (C) 2016, 2017 Sony Semiconductor Solutions Corporation + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; version 2 of the License. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, see . + */ + +#ifndef CXD2880_TNRDMD_DVBT_MON_H +#define CXD2880_TNRDMD_DVBT_MON_H + +#include "cxd2880_tnrdmd.h" +#include "cxd2880_dvbt.h" + +int cxd2880_tnrdmd_dvbt_mon_sync_stat(struct cxd2880_tnrdmd + *tnr_dmd, u8 *sync_stat, + u8 *ts_lock_stat, + u8 *unlock_detected); + +int cxd2880_tnrdmd_dvbt_mon_sync_stat_sub(struct cxd2880_tnrdmd + *tnr_dmd, u8 *sync_stat, + u8 *unlock_detected); + +int cxd2880_tnrdmd_dvbt_mon_mode_guard(struct cxd2880_tnrdmd + *tnr_dmd, + enum cxd2880_dvbt_mode + *mode, + enum cxd2880_dvbt_guard + *guard); + +int cxd2880_tnrdmd_dvbt_mon_carrier_offset(struct cxd2880_tnrdmd + *tnr_dmd, int *offset); + +int cxd2880_tnrdmd_dvbt_mon_carrier_offset_sub(struct + cxd2880_tnrdmd + *tnr_dmd, + int *offset); + +int cxd2880_tnrdmd_dvbt_mon_pre_viterbiber(struct cxd2880_tnrdmd + *tnr_dmd, u32 *ber); + +int cxd2880_tnrdmd_dvbt_mon_pre_rsber(struct cxd2880_tnrdmd + *tnr_dmd, u32 *ber); + +int cxd2880_tnrdmd_dvbt_mon_tps_info(struct cxd2880_tnrdmd + *tnr_dmd, + struct cxd2880_dvbt_tpsinfo + *info); + +int cxd2880_tnrdmd_dvbt_mon_packet_error_number(struct + cxd2880_tnrdmd + *tnr_dmd, + u32 *pen); + +int cxd2880_tnrdmd_dvbt_mon_spectrum_sense(struct cxd2880_tnrdmd + *tnr_dmd, + enum + cxd2880_tnrdmd_spectrum_sense + *sense); + +int cxd2880_tnrdmd_dvbt_mon_snr(struct cxd2880_tnrdmd *tnr_dmd, + int *snr); + +int cxd2880_tnrdmd_dvbt_mon_snr_diver(struct cxd2880_tnrdmd + *tnr_dmd, int *snr, + int *snr_main, int *snr_sub); + +int cxd2880_tnrdmd_dvbt_mon_sampling_offset(struct cxd2880_tnrdmd + *tnr_dmd, int *ppm); + +int cxd2880_tnrdmd_dvbt_mon_sampling_offset_sub(struct + cxd2880_tnrdmd + *tnr_dmd, + int *ppm); + +int cxd2880_tnrdmd_dvbt_mon_quality(struct cxd2880_tnrdmd *tnr_dmd, + u8 *quality); + +int cxd2880_tnrdmd_dvbt_mon_per(struct cxd2880_tnrdmd *tnr_dmd, + u32 *per); + +int cxd2880_tnrdmd_dvbt_mon_ssi(struct cxd2880_tnrdmd *tnr_dmd, + u8 *ssi); + +int cxd2880_tnrdmd_dvbt_mon_ssi_sub(struct cxd2880_tnrdmd *tnr_dmd, + u8 *ssi); + +#endif