All of lore.kernel.org
 help / color / mirror / Atom feed
* Re: [RFC, WIP, v6 03/10] media: vidtv: implement a demodulator driver
@ 2020-05-21 15:31 kbuild test robot
  0 siblings, 0 replies; 3+ messages in thread
From: kbuild test robot @ 2020-05-21 15:31 UTC (permalink / raw)
  To: kbuild

[-- Attachment #1: Type: text/plain, Size: 6793 bytes --]

CC: kbuild-all(a)lists.01.org
In-Reply-To: <20200520070334.1778751-4-dwlsalmeida@gmail.com>
References: <20200520070334.1778751-4-dwlsalmeida@gmail.com>
TO: "Daniel W. S. Almeida" <dwlsalmeida@gmail.com>

Hi "Daniel,

[FYI, it's a private test report for your RFC patch.]
[auto build test WARNING on linuxtv-media/master]
[also build test WARNING on next-20200519]
[cannot apply to linus/master linux/master v5.7-rc6]
[if your patch is applied to the wrong git tree, please drop us a note to help
improve the system. BTW, we also suggest to use '--base' option to specify the
base tree in git format-patch, please see https://stackoverflow.com/a/37406982]

url:    https://github.com/0day-ci/linux/commits/Daniel-W-S-Almeida/media-vidtv-implement-a-virtual-DVB-driver/20200520-232710
base:   git://linuxtv.org/media_tree.git master
:::::: branch date: 24 hours ago
:::::: commit date: 24 hours ago
config: mips-allyesconfig (attached as .config)
compiler: mips-linux-gcc (GCC) 9.3.0
reproduce (this is a W=1 build):
        wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # save the attached .config to linux build tree
        COMPILER_INSTALL_PATH=$HOME/0day COMPILER=gcc-9.3.0 make.cross ARCH=mips 

If you fix the issue, kindly add following tag as appropriate
Reported-by: kbuild test robot <lkp@intel.com>
Reported-by: Julia Lawall <julia.lawall@lip6.fr>


coccinelle warnings: (new ones prefixed by >>)

>> drivers/media/test-drivers/vidtv/vidtv_demod.c:358:3-18: duplicated argument to & or |

# https://github.com/0day-ci/linux/commit/fc49ec9358b6bb8f546b174d9a2a14deed8dc222
git remote add linux-review https://github.com/0day-ci/linux
git remote update linux-review
git checkout fc49ec9358b6bb8f546b174d9a2a14deed8dc222
vim +358 drivers/media/test-drivers/vidtv/vidtv_demod.c

fc49ec9358b6bb Daniel W. S. Almeida 2020-05-20  331  
fc49ec9358b6bb Daniel W. S. Almeida 2020-05-20  332  static const struct dvb_frontend_ops vidtv_demod_ops = {
fc49ec9358b6bb Daniel W. S. Almeida 2020-05-20  333  	.delsys = {
fc49ec9358b6bb Daniel W. S. Almeida 2020-05-20  334  		SYS_DVBT,
fc49ec9358b6bb Daniel W. S. Almeida 2020-05-20  335  		SYS_DVBT2,
fc49ec9358b6bb Daniel W. S. Almeida 2020-05-20  336  		SYS_DVBC_ANNEX_A,
fc49ec9358b6bb Daniel W. S. Almeida 2020-05-20  337  		SYS_DVBS,
fc49ec9358b6bb Daniel W. S. Almeida 2020-05-20  338  		SYS_DVBS2,
fc49ec9358b6bb Daniel W. S. Almeida 2020-05-20  339  	},
fc49ec9358b6bb Daniel W. S. Almeida 2020-05-20  340  
fc49ec9358b6bb Daniel W. S. Almeida 2020-05-20  341  	.info = {
fc49ec9358b6bb Daniel W. S. Almeida 2020-05-20  342  		.name                   = "Dummy demod for DVB-T/T2/C/S/S2",
fc49ec9358b6bb Daniel W. S. Almeida 2020-05-20  343  		.frequency_min_hz       = 51 * MHz,
fc49ec9358b6bb Daniel W. S. Almeida 2020-05-20  344  		.frequency_max_hz       = 2150 * MHz,
fc49ec9358b6bb Daniel W. S. Almeida 2020-05-20  345  		.frequency_stepsize_hz  = 62500,
fc49ec9358b6bb Daniel W. S. Almeida 2020-05-20  346  		.frequency_tolerance_hz = 29500 * kHz,
fc49ec9358b6bb Daniel W. S. Almeida 2020-05-20  347  		.symbol_rate_min        = 1000000,
fc49ec9358b6bb Daniel W. S. Almeida 2020-05-20  348  		.symbol_rate_max        = 45000000,
fc49ec9358b6bb Daniel W. S. Almeida 2020-05-20  349  
fc49ec9358b6bb Daniel W. S. Almeida 2020-05-20  350  		.caps = FE_CAN_FEC_1_2 |
fc49ec9358b6bb Daniel W. S. Almeida 2020-05-20  351  			FE_CAN_FEC_2_3 |
fc49ec9358b6bb Daniel W. S. Almeida 2020-05-20  352  			FE_CAN_FEC_3_4 |
fc49ec9358b6bb Daniel W. S. Almeida 2020-05-20  353  			FE_CAN_FEC_4_5 |
fc49ec9358b6bb Daniel W. S. Almeida 2020-05-20  354  			FE_CAN_FEC_5_6 |
fc49ec9358b6bb Daniel W. S. Almeida 2020-05-20  355  			FE_CAN_FEC_6_7 |
fc49ec9358b6bb Daniel W. S. Almeida 2020-05-20  356  			FE_CAN_FEC_7_8 |
fc49ec9358b6bb Daniel W. S. Almeida 2020-05-20  357  			FE_CAN_FEC_8_9 |
fc49ec9358b6bb Daniel W. S. Almeida 2020-05-20 @358  			FE_CAN_FEC_AUTO |
fc49ec9358b6bb Daniel W. S. Almeida 2020-05-20  359  			FE_CAN_QAM_16 |
fc49ec9358b6bb Daniel W. S. Almeida 2020-05-20  360  			FE_CAN_QAM_64 |
fc49ec9358b6bb Daniel W. S. Almeida 2020-05-20  361  			FE_CAN_QAM_32 |
fc49ec9358b6bb Daniel W. S. Almeida 2020-05-20  362  			FE_CAN_QAM_128 |
fc49ec9358b6bb Daniel W. S. Almeida 2020-05-20  363  			FE_CAN_QAM_256 |
fc49ec9358b6bb Daniel W. S. Almeida 2020-05-20  364  			FE_CAN_QAM_AUTO |
fc49ec9358b6bb Daniel W. S. Almeida 2020-05-20  365  			FE_CAN_QPSK |
fc49ec9358b6bb Daniel W. S. Almeida 2020-05-20  366  			FE_CAN_FEC_AUTO |
fc49ec9358b6bb Daniel W. S. Almeida 2020-05-20  367  			FE_CAN_INVERSION_AUTO |
fc49ec9358b6bb Daniel W. S. Almeida 2020-05-20  368  			FE_CAN_TRANSMISSION_MODE_AUTO |
fc49ec9358b6bb Daniel W. S. Almeida 2020-05-20  369  			FE_CAN_GUARD_INTERVAL_AUTO |
fc49ec9358b6bb Daniel W. S. Almeida 2020-05-20  370  			FE_CAN_HIERARCHY_AUTO,
fc49ec9358b6bb Daniel W. S. Almeida 2020-05-20  371  	},
fc49ec9358b6bb Daniel W. S. Almeida 2020-05-20  372  
fc49ec9358b6bb Daniel W. S. Almeida 2020-05-20  373  	.release = vidtv_demod_release,
fc49ec9358b6bb Daniel W. S. Almeida 2020-05-20  374  
fc49ec9358b6bb Daniel W. S. Almeida 2020-05-20  375  	.init  = vidtv_demod_init,
fc49ec9358b6bb Daniel W. S. Almeida 2020-05-20  376  	.sleep = vidtv_demod_sleep,
fc49ec9358b6bb Daniel W. S. Almeida 2020-05-20  377  
fc49ec9358b6bb Daniel W. S. Almeida 2020-05-20  378  	.set_frontend = vidtv_demod_set_frontend,
fc49ec9358b6bb Daniel W. S. Almeida 2020-05-20  379  	.get_frontend = vidtv_demod_get_frontend,
fc49ec9358b6bb Daniel W. S. Almeida 2020-05-20  380  
fc49ec9358b6bb Daniel W. S. Almeida 2020-05-20  381  	.read_status          = vidtv_demod_read_status,
fc49ec9358b6bb Daniel W. S. Almeida 2020-05-20  382  	.read_ber             = vidtv_demod_read_ber,
fc49ec9358b6bb Daniel W. S. Almeida 2020-05-20  383  	.read_signal_strength = vidtv_demod_read_signal_strength,
fc49ec9358b6bb Daniel W. S. Almeida 2020-05-20  384  	.read_snr             = vidtv_demod_read_snr,
fc49ec9358b6bb Daniel W. S. Almeida 2020-05-20  385  	.read_ucblocks        = vidtv_demod_read_ucblocks,
fc49ec9358b6bb Daniel W. S. Almeida 2020-05-20  386  
fc49ec9358b6bb Daniel W. S. Almeida 2020-05-20  387  	/* For DVB-S/S2 */
fc49ec9358b6bb Daniel W. S. Almeida 2020-05-20  388  	.set_voltage = vidtv_demod_set_voltage,
fc49ec9358b6bb Daniel W. S. Almeida 2020-05-20  389  	.set_tone    = vidtv_demod_set_tone,
fc49ec9358b6bb Daniel W. S. Almeida 2020-05-20  390  };
fc49ec9358b6bb Daniel W. S. Almeida 2020-05-20  391  

---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-all(a)lists.01.org

[-- Attachment #2: config.gz --]
[-- Type: application/gzip, Size: 65705 bytes --]

^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: [RFC, WIP, v6 03/10] media: vidtv: implement a demodulator driver
  2020-05-20  7:03 ` [RFC, WIP, v6 03/10] media: vidtv: implement a demodulator driver Daniel W. S. Almeida
@ 2020-05-28 23:39   ` Shuah Khan
  0 siblings, 0 replies; 3+ messages in thread
From: Shuah Khan @ 2020-05-28 23:39 UTC (permalink / raw)
  To: Daniel W. S. Almeida, mchehab+huawei, sean, kstewart, allison, tglx
  Cc: linux-media, linux-kernel-mentees, linux-kernel, Shuah Khan

On 5/20/20 1:03 AM, Daniel W. S. Almeida wrote:
> From: "Daniel W. S. Almeida" <dwlsalmeida@gmail.com>
> 
> Implement a I2C demodulator driver, simulating support for DVB-T, DVB-C
> and DVB-S.
> 
> This demodulator will periodically check the signal quality against a table
> and drop the TS lock if it drops below a threshold value, regaining it in
> the event that the signal improves.
> 
> Signed-off-by: Daniel W. S. Almeida <dwlsalmeida@gmail.com>
> ---
>   drivers/media/test-drivers/vidtv/Makefile     |   3 +-
>   .../media/test-drivers/vidtv/vidtv_demod.c    | 444 ++++++++++++++++++
>   .../media/test-drivers/vidtv/vidtv_demod.h    |  41 ++
>   3 files changed, 487 insertions(+), 1 deletion(-)
>   create mode 100644 drivers/media/test-drivers/vidtv/vidtv_demod.c
>   create mode 100644 drivers/media/test-drivers/vidtv/vidtv_demod.h
> 
> diff --git a/drivers/media/test-drivers/vidtv/Makefile b/drivers/media/test-drivers/vidtv/Makefile
> index 58e022c094e5e..21e50c11c94d0 100644
> --- a/drivers/media/test-drivers/vidtv/Makefile
> +++ b/drivers/media/test-drivers/vidtv/Makefile
> @@ -1,5 +1,6 @@
>   # SPDX-License-Identifier: GPL-2.0
>   
>   dvb-vidtv-tuner-objs := vidtv_tuner.o
> +dvb-vidtv-demod-objs := vidtv_demod.o
>   
> -obj-$(CONFIG_DVB_VIDTV)	+= dvb-vidtv-tuner.o
> +obj-$(CONFIG_DVB_VIDTV)	+= dvb-vidtv-tuner.o dvb-vidtv-demod.o
> diff --git a/drivers/media/test-drivers/vidtv/vidtv_demod.c b/drivers/media/test-drivers/vidtv/vidtv_demod.c
> new file mode 100644
> index 0000000000000..15912e063cf5a
> --- /dev/null
> +++ b/drivers/media/test-drivers/vidtv/vidtv_demod.c
> @@ -0,0 +1,444 @@
> +// SPDX-License-Identifier: GPL-2.0-or-later
> +/*
> + * The Virtual DVB test driver serves as a reference DVB driver and helps
> + * validate the existing APIs in the media subsystem. It can also aid
> + * developers working on userspace applications.
> + *
> + * Written by Daniel W. S. Almeida <dwlsalmeida@gmail.com>
> + * Based on the example driver written by Emard <emard@softhome.net>
> + */
> +
> +#include <linux/errno.h>
> +#include <linux/i2c.h>
> +#include <linux/init.h>
> +#include <linux/kernel.h>
> +#include <linux/module.h>
> +#include <linux/printk.h>
> +#include <linux/random.h>
> +#include <linux/ratelimit.h>
> +#include <linux/slab.h>
> +#include <linux/string.h>
> +#include <linux/workqueue.h>
> +#include <media/dvb_frontend.h>
> +
> +#include "vidtv_demod.h"
> +
> +// FIXME: just added a random value here
> +#define POLL_THRD_TIME 10 /* ms */
> +
> +static const struct vidtv_demod_cnr_to_qual_s vidtv_demod_c_cnr_2_qual[] = {
> +	/* from libdvbv5 source code, in milli db */
> +	{ QAM_256, FEC_NONE,  34000, 38000},
> +	{ QAM_64,  FEC_NONE,  30000, 34000},
> +};
> +
> +static const struct vidtv_demod_cnr_to_qual_s vidtv_demod_s_cnr_2_qual[] = {
> +	/* from libdvbv5 source code, in milli db */
> +	{ QPSK, FEC_1_2,  7000, 10000},
> +	{ QPSK, FEC_2_3,  9000, 12000},
> +	{ QPSK, FEC_3_4, 10000, 13000},
> +	{ QPSK, FEC_5_6, 11000, 14000},
> +	{ QPSK, FEC_7_8, 12000, 15000},
> +};
> +
> +static const struct vidtv_demod_cnr_to_qual_s vidtv_demod_s2_cnr_2_qual[] = {
> +	/* from libdvbv5 source code, in milli db */
> +	{ QPSK,  FEC_1_2,   9000,  12000},
> +	{ QPSK,  FEC_2_3,  11000,  14000},
> +	{ QPSK,  FEC_3_4,  12000,  15000},
> +	{ QPSK,  FEC_5_6,  12000,  15000},
> +	{ QPSK,  FEC_8_9,  13000,  16000},
> +	{ QPSK,  FEC_9_10, 13500,  16500},
> +	{ PSK_8, FEC_2_3,  14500,  17500},
> +	{ PSK_8, FEC_3_4,  16000,  19000},
> +	{ PSK_8, FEC_5_6,  17500,  20500},
> +	{ PSK_8, FEC_8_9,  19000,  22000},
> +};
> +
> +static const struct vidtv_demod_cnr_to_qual_s vidtv_demod_t_cnr_2_qual[] = {
> +	/* from libdvbv5 source code, in milli db*/
> +	{   QPSK, FEC_1_2,  4100,  5900},
> +	{   QPSK, FEC_2_3,  6100,  9600},
> +	{   QPSK, FEC_3_4,  7200, 12400},
> +	{   QPSK, FEC_5_6,  8500, 15600},
> +	{   QPSK, FEC_7_8,  9200, 17500},
> +
> +	{ QAM_16, FEC_1_2,  9800, 11800},
> +	{ QAM_16, FEC_2_3, 12100, 15300},
> +	{ QAM_16, FEC_3_4, 13400, 18100},
> +	{ QAM_16, FEC_5_6, 14800, 21300},
> +	{ QAM_16, FEC_7_8, 15700, 23600},
> +
> +	{ QAM_64, FEC_1_2, 14000, 16000},
> +	{ QAM_64, FEC_2_3, 19900, 25400},
> +	{ QAM_64, FEC_3_4, 24900, 27900},
> +	{ QAM_64, FEC_5_6, 21300, 23300},
> +	{ QAM_64, FEC_7_8, 22000, 24000},
> +};
> +
> +static const struct vidtv_demod_cnr_to_qual_s
> +*vidtv_match_cnr_s(struct dvb_frontend *fe)

Looks very odd:

Move vidtv_match_cnr_s up and:
static const struct vidtv_demod_cnr_to_qual_s
		vidtv_match_cnr_s(struct dvb_frontend *fe)

is better.
			

> +{
> +	struct dtv_frontend_properties *c;
> +	const struct vidtv_demod_cnr_to_qual_s *cnr2qual = NULL;
> +	u32    array_size                          = 0;

This looks really odd. Don't align them. Align them if it makes
sense. It doesn't here.

> +	u32 i;
> +
> +	c = &fe->dtv_property_cache;
> +
> +	switch (c->delivery_system) {

Indentation

> +	case SYS_DVBT:
> +	case SYS_DVBT2:
> +		cnr2qual   = vidtv_demod_t_cnr_2_qual;
> +		array_size = ARRAY_SIZE(vidtv_demod_t_cnr_2_qual);
> +		break;
> +
> +	case SYS_DVBS:
> +		cnr2qual   = vidtv_demod_s_cnr_2_qual;
> +		array_size = ARRAY_SIZE(vidtv_demod_s_cnr_2_qual);
> +		break;
> +
> +	case SYS_DVBS2:
> +		cnr2qual   = vidtv_demod_s2_cnr_2_qual;
> +		array_size = ARRAY_SIZE(vidtv_demod_s2_cnr_2_qual);
> +		break;
> +
> +	case SYS_DVBC_ANNEX_A:
> +		cnr2qual   = vidtv_demod_c_cnr_2_qual;
> +		array_size = ARRAY_SIZE(vidtv_demod_c_cnr_2_qual);
> +		break;
> +
> +	default:
> +		pr_warn_ratelimited("%s: unsupported delivery system: %u\n",
> +				    __func__,
> +				    c->delivery_system);
> +		break;
> +	}
> +
> +	for (i = 0; i <= array_size; i++)
> +		if (cnr2qual[i].modulation == c->modulation &&
> +		    cnr2qual[i].fec == c->fec_inner)
> +			return &cnr2qual[i];
> +
> +	return NULL; /* not found */
> +}
> +
> +static void vidtv_demod_poll_snr_handler(struct work_struct *work)
> +{
> +	/*
> +	 * periodically check the signal quality and eventually
> +	 * lose the TS lock if it dips too low
> +	 */
> +	struct vidtv_demod_state *state;
> +	const struct vidtv_demod_cnr_to_qual_s *cnr2qual = NULL;
> +	struct vidtv_demod_config *config;
> +	u16 snr = 0;
> +
> +	state  = container_of(work, struct vidtv_demod_state, poll_snr.work);
> +	config = &state->config;
> +
> +	if (!state->frontend.ops.tuner_ops.get_rf_strength)
> +		return;
> +
> +	state->frontend.ops.tuner_ops.get_rf_strength(&state->frontend, &snr);
> +
> +	cnr2qual = vidtv_match_cnr_s(&state->frontend);
> +	if (!cnr2qual)
> +		return;
> +
> +	if (snr < cnr2qual->cnr_ok) {
> +		/* eventually lose the TS lock */
> +		if (prandom_u32_max(100) < config->drop_tslock_prob_on_low_snr)
> +			state->status = 0;
> +	} else {
> +		/* recover if the signal improves */
> +		if (prandom_u32_max(100) <
> +		    config->recover_tslock_prob_on_good_snr)
> +			state->status = FE_HAS_SIGNAL  |
> +					FE_HAS_CARRIER |
> +					FE_HAS_VITERBI |
> +					FE_HAS_SYNC    |
> +					FE_HAS_LOCK;
> +	}
> +
> +	schedule_delayed_work(&state->poll_snr,
> +			      msecs_to_jiffies(POLL_THRD_TIME));
> +}
> +
> +static int vidtv_demod_read_status(struct dvb_frontend *fe,
> +				   enum fe_status *status)
> +{
> +	struct vidtv_demod_state *state = fe->demodulator_priv;
> +
> +	*status = state->status;
> +
> +	return 0;
> +}
> +
> +static int vidtv_demod_read_ber(struct dvb_frontend *fe, u32 *ber)
> +{
> +	*ber = 0;
> +	return 0;
> +}
> +
> +static int vidtv_demod_read_signal_strength(struct dvb_frontend *fe,
> +					    u16 *strength)
> +{
> +	*strength = 0;
> +	return 0;
> +}
> +
> +static int vidtv_demod_read_snr(struct dvb_frontend *fe, u16 *snr)
> +{
> +	*snr = 0;
> +	return 0;
> +}
> +
> +static int vidtv_demod_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks)
> +{
> +	*ucblocks = 0;
> +	return 0;
> +}
> +
> +/*
> + * NOTE:
> + * This is implemented here just to be used as an example for real
> + * demod drivers.
> + *
> + * Should only be implemented if it actually reads something from the hardware.
> + * Also, it should check for the locks, in order to avoid report wrong data
> + * to userspace.
> + */
> +static int vidtv_demod_get_frontend(struct dvb_frontend *fe,
> +				    struct dtv_frontend_properties *p)
> +{
> +	return 0;
> +}
> +
> +static int vidtv_demod_set_frontend(struct dvb_frontend *fe)
> +{
> +	struct vidtv_demod_state *state            = fe->demodulator_priv;
> +	const struct vidtv_demod_cnr_to_qual_s *cnr2qual = NULL;
> +	u32    tuner_status                        = 0;
> +
> +	if (fe->ops.tuner_ops.set_params) {
> +		fe->ops.tuner_ops.set_params(fe);
> +
> +		/* store the CNR returned by the tuner */
> +		fe->ops.tuner_ops.get_rf_strength(fe, &state->tuner_cnr);
> +
> +		fe->ops.tuner_ops.get_status(fe, &tuner_status);
> +		state->status = (state->tuner_cnr > 0) ?  FE_HAS_SIGNAL  |
> +							  FE_HAS_CARRIER |
> +							  FE_HAS_VITERBI |
> +							  FE_HAS_SYNC    |
> +							  FE_HAS_LOCK	 :
> +							  0;
> +		cnr2qual = vidtv_match_cnr_s(fe);
> +
> +		/* signal isn't good: might lose the lock eventually */
> +		if (tuner_status == TUNER_STATUS_LOCKED &&
> +		    state->tuner_cnr < cnr2qual->cnr_good) {
> +			schedule_delayed_work(&state->poll_snr,
> +					      msecs_to_jiffies(POLL_THRD_TIME));
> +
> +			state->poll_snr_thread_running = true;
> +		}
> +
> +		if (fe->ops.i2c_gate_ctrl)
> +			fe->ops.i2c_gate_ctrl(fe, 0);
> +	}
> +
> +	return 0;
> +}
> +
> +static int vidtv_demod_sleep(struct dvb_frontend *fe)
> +{
> +	struct vidtv_demod_state *state = fe->demodulator_priv;
> +
> +	if (state->poll_snr_thread_running) {
> +		cancel_delayed_work_sync(&state->poll_snr);
> +		state->poll_snr_thread_running = false;
> +		state->poll_snr_thread_restart = true;
> +	}
> +	return 0;
> +}
> +
> +static int vidtv_demod_init(struct dvb_frontend *fe)
> +{
> +	struct vidtv_demod_state *state = fe->demodulator_priv;
> +	u32    tuner_status             = 0;
> +
> +	if (state->cold_start)
> +		INIT_DELAYED_WORK(&state->poll_snr,
> +				  &vidtv_demod_poll_snr_handler);
> +
> +	/*
> +	 * At resume, start the snr poll thread only if it was suspended with
> +	 * the thread running. Extra care should be taken here, as some tuner
> +	 * status change might happen at resume time (for example, due to an
> +	 * ioctl syscall to set_frontend, or due to a release syscall).
> +	 */
> +	fe->ops.tuner_ops.get_status(fe, &tuner_status);
> +
> +	if (tuner_status == TUNER_STATUS_LOCKED &&
> +	    state->poll_snr_thread_restart) {
> +		schedule_delayed_work(&state->poll_snr,
> +				      msecs_to_jiffies(POLL_THRD_TIME));
> +
> +		state->poll_snr_thread_restart = false;
> +	}
> +
> +	state->cold_start = false;
> +	return 0;
> +}
> +
> +/*
> + * NOTE:
> + * This is implemented here just to be used as an example for real
> + * demod drivers.
> + *
> + * Should only be implemented if the demod has support for DVB-S or DVB-S2
> + */
> +static int vidtv_demod_set_tone(struct dvb_frontend *fe,
> +				enum fe_sec_tone_mode tone)
> +{
> +	return 0;
> +}
> +
> +/*
> + * NOTE:
> + * This is implemented here just to be used as an example for real
> + * demod drivers.
> + *
> + * Should only be implemented if the demod has support for DVB-S or DVB-S2
> + */
> +static int vidtv_demod_set_voltage(struct dvb_frontend *fe,
> +				   enum fe_sec_voltage voltage)
> +{
> +	return 0;
> +}
> +
> +static void vidtv_demod_release(struct dvb_frontend *fe)
> +{
> +	struct vidtv_demod_state *state = fe->demodulator_priv;
> +
> +	if (state->poll_snr_thread_running)
> +		cancel_delayed_work_sync(&state->poll_snr);
> +
> +	kfree(state);
> +}
> +
> +static const struct dvb_frontend_ops vidtv_demod_ops = {
> +	.delsys = {
> +		SYS_DVBT,
> +		SYS_DVBT2,
> +		SYS_DVBC_ANNEX_A,
> +		SYS_DVBS,
> +		SYS_DVBS2,
> +	},
> +
> +	.info = {
> +		.name                   = "Dummy demod for DVB-T/T2/C/S/S2",
> +		.frequency_min_hz       = 51 * MHz,
> +		.frequency_max_hz       = 2150 * MHz,
> +		.frequency_stepsize_hz  = 62500,
> +		.frequency_tolerance_hz = 29500 * kHz,
> +		.symbol_rate_min        = 1000000,
> +		.symbol_rate_max        = 45000000,
> +
> +		.caps = FE_CAN_FEC_1_2 |
> +			FE_CAN_FEC_2_3 |
> +			FE_CAN_FEC_3_4 |
> +			FE_CAN_FEC_4_5 |
> +			FE_CAN_FEC_5_6 |
> +			FE_CAN_FEC_6_7 |
> +			FE_CAN_FEC_7_8 |
> +			FE_CAN_FEC_8_9 |
> +			FE_CAN_FEC_AUTO |

Here is the first one.

> +			FE_CAN_QAM_16 |
> +			FE_CAN_QAM_64 |
> +			FE_CAN_QAM_32 |
> +			FE_CAN_QAM_128 |
> +			FE_CAN_QAM_256 |
> +			FE_CAN_QAM_AUTO |
> +			FE_CAN_QPSK |
> +			FE_CAN_FEC_AUTO |

Duplicate entry? Cut and paste error perhaps.

> +			FE_CAN_INVERSION_AUTO |
> +			FE_CAN_TRANSMISSION_MODE_AUTO |
> +			FE_CAN_GUARD_INTERVAL_AUTO |
> +			FE_CAN_HIERARCHY_AUTO,
> +	},
> +
> +	.release = vidtv_demod_release,
> +
> +	.init  = vidtv_demod_init,
> +	.sleep = vidtv_demod_sleep,
> +
> +	.set_frontend = vidtv_demod_set_frontend,
> +	.get_frontend = vidtv_demod_get_frontend,
> +
> +	.read_status          = vidtv_demod_read_status,
> +	.read_ber             = vidtv_demod_read_ber,
> +	.read_signal_strength = vidtv_demod_read_signal_strength,
> +	.read_snr             = vidtv_demod_read_snr,
> +	.read_ucblocks        = vidtv_demod_read_ucblocks,
> +
> +	/* For DVB-S/S2 */
> +	.set_voltage = vidtv_demod_set_voltage,
> +	.set_tone    = vidtv_demod_set_tone,
> +};
> +
> +static const struct i2c_device_id vidtv_demod_i2c_id_table[] = {
> +	{"vidtv_demod", 0},
> +	{}
> +};
> +MODULE_DEVICE_TABLE(i2c, vidtv_demod_i2c_id_table);
> +
> +static int vidtv_demod_i2c_probe(struct i2c_client *client,
> +				 const struct i2c_device_id *id)
> +{
> +	struct vidtv_demod_state *state;
> +
> +	/* allocate memory for the internal state */
> +	state = kzalloc(sizeof(*state), GFP_KERNEL);
> +	if (!state)
> +		return -ENOMEM;
> +
> +	/* create dvb_frontend */
> +	memcpy(&state->frontend.ops,
> +	       &vidtv_demod_ops,
> +	       sizeof(struct dvb_frontend_ops));
> +
> +	state->frontend.demodulator_priv = state;
> +	i2c_set_clientdata(client, state);
> +
> +	return 0;
> +}
> +
> +static int vidtv_demod_i2c_remove(struct i2c_client *client)
> +{
> +	struct vidtv_demod_state *state = i2c_get_clientdata(client);
> +
> +	memset(&state->frontend.ops, 0, sizeof(struct dvb_frontend_ops));
> +	state->frontend.demodulator_priv = NULL;
> +	kfree(state);
> +
> +	return 0;
> +}
> +
> +static struct i2c_driver vidtv_demod_i2c_driver = {
> +	.driver = {
> +		.name                = "vidtv_demod",
> +		.suppress_bind_attrs = true,
> +	},
> +	.probe    = vidtv_demod_i2c_probe,
> +	.remove   = vidtv_demod_i2c_remove,
> +	.id_table = vidtv_demod_i2c_id_table,
> +};
> +
> +module_i2c_driver(vidtv_demod_i2c_driver);
> +
> +MODULE_DESCRIPTION("Virtual DVB Demodulator Driver");
> +MODULE_AUTHOR("Daniel W. S. Almeida");
> +MODULE_LICENSE("GPL");
> diff --git a/drivers/media/test-drivers/vidtv/vidtv_demod.h b/drivers/media/test-drivers/vidtv/vidtv_demod.h
> new file mode 100644
> index 0000000000000..b14957d9d4ea0
> --- /dev/null
> +++ b/drivers/media/test-drivers/vidtv/vidtv_demod.h
> @@ -0,0 +1,41 @@
> +/* SPDX-License-Identifier: GPL-2.0-or-later */
> +/*
> + * The Virtual DTV test driver serves as a reference DVB driver and helps
> + * validate the existing APIs in the media subsystem. It can also aid
> + * developers working on userspace applications.
> + *
> + * Written by Daniel W. S. Almeida <dwlsalmeida@gmail.com>

Change it to Copyright. Same comment on all files in this series.

> + * Based on the example driver written by Emard <emard@softhome.net>
> + */
> +
> +#ifndef VIDTV_DEMOD_H
> +#define VIDTV_DEMOD_H
> +
> +#include <linux/dvb/frontend.h>
> +#include <media/dvb_frontend.h>
> +
> +struct vidtv_demod_cnr_to_qual_s {
> +	/* attempt to use the same values as libdvbv5 */
> +	u32 modulation;
> +	u32 fec;
> +	u32 cnr_ok, cnr_good;

Move cnr_good to a separate line. Describe these variables.
Whatare they for and what they do.

> +};
> +
> +struct vidtv_demod_config {
> +	/* probability of losing the lock due to low snr */
> +	u8 drop_tslock_prob_on_low_snr;
> +	/* probability of recovering when the signal improves */
> +	u8 recover_tslock_prob_on_good_snr;
> +};
> +
> +struct vidtv_demod_state {
> +	struct dvb_frontend frontend;
> +	struct vidtv_demod_config config;
> +	struct delayed_work poll_snr;
> +	enum fe_status status;
> +	u16 tuner_cnr;
> +	bool cold_start;
> +	bool poll_snr_thread_running;
> +	bool poll_snr_thread_restart;
> +};
> +#endif // VIDTV_DEMOD_H
> 

thanks,
-- Shuah

^ permalink raw reply	[flat|nested] 3+ messages in thread

* [RFC, WIP, v6 03/10] media: vidtv: implement a demodulator driver
  2020-05-20  7:03 [RFC, WIP, v6 00/10] media: vidtv: implement a virtual DVB driver Daniel W. S. Almeida
@ 2020-05-20  7:03 ` Daniel W. S. Almeida
  2020-05-28 23:39   ` Shuah Khan
  0 siblings, 1 reply; 3+ messages in thread
From: Daniel W. S. Almeida @ 2020-05-20  7:03 UTC (permalink / raw)
  To: mchehab+huawei, sean, kstewart, allison, tglx
  Cc: Daniel W. S. Almeida, linux-media, skhan, linux-kernel-mentees,
	linux-kernel

From: "Daniel W. S. Almeida" <dwlsalmeida@gmail.com>

Implement a I2C demodulator driver, simulating support for DVB-T, DVB-C
and DVB-S.

This demodulator will periodically check the signal quality against a table
and drop the TS lock if it drops below a threshold value, regaining it in
the event that the signal improves.

Signed-off-by: Daniel W. S. Almeida <dwlsalmeida@gmail.com>
---
 drivers/media/test-drivers/vidtv/Makefile     |   3 +-
 .../media/test-drivers/vidtv/vidtv_demod.c    | 444 ++++++++++++++++++
 .../media/test-drivers/vidtv/vidtv_demod.h    |  41 ++
 3 files changed, 487 insertions(+), 1 deletion(-)
 create mode 100644 drivers/media/test-drivers/vidtv/vidtv_demod.c
 create mode 100644 drivers/media/test-drivers/vidtv/vidtv_demod.h

diff --git a/drivers/media/test-drivers/vidtv/Makefile b/drivers/media/test-drivers/vidtv/Makefile
index 58e022c094e5e..21e50c11c94d0 100644
--- a/drivers/media/test-drivers/vidtv/Makefile
+++ b/drivers/media/test-drivers/vidtv/Makefile
@@ -1,5 +1,6 @@
 # SPDX-License-Identifier: GPL-2.0
 
 dvb-vidtv-tuner-objs := vidtv_tuner.o
+dvb-vidtv-demod-objs := vidtv_demod.o
 
-obj-$(CONFIG_DVB_VIDTV)	+= dvb-vidtv-tuner.o
+obj-$(CONFIG_DVB_VIDTV)	+= dvb-vidtv-tuner.o dvb-vidtv-demod.o
diff --git a/drivers/media/test-drivers/vidtv/vidtv_demod.c b/drivers/media/test-drivers/vidtv/vidtv_demod.c
new file mode 100644
index 0000000000000..15912e063cf5a
--- /dev/null
+++ b/drivers/media/test-drivers/vidtv/vidtv_demod.c
@@ -0,0 +1,444 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * The Virtual DVB test driver serves as a reference DVB driver and helps
+ * validate the existing APIs in the media subsystem. It can also aid
+ * developers working on userspace applications.
+ *
+ * Written by Daniel W. S. Almeida <dwlsalmeida@gmail.com>
+ * Based on the example driver written by Emard <emard@softhome.net>
+ */
+
+#include <linux/errno.h>
+#include <linux/i2c.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/printk.h>
+#include <linux/random.h>
+#include <linux/ratelimit.h>
+#include <linux/slab.h>
+#include <linux/string.h>
+#include <linux/workqueue.h>
+#include <media/dvb_frontend.h>
+
+#include "vidtv_demod.h"
+
+// FIXME: just added a random value here
+#define POLL_THRD_TIME 10 /* ms */
+
+static const struct vidtv_demod_cnr_to_qual_s vidtv_demod_c_cnr_2_qual[] = {
+	/* from libdvbv5 source code, in milli db */
+	{ QAM_256, FEC_NONE,  34000, 38000},
+	{ QAM_64,  FEC_NONE,  30000, 34000},
+};
+
+static const struct vidtv_demod_cnr_to_qual_s vidtv_demod_s_cnr_2_qual[] = {
+	/* from libdvbv5 source code, in milli db */
+	{ QPSK, FEC_1_2,  7000, 10000},
+	{ QPSK, FEC_2_3,  9000, 12000},
+	{ QPSK, FEC_3_4, 10000, 13000},
+	{ QPSK, FEC_5_6, 11000, 14000},
+	{ QPSK, FEC_7_8, 12000, 15000},
+};
+
+static const struct vidtv_demod_cnr_to_qual_s vidtv_demod_s2_cnr_2_qual[] = {
+	/* from libdvbv5 source code, in milli db */
+	{ QPSK,  FEC_1_2,   9000,  12000},
+	{ QPSK,  FEC_2_3,  11000,  14000},
+	{ QPSK,  FEC_3_4,  12000,  15000},
+	{ QPSK,  FEC_5_6,  12000,  15000},
+	{ QPSK,  FEC_8_9,  13000,  16000},
+	{ QPSK,  FEC_9_10, 13500,  16500},
+	{ PSK_8, FEC_2_3,  14500,  17500},
+	{ PSK_8, FEC_3_4,  16000,  19000},
+	{ PSK_8, FEC_5_6,  17500,  20500},
+	{ PSK_8, FEC_8_9,  19000,  22000},
+};
+
+static const struct vidtv_demod_cnr_to_qual_s vidtv_demod_t_cnr_2_qual[] = {
+	/* from libdvbv5 source code, in milli db*/
+	{   QPSK, FEC_1_2,  4100,  5900},
+	{   QPSK, FEC_2_3,  6100,  9600},
+	{   QPSK, FEC_3_4,  7200, 12400},
+	{   QPSK, FEC_5_6,  8500, 15600},
+	{   QPSK, FEC_7_8,  9200, 17500},
+
+	{ QAM_16, FEC_1_2,  9800, 11800},
+	{ QAM_16, FEC_2_3, 12100, 15300},
+	{ QAM_16, FEC_3_4, 13400, 18100},
+	{ QAM_16, FEC_5_6, 14800, 21300},
+	{ QAM_16, FEC_7_8, 15700, 23600},
+
+	{ QAM_64, FEC_1_2, 14000, 16000},
+	{ QAM_64, FEC_2_3, 19900, 25400},
+	{ QAM_64, FEC_3_4, 24900, 27900},
+	{ QAM_64, FEC_5_6, 21300, 23300},
+	{ QAM_64, FEC_7_8, 22000, 24000},
+};
+
+static const struct vidtv_demod_cnr_to_qual_s
+*vidtv_match_cnr_s(struct dvb_frontend *fe)
+{
+	struct dtv_frontend_properties *c;
+	const struct vidtv_demod_cnr_to_qual_s *cnr2qual = NULL;
+	u32    array_size                          = 0;
+	u32 i;
+
+	c = &fe->dtv_property_cache;
+
+	switch (c->delivery_system) {
+	case SYS_DVBT:
+	case SYS_DVBT2:
+		cnr2qual   = vidtv_demod_t_cnr_2_qual;
+		array_size = ARRAY_SIZE(vidtv_demod_t_cnr_2_qual);
+		break;
+
+	case SYS_DVBS:
+		cnr2qual   = vidtv_demod_s_cnr_2_qual;
+		array_size = ARRAY_SIZE(vidtv_demod_s_cnr_2_qual);
+		break;
+
+	case SYS_DVBS2:
+		cnr2qual   = vidtv_demod_s2_cnr_2_qual;
+		array_size = ARRAY_SIZE(vidtv_demod_s2_cnr_2_qual);
+		break;
+
+	case SYS_DVBC_ANNEX_A:
+		cnr2qual   = vidtv_demod_c_cnr_2_qual;
+		array_size = ARRAY_SIZE(vidtv_demod_c_cnr_2_qual);
+		break;
+
+	default:
+		pr_warn_ratelimited("%s: unsupported delivery system: %u\n",
+				    __func__,
+				    c->delivery_system);
+		break;
+	}
+
+	for (i = 0; i <= array_size; i++)
+		if (cnr2qual[i].modulation == c->modulation &&
+		    cnr2qual[i].fec == c->fec_inner)
+			return &cnr2qual[i];
+
+	return NULL; /* not found */
+}
+
+static void vidtv_demod_poll_snr_handler(struct work_struct *work)
+{
+	/*
+	 * periodically check the signal quality and eventually
+	 * lose the TS lock if it dips too low
+	 */
+	struct vidtv_demod_state *state;
+	const struct vidtv_demod_cnr_to_qual_s *cnr2qual = NULL;
+	struct vidtv_demod_config *config;
+	u16 snr = 0;
+
+	state  = container_of(work, struct vidtv_demod_state, poll_snr.work);
+	config = &state->config;
+
+	if (!state->frontend.ops.tuner_ops.get_rf_strength)
+		return;
+
+	state->frontend.ops.tuner_ops.get_rf_strength(&state->frontend, &snr);
+
+	cnr2qual = vidtv_match_cnr_s(&state->frontend);
+	if (!cnr2qual)
+		return;
+
+	if (snr < cnr2qual->cnr_ok) {
+		/* eventually lose the TS lock */
+		if (prandom_u32_max(100) < config->drop_tslock_prob_on_low_snr)
+			state->status = 0;
+	} else {
+		/* recover if the signal improves */
+		if (prandom_u32_max(100) <
+		    config->recover_tslock_prob_on_good_snr)
+			state->status = FE_HAS_SIGNAL  |
+					FE_HAS_CARRIER |
+					FE_HAS_VITERBI |
+					FE_HAS_SYNC    |
+					FE_HAS_LOCK;
+	}
+
+	schedule_delayed_work(&state->poll_snr,
+			      msecs_to_jiffies(POLL_THRD_TIME));
+}
+
+static int vidtv_demod_read_status(struct dvb_frontend *fe,
+				   enum fe_status *status)
+{
+	struct vidtv_demod_state *state = fe->demodulator_priv;
+
+	*status = state->status;
+
+	return 0;
+}
+
+static int vidtv_demod_read_ber(struct dvb_frontend *fe, u32 *ber)
+{
+	*ber = 0;
+	return 0;
+}
+
+static int vidtv_demod_read_signal_strength(struct dvb_frontend *fe,
+					    u16 *strength)
+{
+	*strength = 0;
+	return 0;
+}
+
+static int vidtv_demod_read_snr(struct dvb_frontend *fe, u16 *snr)
+{
+	*snr = 0;
+	return 0;
+}
+
+static int vidtv_demod_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks)
+{
+	*ucblocks = 0;
+	return 0;
+}
+
+/*
+ * NOTE:
+ * This is implemented here just to be used as an example for real
+ * demod drivers.
+ *
+ * Should only be implemented if it actually reads something from the hardware.
+ * Also, it should check for the locks, in order to avoid report wrong data
+ * to userspace.
+ */
+static int vidtv_demod_get_frontend(struct dvb_frontend *fe,
+				    struct dtv_frontend_properties *p)
+{
+	return 0;
+}
+
+static int vidtv_demod_set_frontend(struct dvb_frontend *fe)
+{
+	struct vidtv_demod_state *state            = fe->demodulator_priv;
+	const struct vidtv_demod_cnr_to_qual_s *cnr2qual = NULL;
+	u32    tuner_status                        = 0;
+
+	if (fe->ops.tuner_ops.set_params) {
+		fe->ops.tuner_ops.set_params(fe);
+
+		/* store the CNR returned by the tuner */
+		fe->ops.tuner_ops.get_rf_strength(fe, &state->tuner_cnr);
+
+		fe->ops.tuner_ops.get_status(fe, &tuner_status);
+		state->status = (state->tuner_cnr > 0) ?  FE_HAS_SIGNAL  |
+							  FE_HAS_CARRIER |
+							  FE_HAS_VITERBI |
+							  FE_HAS_SYNC    |
+							  FE_HAS_LOCK	 :
+							  0;
+		cnr2qual = vidtv_match_cnr_s(fe);
+
+		/* signal isn't good: might lose the lock eventually */
+		if (tuner_status == TUNER_STATUS_LOCKED &&
+		    state->tuner_cnr < cnr2qual->cnr_good) {
+			schedule_delayed_work(&state->poll_snr,
+					      msecs_to_jiffies(POLL_THRD_TIME));
+
+			state->poll_snr_thread_running = true;
+		}
+
+		if (fe->ops.i2c_gate_ctrl)
+			fe->ops.i2c_gate_ctrl(fe, 0);
+	}
+
+	return 0;
+}
+
+static int vidtv_demod_sleep(struct dvb_frontend *fe)
+{
+	struct vidtv_demod_state *state = fe->demodulator_priv;
+
+	if (state->poll_snr_thread_running) {
+		cancel_delayed_work_sync(&state->poll_snr);
+		state->poll_snr_thread_running = false;
+		state->poll_snr_thread_restart = true;
+	}
+	return 0;
+}
+
+static int vidtv_demod_init(struct dvb_frontend *fe)
+{
+	struct vidtv_demod_state *state = fe->demodulator_priv;
+	u32    tuner_status             = 0;
+
+	if (state->cold_start)
+		INIT_DELAYED_WORK(&state->poll_snr,
+				  &vidtv_demod_poll_snr_handler);
+
+	/*
+	 * At resume, start the snr poll thread only if it was suspended with
+	 * the thread running. Extra care should be taken here, as some tuner
+	 * status change might happen at resume time (for example, due to an
+	 * ioctl syscall to set_frontend, or due to a release syscall).
+	 */
+	fe->ops.tuner_ops.get_status(fe, &tuner_status);
+
+	if (tuner_status == TUNER_STATUS_LOCKED &&
+	    state->poll_snr_thread_restart) {
+		schedule_delayed_work(&state->poll_snr,
+				      msecs_to_jiffies(POLL_THRD_TIME));
+
+		state->poll_snr_thread_restart = false;
+	}
+
+	state->cold_start = false;
+	return 0;
+}
+
+/*
+ * NOTE:
+ * This is implemented here just to be used as an example for real
+ * demod drivers.
+ *
+ * Should only be implemented if the demod has support for DVB-S or DVB-S2
+ */
+static int vidtv_demod_set_tone(struct dvb_frontend *fe,
+				enum fe_sec_tone_mode tone)
+{
+	return 0;
+}
+
+/*
+ * NOTE:
+ * This is implemented here just to be used as an example for real
+ * demod drivers.
+ *
+ * Should only be implemented if the demod has support for DVB-S or DVB-S2
+ */
+static int vidtv_demod_set_voltage(struct dvb_frontend *fe,
+				   enum fe_sec_voltage voltage)
+{
+	return 0;
+}
+
+static void vidtv_demod_release(struct dvb_frontend *fe)
+{
+	struct vidtv_demod_state *state = fe->demodulator_priv;
+
+	if (state->poll_snr_thread_running)
+		cancel_delayed_work_sync(&state->poll_snr);
+
+	kfree(state);
+}
+
+static const struct dvb_frontend_ops vidtv_demod_ops = {
+	.delsys = {
+		SYS_DVBT,
+		SYS_DVBT2,
+		SYS_DVBC_ANNEX_A,
+		SYS_DVBS,
+		SYS_DVBS2,
+	},
+
+	.info = {
+		.name                   = "Dummy demod for DVB-T/T2/C/S/S2",
+		.frequency_min_hz       = 51 * MHz,
+		.frequency_max_hz       = 2150 * MHz,
+		.frequency_stepsize_hz  = 62500,
+		.frequency_tolerance_hz = 29500 * kHz,
+		.symbol_rate_min        = 1000000,
+		.symbol_rate_max        = 45000000,
+
+		.caps = FE_CAN_FEC_1_2 |
+			FE_CAN_FEC_2_3 |
+			FE_CAN_FEC_3_4 |
+			FE_CAN_FEC_4_5 |
+			FE_CAN_FEC_5_6 |
+			FE_CAN_FEC_6_7 |
+			FE_CAN_FEC_7_8 |
+			FE_CAN_FEC_8_9 |
+			FE_CAN_FEC_AUTO |
+			FE_CAN_QAM_16 |
+			FE_CAN_QAM_64 |
+			FE_CAN_QAM_32 |
+			FE_CAN_QAM_128 |
+			FE_CAN_QAM_256 |
+			FE_CAN_QAM_AUTO |
+			FE_CAN_QPSK |
+			FE_CAN_FEC_AUTO |
+			FE_CAN_INVERSION_AUTO |
+			FE_CAN_TRANSMISSION_MODE_AUTO |
+			FE_CAN_GUARD_INTERVAL_AUTO |
+			FE_CAN_HIERARCHY_AUTO,
+	},
+
+	.release = vidtv_demod_release,
+
+	.init  = vidtv_demod_init,
+	.sleep = vidtv_demod_sleep,
+
+	.set_frontend = vidtv_demod_set_frontend,
+	.get_frontend = vidtv_demod_get_frontend,
+
+	.read_status          = vidtv_demod_read_status,
+	.read_ber             = vidtv_demod_read_ber,
+	.read_signal_strength = vidtv_demod_read_signal_strength,
+	.read_snr             = vidtv_demod_read_snr,
+	.read_ucblocks        = vidtv_demod_read_ucblocks,
+
+	/* For DVB-S/S2 */
+	.set_voltage = vidtv_demod_set_voltage,
+	.set_tone    = vidtv_demod_set_tone,
+};
+
+static const struct i2c_device_id vidtv_demod_i2c_id_table[] = {
+	{"vidtv_demod", 0},
+	{}
+};
+MODULE_DEVICE_TABLE(i2c, vidtv_demod_i2c_id_table);
+
+static int vidtv_demod_i2c_probe(struct i2c_client *client,
+				 const struct i2c_device_id *id)
+{
+	struct vidtv_demod_state *state;
+
+	/* allocate memory for the internal state */
+	state = kzalloc(sizeof(*state), GFP_KERNEL);
+	if (!state)
+		return -ENOMEM;
+
+	/* create dvb_frontend */
+	memcpy(&state->frontend.ops,
+	       &vidtv_demod_ops,
+	       sizeof(struct dvb_frontend_ops));
+
+	state->frontend.demodulator_priv = state;
+	i2c_set_clientdata(client, state);
+
+	return 0;
+}
+
+static int vidtv_demod_i2c_remove(struct i2c_client *client)
+{
+	struct vidtv_demod_state *state = i2c_get_clientdata(client);
+
+	memset(&state->frontend.ops, 0, sizeof(struct dvb_frontend_ops));
+	state->frontend.demodulator_priv = NULL;
+	kfree(state);
+
+	return 0;
+}
+
+static struct i2c_driver vidtv_demod_i2c_driver = {
+	.driver = {
+		.name                = "vidtv_demod",
+		.suppress_bind_attrs = true,
+	},
+	.probe    = vidtv_demod_i2c_probe,
+	.remove   = vidtv_demod_i2c_remove,
+	.id_table = vidtv_demod_i2c_id_table,
+};
+
+module_i2c_driver(vidtv_demod_i2c_driver);
+
+MODULE_DESCRIPTION("Virtual DVB Demodulator Driver");
+MODULE_AUTHOR("Daniel W. S. Almeida");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/test-drivers/vidtv/vidtv_demod.h b/drivers/media/test-drivers/vidtv/vidtv_demod.h
new file mode 100644
index 0000000000000..b14957d9d4ea0
--- /dev/null
+++ b/drivers/media/test-drivers/vidtv/vidtv_demod.h
@@ -0,0 +1,41 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * The Virtual DTV test driver serves as a reference DVB driver and helps
+ * validate the existing APIs in the media subsystem. It can also aid
+ * developers working on userspace applications.
+ *
+ * Written by Daniel W. S. Almeida <dwlsalmeida@gmail.com>
+ * Based on the example driver written by Emard <emard@softhome.net>
+ */
+
+#ifndef VIDTV_DEMOD_H
+#define VIDTV_DEMOD_H
+
+#include <linux/dvb/frontend.h>
+#include <media/dvb_frontend.h>
+
+struct vidtv_demod_cnr_to_qual_s {
+	/* attempt to use the same values as libdvbv5 */
+	u32 modulation;
+	u32 fec;
+	u32 cnr_ok, cnr_good;
+};
+
+struct vidtv_demod_config {
+	/* probability of losing the lock due to low snr */
+	u8 drop_tslock_prob_on_low_snr;
+	/* probability of recovering when the signal improves */
+	u8 recover_tslock_prob_on_good_snr;
+};
+
+struct vidtv_demod_state {
+	struct dvb_frontend frontend;
+	struct vidtv_demod_config config;
+	struct delayed_work poll_snr;
+	enum fe_status status;
+	u16 tuner_cnr;
+	bool cold_start;
+	bool poll_snr_thread_running;
+	bool poll_snr_thread_restart;
+};
+#endif // VIDTV_DEMOD_H
-- 
2.26.2


^ permalink raw reply related	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2020-05-28 23:47 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-05-21 15:31 [RFC, WIP, v6 03/10] media: vidtv: implement a demodulator driver kbuild test robot
  -- strict thread matches above, loose matches on Subject: below --
2020-05-20  7:03 [RFC, WIP, v6 00/10] media: vidtv: implement a virtual DVB driver Daniel W. S. Almeida
2020-05-20  7:03 ` [RFC, WIP, v6 03/10] media: vidtv: implement a demodulator driver Daniel W. S. Almeida
2020-05-28 23:39   ` Shuah Khan

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.