1f2ac8ce8SMauro Carvalho Chehab.. SPDX-License-Identifier: GPL-2.0 2f2ac8ce8SMauro Carvalho Chehab 35b3b8c81SMauro Carvalho ChehabDigital TV Frontend kABI 45b3b8c81SMauro Carvalho Chehab------------------------ 55b3b8c81SMauro Carvalho Chehab 65b3b8c81SMauro Carvalho ChehabDigital TV Frontend 75b3b8c81SMauro Carvalho Chehab~~~~~~~~~~~~~~~~~~~ 85b3b8c81SMauro Carvalho Chehab 95b3b8c81SMauro Carvalho ChehabThe Digital TV Frontend kABI defines a driver-internal interface for 105b3b8c81SMauro Carvalho Chehabregistering low-level, hardware specific driver to a hardware independent 115b3b8c81SMauro Carvalho Chehabfrontend layer. It is only of interest for Digital TV device driver writers. 125b3b8c81SMauro Carvalho ChehabThe header file for this API is named ``dvb_frontend.h`` and located in 13fada1935SMauro Carvalho Chehab``include/media/``. 145b3b8c81SMauro Carvalho Chehab 155b3b8c81SMauro Carvalho ChehabDemodulator driver 165b3b8c81SMauro Carvalho Chehab^^^^^^^^^^^^^^^^^^ 175b3b8c81SMauro Carvalho Chehab 18f19dfd26SDaniel W. S. AlmeidaThe demodulator driver is responsible for talking with the decoding part of the 19f19dfd26SDaniel W. S. Almeidahardware. Such driver should implement :c:type:`dvb_frontend_ops`, which 205b3b8c81SMauro Carvalho Chehabtells what type of digital TV standards are supported, and points to a 215b3b8c81SMauro Carvalho Chehabseries of functions that allow the DVB core to command the hardware via 22fada1935SMauro Carvalho Chehabthe code under ``include/media/dvb_frontend.c``. 235b3b8c81SMauro Carvalho Chehab 245b3b8c81SMauro Carvalho ChehabA typical example of such struct in a driver ``foo`` is:: 255b3b8c81SMauro Carvalho Chehab 265b3b8c81SMauro Carvalho Chehab static struct dvb_frontend_ops foo_ops = { 275b3b8c81SMauro Carvalho Chehab .delsys = { SYS_DVBT, SYS_DVBT2, SYS_DVBC_ANNEX_A }, 285b3b8c81SMauro Carvalho Chehab .info = { 295b3b8c81SMauro Carvalho Chehab .name = "foo DVB-T/T2/C driver", 305b3b8c81SMauro Carvalho Chehab .caps = FE_CAN_FEC_1_2 | 315b3b8c81SMauro Carvalho Chehab FE_CAN_FEC_2_3 | 325b3b8c81SMauro Carvalho Chehab FE_CAN_FEC_3_4 | 335b3b8c81SMauro Carvalho Chehab FE_CAN_FEC_5_6 | 345b3b8c81SMauro Carvalho Chehab FE_CAN_FEC_7_8 | 355b3b8c81SMauro Carvalho Chehab FE_CAN_FEC_AUTO | 365b3b8c81SMauro Carvalho Chehab FE_CAN_QPSK | 375b3b8c81SMauro Carvalho Chehab FE_CAN_QAM_16 | 385b3b8c81SMauro Carvalho Chehab FE_CAN_QAM_32 | 395b3b8c81SMauro Carvalho Chehab FE_CAN_QAM_64 | 405b3b8c81SMauro Carvalho Chehab FE_CAN_QAM_128 | 415b3b8c81SMauro Carvalho Chehab FE_CAN_QAM_256 | 425b3b8c81SMauro Carvalho Chehab FE_CAN_QAM_AUTO | 435b3b8c81SMauro Carvalho Chehab FE_CAN_TRANSMISSION_MODE_AUTO | 445b3b8c81SMauro Carvalho Chehab FE_CAN_GUARD_INTERVAL_AUTO | 455b3b8c81SMauro Carvalho Chehab FE_CAN_HIERARCHY_AUTO | 465b3b8c81SMauro Carvalho Chehab FE_CAN_MUTE_TS | 475b3b8c81SMauro Carvalho Chehab FE_CAN_2G_MODULATION, 485b3b8c81SMauro Carvalho Chehab .frequency_min = 42000000, /* Hz */ 495b3b8c81SMauro Carvalho Chehab .frequency_max = 1002000000, /* Hz */ 505b3b8c81SMauro Carvalho Chehab .symbol_rate_min = 870000, 515b3b8c81SMauro Carvalho Chehab .symbol_rate_max = 11700000 525b3b8c81SMauro Carvalho Chehab }, 535b3b8c81SMauro Carvalho Chehab .init = foo_init, 545b3b8c81SMauro Carvalho Chehab .sleep = foo_sleep, 555b3b8c81SMauro Carvalho Chehab .release = foo_release, 565b3b8c81SMauro Carvalho Chehab .set_frontend = foo_set_frontend, 575b3b8c81SMauro Carvalho Chehab .get_frontend = foo_get_frontend, 585b3b8c81SMauro Carvalho Chehab .read_status = foo_get_status_and_stats, 595b3b8c81SMauro Carvalho Chehab .tune = foo_tune, 605b3b8c81SMauro Carvalho Chehab .i2c_gate_ctrl = foo_i2c_gate_ctrl, 615b3b8c81SMauro Carvalho Chehab .get_frontend_algo = foo_get_algo, 625b3b8c81SMauro Carvalho Chehab }; 635b3b8c81SMauro Carvalho Chehab 645b3b8c81SMauro Carvalho ChehabA typical example of such struct in a driver ``bar`` meant to be used on 655b3b8c81SMauro Carvalho ChehabSatellite TV reception is:: 665b3b8c81SMauro Carvalho Chehab 675b3b8c81SMauro Carvalho Chehab static const struct dvb_frontend_ops bar_ops = { 685b3b8c81SMauro Carvalho Chehab .delsys = { SYS_DVBS, SYS_DVBS2 }, 695b3b8c81SMauro Carvalho Chehab .info = { 705b3b8c81SMauro Carvalho Chehab .name = "Bar DVB-S/S2 demodulator", 715b3b8c81SMauro Carvalho Chehab .frequency_min = 500000, /* KHz */ 725b3b8c81SMauro Carvalho Chehab .frequency_max = 2500000, /* KHz */ 735b3b8c81SMauro Carvalho Chehab .frequency_stepsize = 0, 745b3b8c81SMauro Carvalho Chehab .symbol_rate_min = 1000000, 755b3b8c81SMauro Carvalho Chehab .symbol_rate_max = 45000000, 765b3b8c81SMauro Carvalho Chehab .symbol_rate_tolerance = 500, 775b3b8c81SMauro Carvalho Chehab .caps = FE_CAN_INVERSION_AUTO | 785b3b8c81SMauro Carvalho Chehab FE_CAN_FEC_AUTO | 795b3b8c81SMauro Carvalho Chehab FE_CAN_QPSK, 805b3b8c81SMauro Carvalho Chehab }, 815b3b8c81SMauro Carvalho Chehab .init = bar_init, 825b3b8c81SMauro Carvalho Chehab .sleep = bar_sleep, 835b3b8c81SMauro Carvalho Chehab .release = bar_release, 845b3b8c81SMauro Carvalho Chehab .set_frontend = bar_set_frontend, 855b3b8c81SMauro Carvalho Chehab .get_frontend = bar_get_frontend, 865b3b8c81SMauro Carvalho Chehab .read_status = bar_get_status_and_stats, 875b3b8c81SMauro Carvalho Chehab .i2c_gate_ctrl = bar_i2c_gate_ctrl, 885b3b8c81SMauro Carvalho Chehab .get_frontend_algo = bar_get_algo, 895b3b8c81SMauro Carvalho Chehab .tune = bar_tune, 905b3b8c81SMauro Carvalho Chehab 915b3b8c81SMauro Carvalho Chehab /* Satellite-specific */ 925b3b8c81SMauro Carvalho Chehab .diseqc_send_master_cmd = bar_send_diseqc_msg, 935b3b8c81SMauro Carvalho Chehab .diseqc_send_burst = bar_send_burst, 945b3b8c81SMauro Carvalho Chehab .set_tone = bar_set_tone, 955b3b8c81SMauro Carvalho Chehab .set_voltage = bar_set_voltage, 965b3b8c81SMauro Carvalho Chehab }; 975b3b8c81SMauro Carvalho Chehab 985b3b8c81SMauro Carvalho Chehab.. note:: 995b3b8c81SMauro Carvalho Chehab 1005b3b8c81SMauro Carvalho Chehab #) For satellite digital TV standards (DVB-S, DVB-S2, ISDB-S), the 1015b3b8c81SMauro Carvalho Chehab frequencies are specified in kHz, while, for terrestrial and cable 1025b3b8c81SMauro Carvalho Chehab standards, they're specified in Hz. Due to that, if the same frontend 1035b3b8c81SMauro Carvalho Chehab supports both types, you'll need to have two separate 1045b3b8c81SMauro Carvalho Chehab :c:type:`dvb_frontend_ops` structures, one for each standard. 1055b3b8c81SMauro Carvalho Chehab #) The ``.i2c_gate_ctrl`` field is present only when the hardware has 1065b3b8c81SMauro Carvalho Chehab allows controlling an I2C gate (either directly of via some GPIO pin), 1075b3b8c81SMauro Carvalho Chehab in order to remove the tuner from the I2C bus after a channel is 1085b3b8c81SMauro Carvalho Chehab tuned. 1095b3b8c81SMauro Carvalho Chehab #) All new drivers should implement the 1105b3b8c81SMauro Carvalho Chehab :ref:`DVBv5 statistics <dvbv5_stats>` via ``.read_status``. 1115b3b8c81SMauro Carvalho Chehab Yet, there are a number of callbacks meant to get statistics for 1125b3b8c81SMauro Carvalho Chehab signal strength, S/N and UCB. Those are there to provide backward 1135b3b8c81SMauro Carvalho Chehab compatibility with legacy applications that don't support the DVBv5 1145b3b8c81SMauro Carvalho Chehab API. Implementing those callbacks are optional. Those callbacks may be 1155b3b8c81SMauro Carvalho Chehab removed in the future, after we have all existing drivers supporting 1165b3b8c81SMauro Carvalho Chehab DVBv5 stats. 1175b3b8c81SMauro Carvalho Chehab #) Other callbacks are required for satellite TV standards, in order to 1185b3b8c81SMauro Carvalho Chehab control LNBf and DiSEqC: ``.diseqc_send_master_cmd``, 1195b3b8c81SMauro Carvalho Chehab ``.diseqc_send_burst``, ``.set_tone``, ``.set_voltage``. 1205b3b8c81SMauro Carvalho Chehab 1215b3b8c81SMauro Carvalho Chehab.. |delta| unicode:: U+00394 1225b3b8c81SMauro Carvalho Chehab 123f19dfd26SDaniel W. S. AlmeidaThe ``include/media/dvb_frontend.c`` has a kernel thread which is 124b2fc98fcSMauro Carvalho Chehabresponsible for tuning the device. It supports multiple algorithms to 1255b3b8c81SMauro Carvalho Chehabdetect a channel, as defined at enum :c:func:`dvbfe_algo`. 1265b3b8c81SMauro Carvalho Chehab 1275b3b8c81SMauro Carvalho ChehabThe algorithm to be used is obtained via ``.get_frontend_algo``. If the driver 1289303c9d5SMauro Carvalho Chehabdoesn't fill its field at struct dvb_frontend_ops, it will default to 1295b3b8c81SMauro Carvalho Chehab``DVBFE_ALGO_SW``, meaning that the dvb-core will do a zigzag when tuning, 1305b3b8c81SMauro Carvalho Chehabe. g. it will try first to use the specified center frequency ``f``, 1315b3b8c81SMauro Carvalho Chehabthen, it will do ``f`` + |delta|, ``f`` - |delta|, ``f`` + 2 x |delta|, 1325b3b8c81SMauro Carvalho Chehab``f`` - 2 x |delta| and so on. 1335b3b8c81SMauro Carvalho Chehab 1345b3b8c81SMauro Carvalho ChehabIf the hardware has internally a some sort of zigzag algorithm, you should 1355b3b8c81SMauro Carvalho Chehabdefine a ``.get_frontend_algo`` function that would return ``DVBFE_ALGO_HW``. 1365b3b8c81SMauro Carvalho Chehab 1375b3b8c81SMauro Carvalho Chehab.. note:: 1385b3b8c81SMauro Carvalho Chehab 1395b3b8c81SMauro Carvalho Chehab The core frontend support also supports 1405b3b8c81SMauro Carvalho Chehab a third type (``DVBFE_ALGO_CUSTOM``), in order to allow the driver to 1415b3b8c81SMauro Carvalho Chehab define its own hardware-assisted algorithm. Very few hardware need to 1425b3b8c81SMauro Carvalho Chehab use it nowadays. Using ``DVBFE_ALGO_CUSTOM`` require to provide other 1439303c9d5SMauro Carvalho Chehab function callbacks at struct dvb_frontend_ops. 1445b3b8c81SMauro Carvalho Chehab 1455b3b8c81SMauro Carvalho ChehabAttaching frontend driver to the bridge driver 1465b3b8c81SMauro Carvalho Chehab^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 1475b3b8c81SMauro Carvalho Chehab 1485b3b8c81SMauro Carvalho ChehabBefore using the Digital TV frontend core, the bridge driver should attach 1495b3b8c81SMauro Carvalho Chehabthe frontend demod, tuner and SEC devices and call 1505b3b8c81SMauro Carvalho Chehab:c:func:`dvb_register_frontend()`, 1515b3b8c81SMauro Carvalho Chehabin order to register the new frontend at the subsystem. At device 1525b3b8c81SMauro Carvalho Chehabdetach/removal, the bridge driver should call 1535b3b8c81SMauro Carvalho Chehab:c:func:`dvb_unregister_frontend()` to 1545b3b8c81SMauro Carvalho Chehabremove the frontend from the core and then :c:func:`dvb_frontend_detach()` 1555b3b8c81SMauro Carvalho Chehabto free the memory allocated by the frontend drivers. 1565b3b8c81SMauro Carvalho Chehab 1575b3b8c81SMauro Carvalho ChehabThe drivers should also call :c:func:`dvb_frontend_suspend()` as part of 1585b3b8c81SMauro Carvalho Chehabtheir handler for the :c:type:`device_driver`.\ ``suspend()``, and 1595b3b8c81SMauro Carvalho Chehab:c:func:`dvb_frontend_resume()` as 1605b3b8c81SMauro Carvalho Chehabpart of their handler for :c:type:`device_driver`.\ ``resume()``. 1615b3b8c81SMauro Carvalho Chehab 1625b3b8c81SMauro Carvalho ChehabA few other optional functions are provided to handle some special cases. 1635b3b8c81SMauro Carvalho Chehab 1645b3b8c81SMauro Carvalho Chehab.. _dvbv5_stats: 1655b3b8c81SMauro Carvalho Chehab 1665b3b8c81SMauro Carvalho ChehabDigital TV Frontend statistics 1675b3b8c81SMauro Carvalho Chehab~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1685b3b8c81SMauro Carvalho Chehab 1695b3b8c81SMauro Carvalho ChehabIntroduction 1705b3b8c81SMauro Carvalho Chehab^^^^^^^^^^^^ 1715b3b8c81SMauro Carvalho Chehab 1725b3b8c81SMauro Carvalho ChehabDigital TV frontends provide a range of 1735b3b8c81SMauro Carvalho Chehab:ref:`statistics <frontend-stat-properties>` meant to help tuning the device 1745b3b8c81SMauro Carvalho Chehaband measuring the quality of service. 1755b3b8c81SMauro Carvalho Chehab 1765b3b8c81SMauro Carvalho ChehabFor each statistics measurement, the driver should set the type of scale used, 1775b3b8c81SMauro Carvalho Chehabor ``FE_SCALE_NOT_AVAILABLE`` if the statistics is not available on a given 1785b3b8c81SMauro Carvalho Chehabtime. Drivers should also provide the number of statistics for each type. 1795b3b8c81SMauro Carvalho Chehabthat's usually 1 for most video standards [#f2]_. 1805b3b8c81SMauro Carvalho Chehab 1815b3b8c81SMauro Carvalho ChehabDrivers should initialize each statistic counters with length and 1825b3b8c81SMauro Carvalho Chehabscale at its init code. For example, if the frontend provides signal 1835b3b8c81SMauro Carvalho Chehabstrength, it should have, on its init code:: 1845b3b8c81SMauro Carvalho Chehab 1855b3b8c81SMauro Carvalho Chehab struct dtv_frontend_properties *c = &state->fe.dtv_property_cache; 1865b3b8c81SMauro Carvalho Chehab 1875b3b8c81SMauro Carvalho Chehab c->strength.len = 1; 1885b3b8c81SMauro Carvalho Chehab c->strength.stat[0].scale = FE_SCALE_NOT_AVAILABLE; 1895b3b8c81SMauro Carvalho Chehab 1905b3b8c81SMauro Carvalho ChehabAnd, when the statistics got updated, set the scale:: 1915b3b8c81SMauro Carvalho Chehab 1925b3b8c81SMauro Carvalho Chehab c->strength.stat[0].scale = FE_SCALE_DECIBEL; 1935b3b8c81SMauro Carvalho Chehab c->strength.stat[0].uvalue = strength; 1945b3b8c81SMauro Carvalho Chehab 1955b3b8c81SMauro Carvalho Chehab.. [#f2] For ISDB-T, it may provide both a global statistics and a per-layer 1965b3b8c81SMauro Carvalho Chehab set of statistics. On such cases, len should be equal to 4. The first 1975b3b8c81SMauro Carvalho Chehab value corresponds to the global stat; the other ones to each layer, e. g.: 1985b3b8c81SMauro Carvalho Chehab 1995b3b8c81SMauro Carvalho Chehab - c->cnr.stat[0] for global S/N carrier ratio, 2005b3b8c81SMauro Carvalho Chehab - c->cnr.stat[1] for Layer A S/N carrier ratio, 2015b3b8c81SMauro Carvalho Chehab - c->cnr.stat[2] for layer B S/N carrier ratio, 2025b3b8c81SMauro Carvalho Chehab - c->cnr.stat[3] for layer C S/N carrier ratio. 2035b3b8c81SMauro Carvalho Chehab 2045b3b8c81SMauro Carvalho Chehab.. note:: Please prefer to use ``FE_SCALE_DECIBEL`` instead of 2055b3b8c81SMauro Carvalho Chehab ``FE_SCALE_RELATIVE`` for signal strength and CNR measurements. 2065b3b8c81SMauro Carvalho Chehab 2075b3b8c81SMauro Carvalho ChehabGroups of statistics 2085b3b8c81SMauro Carvalho Chehab^^^^^^^^^^^^^^^^^^^^ 2095b3b8c81SMauro Carvalho Chehab 2105b3b8c81SMauro Carvalho ChehabThere are several groups of statistics currently supported: 2115b3b8c81SMauro Carvalho Chehab 2125b3b8c81SMauro Carvalho ChehabSignal strength (:ref:`DTV-STAT-SIGNAL-STRENGTH`) 2135b3b8c81SMauro Carvalho Chehab - Measures the signal strength level at the analog part of the tuner or 2145b3b8c81SMauro Carvalho Chehab demod. 2155b3b8c81SMauro Carvalho Chehab 2165b3b8c81SMauro Carvalho Chehab - Typically obtained from the gain applied to the tuner and/or frontend 2175b3b8c81SMauro Carvalho Chehab in order to detect the carrier. When no carrier is detected, the gain is 2185b3b8c81SMauro Carvalho Chehab at the maximum value (so, strength is on its minimal). 2195b3b8c81SMauro Carvalho Chehab 2205b3b8c81SMauro Carvalho Chehab - As the gain is visible through the set of registers that adjust the gain, 2215b3b8c81SMauro Carvalho Chehab typically, this statistics is always available [#f3]_. 2225b3b8c81SMauro Carvalho Chehab 223f19dfd26SDaniel W. S. Almeida - Drivers should try to make it available all the times, as these statistics 2245b3b8c81SMauro Carvalho Chehab can be used when adjusting an antenna position and to check for troubles 2255b3b8c81SMauro Carvalho Chehab at the cabling. 2265b3b8c81SMauro Carvalho Chehab 227f19dfd26SDaniel W. S. Almeida .. [#f3] On a few devices, the gain keeps floating if there is no carrier. 2285b3b8c81SMauro Carvalho Chehab On such devices, strength report should check first if carrier is 2295b3b8c81SMauro Carvalho Chehab detected at the tuner (``FE_HAS_CARRIER``, see :c:type:`fe_status`), 2305b3b8c81SMauro Carvalho Chehab and otherwise return the lowest possible value. 2315b3b8c81SMauro Carvalho Chehab 2325b3b8c81SMauro Carvalho ChehabCarrier Signal to Noise ratio (:ref:`DTV-STAT-CNR`) 2335b3b8c81SMauro Carvalho Chehab - Signal to Noise ratio for the main carrier. 2345b3b8c81SMauro Carvalho Chehab 235f19dfd26SDaniel W. S. Almeida - Signal to Noise measurement depends on the device. On some hardware, it is 2365b3b8c81SMauro Carvalho Chehab available when the main carrier is detected. On those hardware, CNR 2375b3b8c81SMauro Carvalho Chehab measurement usually comes from the tuner (e. g. after ``FE_HAS_CARRIER``, 2385b3b8c81SMauro Carvalho Chehab see :c:type:`fe_status`). 2395b3b8c81SMauro Carvalho Chehab 2405b3b8c81SMauro Carvalho Chehab On other devices, it requires inner FEC decoding, 2415b3b8c81SMauro Carvalho Chehab as the frontend measures it indirectly from other parameters (e. g. after 2425b3b8c81SMauro Carvalho Chehab ``FE_HAS_VITERBI``, see :c:type:`fe_status`). 2435b3b8c81SMauro Carvalho Chehab 2445b3b8c81SMauro Carvalho Chehab Having it available after inner FEC is more common. 2455b3b8c81SMauro Carvalho Chehab 2465b3b8c81SMauro Carvalho ChehabBit counts post-FEC (:ref:`DTV-STAT-POST-ERROR-BIT-COUNT` and :ref:`DTV-STAT-POST-TOTAL-BIT-COUNT`) 247*1785c829SRandy Dunlap - Those counters measure the number of bits and bit errors after 2485b3b8c81SMauro Carvalho Chehab the forward error correction (FEC) on the inner coding block 2495b3b8c81SMauro Carvalho Chehab (after Viterbi, LDPC or other inner code). 2505b3b8c81SMauro Carvalho Chehab 2515b3b8c81SMauro Carvalho Chehab - Due to its nature, those statistics depend on full coding lock 2525b3b8c81SMauro Carvalho Chehab (e. g. after ``FE_HAS_SYNC`` or after ``FE_HAS_LOCK``, 2535b3b8c81SMauro Carvalho Chehab see :c:type:`fe_status`). 2545b3b8c81SMauro Carvalho Chehab 2555b3b8c81SMauro Carvalho ChehabBit counts pre-FEC (:ref:`DTV-STAT-PRE-ERROR-BIT-COUNT` and :ref:`DTV-STAT-PRE-TOTAL-BIT-COUNT`) 256*1785c829SRandy Dunlap - Those counters measure the number of bits and bit errors before 2575b3b8c81SMauro Carvalho Chehab the forward error correction (FEC) on the inner coding block 2585b3b8c81SMauro Carvalho Chehab (before Viterbi, LDPC or other inner code). 2595b3b8c81SMauro Carvalho Chehab 2605b3b8c81SMauro Carvalho Chehab - Not all frontends provide this kind of statistics. 2615b3b8c81SMauro Carvalho Chehab 2625b3b8c81SMauro Carvalho Chehab - Due to its nature, those statistics depend on inner coding lock (e. g. 2635b3b8c81SMauro Carvalho Chehab after ``FE_HAS_VITERBI``, see :c:type:`fe_status`). 2645b3b8c81SMauro Carvalho Chehab 2655b3b8c81SMauro Carvalho ChehabBlock counts (:ref:`DTV-STAT-ERROR-BLOCK-COUNT` and :ref:`DTV-STAT-TOTAL-BLOCK-COUNT`) 266*1785c829SRandy Dunlap - Those counters measure the number of blocks and block errors after 2675b3b8c81SMauro Carvalho Chehab the forward error correction (FEC) on the inner coding block 2685b3b8c81SMauro Carvalho Chehab (before Viterbi, LDPC or other inner code). 2695b3b8c81SMauro Carvalho Chehab 2705b3b8c81SMauro Carvalho Chehab - Due to its nature, those statistics depend on full coding lock 2715b3b8c81SMauro Carvalho Chehab (e. g. after ``FE_HAS_SYNC`` or after 2725b3b8c81SMauro Carvalho Chehab ``FE_HAS_LOCK``, see :c:type:`fe_status`). 2735b3b8c81SMauro Carvalho Chehab 2745b3b8c81SMauro Carvalho Chehab.. note:: All counters should be monotonically increased as they're 2755b3b8c81SMauro Carvalho Chehab collected from the hardware. 2765b3b8c81SMauro Carvalho Chehab 2775b3b8c81SMauro Carvalho ChehabA typical example of the logic that handle status and statistics is:: 2785b3b8c81SMauro Carvalho Chehab 2795b3b8c81SMauro Carvalho Chehab static int foo_get_status_and_stats(struct dvb_frontend *fe) 2805b3b8c81SMauro Carvalho Chehab { 2815b3b8c81SMauro Carvalho Chehab struct foo_state *state = fe->demodulator_priv; 2825b3b8c81SMauro Carvalho Chehab struct dtv_frontend_properties *c = &fe->dtv_property_cache; 2835b3b8c81SMauro Carvalho Chehab 2845b3b8c81SMauro Carvalho Chehab int rc; 2855b3b8c81SMauro Carvalho Chehab enum fe_status *status; 2865b3b8c81SMauro Carvalho Chehab 2875b3b8c81SMauro Carvalho Chehab /* Both status and strength are always available */ 2885b3b8c81SMauro Carvalho Chehab rc = foo_read_status(fe, &status); 2895b3b8c81SMauro Carvalho Chehab if (rc < 0) 2905b3b8c81SMauro Carvalho Chehab return rc; 2915b3b8c81SMauro Carvalho Chehab 2925b3b8c81SMauro Carvalho Chehab rc = foo_read_strength(fe); 2935b3b8c81SMauro Carvalho Chehab if (rc < 0) 2945b3b8c81SMauro Carvalho Chehab return rc; 2955b3b8c81SMauro Carvalho Chehab 2965b3b8c81SMauro Carvalho Chehab /* Check if CNR is available */ 2975b3b8c81SMauro Carvalho Chehab if (!(fe->status & FE_HAS_CARRIER)) 2985b3b8c81SMauro Carvalho Chehab return 0; 2995b3b8c81SMauro Carvalho Chehab 3005b3b8c81SMauro Carvalho Chehab rc = foo_read_cnr(fe); 3015b3b8c81SMauro Carvalho Chehab if (rc < 0) 3025b3b8c81SMauro Carvalho Chehab return rc; 3035b3b8c81SMauro Carvalho Chehab 3045b3b8c81SMauro Carvalho Chehab /* Check if pre-BER stats are available */ 3055b3b8c81SMauro Carvalho Chehab if (!(fe->status & FE_HAS_VITERBI)) 3065b3b8c81SMauro Carvalho Chehab return 0; 3075b3b8c81SMauro Carvalho Chehab 3085b3b8c81SMauro Carvalho Chehab rc = foo_get_pre_ber(fe); 3095b3b8c81SMauro Carvalho Chehab if (rc < 0) 3105b3b8c81SMauro Carvalho Chehab return rc; 3115b3b8c81SMauro Carvalho Chehab 3125b3b8c81SMauro Carvalho Chehab /* Check if post-BER stats are available */ 3135b3b8c81SMauro Carvalho Chehab if (!(fe->status & FE_HAS_SYNC)) 3145b3b8c81SMauro Carvalho Chehab return 0; 3155b3b8c81SMauro Carvalho Chehab 3165b3b8c81SMauro Carvalho Chehab rc = foo_get_post_ber(fe); 3175b3b8c81SMauro Carvalho Chehab if (rc < 0) 3185b3b8c81SMauro Carvalho Chehab return rc; 3195b3b8c81SMauro Carvalho Chehab } 3205b3b8c81SMauro Carvalho Chehab 3215b3b8c81SMauro Carvalho Chehab static const struct dvb_frontend_ops ops = { 3225b3b8c81SMauro Carvalho Chehab /* ... */ 3235b3b8c81SMauro Carvalho Chehab .read_status = foo_get_status_and_stats, 3245b3b8c81SMauro Carvalho Chehab }; 3255b3b8c81SMauro Carvalho Chehab 326f19dfd26SDaniel W. S. AlmeidaStatistics collection 327f19dfd26SDaniel W. S. Almeida^^^^^^^^^^^^^^^^^^^^^ 3285b3b8c81SMauro Carvalho Chehab 3295b3b8c81SMauro Carvalho ChehabOn almost all frontend hardware, the bit and byte counts are stored by 3305b3b8c81SMauro Carvalho Chehabthe hardware after a certain amount of time or after the total bit/block 331adf48e3fSMauro Carvalho Chehabcounter reaches a certain value (usually programmable), for example, on 3325b3b8c81SMauro Carvalho Chehabevery 1000 ms or after receiving 1,000,000 bits. 3335b3b8c81SMauro Carvalho Chehab 3345b3b8c81SMauro Carvalho ChehabSo, if you read the registers too soon, you'll end by reading the same 3355b3b8c81SMauro Carvalho Chehabvalue as in the previous reading, causing the monotonic value to be 3365b3b8c81SMauro Carvalho Chehabincremented too often. 3375b3b8c81SMauro Carvalho Chehab 3385b3b8c81SMauro Carvalho ChehabDrivers should take the responsibility to avoid too often reads. That 3395b3b8c81SMauro Carvalho Chehabcan be done using two approaches: 3405b3b8c81SMauro Carvalho Chehab 3415b3b8c81SMauro Carvalho Chehabif the driver have a bit that indicates when a collected data is ready 3425b3b8c81SMauro Carvalho Chehab%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 3435b3b8c81SMauro Carvalho Chehab 3445b3b8c81SMauro Carvalho ChehabDriver should check such bit before making the statistics available. 3455b3b8c81SMauro Carvalho Chehab 3465b3b8c81SMauro Carvalho ChehabAn example of such behavior can be found at this code snippet (adapted 3475b3b8c81SMauro Carvalho Chehabfrom mb86a20s driver's logic):: 3485b3b8c81SMauro Carvalho Chehab 3495b3b8c81SMauro Carvalho Chehab static int foo_get_pre_ber(struct dvb_frontend *fe) 3505b3b8c81SMauro Carvalho Chehab { 3515b3b8c81SMauro Carvalho Chehab struct foo_state *state = fe->demodulator_priv; 3525b3b8c81SMauro Carvalho Chehab struct dtv_frontend_properties *c = &fe->dtv_property_cache; 3535b3b8c81SMauro Carvalho Chehab int rc, bit_error; 3545b3b8c81SMauro Carvalho Chehab 3555b3b8c81SMauro Carvalho Chehab /* Check if the BER measures are already available */ 3565b3b8c81SMauro Carvalho Chehab rc = foo_read_u8(state, 0x54); 3575b3b8c81SMauro Carvalho Chehab if (rc < 0) 3585b3b8c81SMauro Carvalho Chehab return rc; 3595b3b8c81SMauro Carvalho Chehab 3605b3b8c81SMauro Carvalho Chehab if (!rc) 3615b3b8c81SMauro Carvalho Chehab return 0; 3625b3b8c81SMauro Carvalho Chehab 3635b3b8c81SMauro Carvalho Chehab /* Read Bit Error Count */ 3645b3b8c81SMauro Carvalho Chehab bit_error = foo_read_u32(state, 0x55); 3655b3b8c81SMauro Carvalho Chehab if (bit_error < 0) 3665b3b8c81SMauro Carvalho Chehab return bit_error; 3675b3b8c81SMauro Carvalho Chehab 3685b3b8c81SMauro Carvalho Chehab /* Read Total Bit Count */ 3695b3b8c81SMauro Carvalho Chehab rc = foo_read_u32(state, 0x51); 3705b3b8c81SMauro Carvalho Chehab if (rc < 0) 3715b3b8c81SMauro Carvalho Chehab return rc; 3725b3b8c81SMauro Carvalho Chehab 3735b3b8c81SMauro Carvalho Chehab c->pre_bit_error.stat[0].scale = FE_SCALE_COUNTER; 3745b3b8c81SMauro Carvalho Chehab c->pre_bit_error.stat[0].uvalue += bit_error; 3755b3b8c81SMauro Carvalho Chehab c->pre_bit_count.stat[0].scale = FE_SCALE_COUNTER; 3765b3b8c81SMauro Carvalho Chehab c->pre_bit_count.stat[0].uvalue += rc; 3775b3b8c81SMauro Carvalho Chehab 3785b3b8c81SMauro Carvalho Chehab return 0; 3795b3b8c81SMauro Carvalho Chehab } 3805b3b8c81SMauro Carvalho Chehab 3815b3b8c81SMauro Carvalho ChehabIf the driver doesn't provide a statistics available check bit 3825b3b8c81SMauro Carvalho Chehab%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 3835b3b8c81SMauro Carvalho Chehab 3845b3b8c81SMauro Carvalho ChehabA few devices, however, may not provide a way to check if the stats are 3855b3b8c81SMauro Carvalho Chehabavailable (or the way to check it is unknown). They may not even provide 3865b3b8c81SMauro Carvalho Chehaba way to directly read the total number of bits or blocks. 3875b3b8c81SMauro Carvalho Chehab 3885b3b8c81SMauro Carvalho ChehabOn those devices, the driver need to ensure that it won't be reading from 3895b3b8c81SMauro Carvalho Chehabthe register too often and/or estimate the total number of bits/blocks. 3905b3b8c81SMauro Carvalho Chehab 3915b3b8c81SMauro Carvalho ChehabOn such drivers, a typical routine to get statistics would be like 3925b3b8c81SMauro Carvalho Chehab(adapted from dib8000 driver's logic):: 3935b3b8c81SMauro Carvalho Chehab 3945b3b8c81SMauro Carvalho Chehab struct foo_state { 3955b3b8c81SMauro Carvalho Chehab /* ... */ 3965b3b8c81SMauro Carvalho Chehab 3975b3b8c81SMauro Carvalho Chehab unsigned long per_jiffies_stats; 3985b3b8c81SMauro Carvalho Chehab } 3995b3b8c81SMauro Carvalho Chehab 4005b3b8c81SMauro Carvalho Chehab static int foo_get_pre_ber(struct dvb_frontend *fe) 4015b3b8c81SMauro Carvalho Chehab { 4025b3b8c81SMauro Carvalho Chehab struct foo_state *state = fe->demodulator_priv; 4035b3b8c81SMauro Carvalho Chehab struct dtv_frontend_properties *c = &fe->dtv_property_cache; 4045b3b8c81SMauro Carvalho Chehab int rc, bit_error; 4055b3b8c81SMauro Carvalho Chehab u64 bits; 4065b3b8c81SMauro Carvalho Chehab 4075b3b8c81SMauro Carvalho Chehab /* Check if time for stats was elapsed */ 4085b3b8c81SMauro Carvalho Chehab if (!time_after(jiffies, state->per_jiffies_stats)) 4095b3b8c81SMauro Carvalho Chehab return 0; 4105b3b8c81SMauro Carvalho Chehab 4115b3b8c81SMauro Carvalho Chehab /* Next stat should be collected in 1000 ms */ 4125b3b8c81SMauro Carvalho Chehab state->per_jiffies_stats = jiffies + msecs_to_jiffies(1000); 4135b3b8c81SMauro Carvalho Chehab 4145b3b8c81SMauro Carvalho Chehab /* Read Bit Error Count */ 4155b3b8c81SMauro Carvalho Chehab bit_error = foo_read_u32(state, 0x55); 4165b3b8c81SMauro Carvalho Chehab if (bit_error < 0) 4175b3b8c81SMauro Carvalho Chehab return bit_error; 4185b3b8c81SMauro Carvalho Chehab 4195b3b8c81SMauro Carvalho Chehab /* 4205b3b8c81SMauro Carvalho Chehab * On this particular frontend, there's no register that 4215b3b8c81SMauro Carvalho Chehab * would provide the number of bits per 1000ms sample. So, 4225b3b8c81SMauro Carvalho Chehab * some function would calculate it based on DTV properties 4235b3b8c81SMauro Carvalho Chehab */ 4245b3b8c81SMauro Carvalho Chehab bits = get_number_of_bits_per_1000ms(fe); 4255b3b8c81SMauro Carvalho Chehab 4265b3b8c81SMauro Carvalho Chehab c->pre_bit_error.stat[0].scale = FE_SCALE_COUNTER; 4275b3b8c81SMauro Carvalho Chehab c->pre_bit_error.stat[0].uvalue += bit_error; 4285b3b8c81SMauro Carvalho Chehab c->pre_bit_count.stat[0].scale = FE_SCALE_COUNTER; 4295b3b8c81SMauro Carvalho Chehab c->pre_bit_count.stat[0].uvalue += bits; 4305b3b8c81SMauro Carvalho Chehab 4315b3b8c81SMauro Carvalho Chehab return 0; 4325b3b8c81SMauro Carvalho Chehab } 4335b3b8c81SMauro Carvalho Chehab 4345b3b8c81SMauro Carvalho ChehabPlease notice that, on both cases, we're getting the statistics using the 4355b3b8c81SMauro Carvalho Chehab:c:type:`dvb_frontend_ops` ``.read_status`` callback. The rationale is that 4365b3b8c81SMauro Carvalho Chehabthe frontend core will automatically call this function periodically 4375b3b8c81SMauro Carvalho Chehab(usually, 3 times per second, when the frontend is locked). 4385b3b8c81SMauro Carvalho Chehab 4395b3b8c81SMauro Carvalho ChehabThat warrants that we won't miss to collect a counter and increment the 4405b3b8c81SMauro Carvalho Chehabmonotonic stats at the right time. 4415b3b8c81SMauro Carvalho Chehab 4425b3b8c81SMauro Carvalho ChehabDigital TV Frontend functions and types 4435b3b8c81SMauro Carvalho Chehab~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 4445b3b8c81SMauro Carvalho Chehab 445fada1935SMauro Carvalho Chehab.. kernel-doc:: include/media/dvb_frontend.h 446