xref: /linux/Documentation/driver-api/media/dtv-frontend.rst (revision 1785c8290489bb4b9f2897b7f545fd06e1f6d226)
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