1*3a137f81SMauro Carvalho Chehab // SPDX-License-Identifier: GPL-2.0-or-later 2*3a137f81SMauro Carvalho Chehab /* 3*3a137f81SMauro Carvalho Chehab * Driver for Dummy Frontend 4*3a137f81SMauro Carvalho Chehab * 5*3a137f81SMauro Carvalho Chehab * Written by Emard <emard@softhome.net> 6*3a137f81SMauro Carvalho Chehab */ 7*3a137f81SMauro Carvalho Chehab 8*3a137f81SMauro Carvalho Chehab #include <linux/module.h> 9*3a137f81SMauro Carvalho Chehab #include <linux/init.h> 10*3a137f81SMauro Carvalho Chehab #include <linux/string.h> 11*3a137f81SMauro Carvalho Chehab #include <linux/slab.h> 12*3a137f81SMauro Carvalho Chehab 13*3a137f81SMauro Carvalho Chehab #include <media/dvb_frontend.h> 14*3a137f81SMauro Carvalho Chehab #include "dvb_dummy_fe.h" 15*3a137f81SMauro Carvalho Chehab 16*3a137f81SMauro Carvalho Chehab 17*3a137f81SMauro Carvalho Chehab struct dvb_dummy_fe_state { 18*3a137f81SMauro Carvalho Chehab struct dvb_frontend frontend; 19*3a137f81SMauro Carvalho Chehab }; 20*3a137f81SMauro Carvalho Chehab 21*3a137f81SMauro Carvalho Chehab 22*3a137f81SMauro Carvalho Chehab static int dvb_dummy_fe_read_status(struct dvb_frontend *fe, 23*3a137f81SMauro Carvalho Chehab enum fe_status *status) 24*3a137f81SMauro Carvalho Chehab { 25*3a137f81SMauro Carvalho Chehab *status = FE_HAS_SIGNAL 26*3a137f81SMauro Carvalho Chehab | FE_HAS_CARRIER 27*3a137f81SMauro Carvalho Chehab | FE_HAS_VITERBI 28*3a137f81SMauro Carvalho Chehab | FE_HAS_SYNC 29*3a137f81SMauro Carvalho Chehab | FE_HAS_LOCK; 30*3a137f81SMauro Carvalho Chehab 31*3a137f81SMauro Carvalho Chehab return 0; 32*3a137f81SMauro Carvalho Chehab } 33*3a137f81SMauro Carvalho Chehab 34*3a137f81SMauro Carvalho Chehab static int dvb_dummy_fe_read_ber(struct dvb_frontend *fe, u32 *ber) 35*3a137f81SMauro Carvalho Chehab { 36*3a137f81SMauro Carvalho Chehab *ber = 0; 37*3a137f81SMauro Carvalho Chehab return 0; 38*3a137f81SMauro Carvalho Chehab } 39*3a137f81SMauro Carvalho Chehab 40*3a137f81SMauro Carvalho Chehab static int dvb_dummy_fe_read_signal_strength(struct dvb_frontend *fe, 41*3a137f81SMauro Carvalho Chehab u16 *strength) 42*3a137f81SMauro Carvalho Chehab { 43*3a137f81SMauro Carvalho Chehab *strength = 0; 44*3a137f81SMauro Carvalho Chehab return 0; 45*3a137f81SMauro Carvalho Chehab } 46*3a137f81SMauro Carvalho Chehab 47*3a137f81SMauro Carvalho Chehab static int dvb_dummy_fe_read_snr(struct dvb_frontend *fe, u16 *snr) 48*3a137f81SMauro Carvalho Chehab { 49*3a137f81SMauro Carvalho Chehab *snr = 0; 50*3a137f81SMauro Carvalho Chehab return 0; 51*3a137f81SMauro Carvalho Chehab } 52*3a137f81SMauro Carvalho Chehab 53*3a137f81SMauro Carvalho Chehab static int dvb_dummy_fe_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks) 54*3a137f81SMauro Carvalho Chehab { 55*3a137f81SMauro Carvalho Chehab *ucblocks = 0; 56*3a137f81SMauro Carvalho Chehab return 0; 57*3a137f81SMauro Carvalho Chehab } 58*3a137f81SMauro Carvalho Chehab 59*3a137f81SMauro Carvalho Chehab /* 60*3a137f81SMauro Carvalho Chehab * Should only be implemented if it actually reads something from the hardware. 61*3a137f81SMauro Carvalho Chehab * Also, it should check for the locks, in order to avoid report wrong data 62*3a137f81SMauro Carvalho Chehab * to userspace. 63*3a137f81SMauro Carvalho Chehab */ 64*3a137f81SMauro Carvalho Chehab static int dvb_dummy_fe_get_frontend(struct dvb_frontend *fe, 65*3a137f81SMauro Carvalho Chehab struct dtv_frontend_properties *p) 66*3a137f81SMauro Carvalho Chehab { 67*3a137f81SMauro Carvalho Chehab return 0; 68*3a137f81SMauro Carvalho Chehab } 69*3a137f81SMauro Carvalho Chehab 70*3a137f81SMauro Carvalho Chehab static int dvb_dummy_fe_set_frontend(struct dvb_frontend *fe) 71*3a137f81SMauro Carvalho Chehab { 72*3a137f81SMauro Carvalho Chehab if (fe->ops.tuner_ops.set_params) { 73*3a137f81SMauro Carvalho Chehab fe->ops.tuner_ops.set_params(fe); 74*3a137f81SMauro Carvalho Chehab if (fe->ops.i2c_gate_ctrl) 75*3a137f81SMauro Carvalho Chehab fe->ops.i2c_gate_ctrl(fe, 0); 76*3a137f81SMauro Carvalho Chehab } 77*3a137f81SMauro Carvalho Chehab 78*3a137f81SMauro Carvalho Chehab return 0; 79*3a137f81SMauro Carvalho Chehab } 80*3a137f81SMauro Carvalho Chehab 81*3a137f81SMauro Carvalho Chehab static int dvb_dummy_fe_sleep(struct dvb_frontend *fe) 82*3a137f81SMauro Carvalho Chehab { 83*3a137f81SMauro Carvalho Chehab return 0; 84*3a137f81SMauro Carvalho Chehab } 85*3a137f81SMauro Carvalho Chehab 86*3a137f81SMauro Carvalho Chehab static int dvb_dummy_fe_init(struct dvb_frontend *fe) 87*3a137f81SMauro Carvalho Chehab { 88*3a137f81SMauro Carvalho Chehab return 0; 89*3a137f81SMauro Carvalho Chehab } 90*3a137f81SMauro Carvalho Chehab 91*3a137f81SMauro Carvalho Chehab static int dvb_dummy_fe_set_tone(struct dvb_frontend *fe, 92*3a137f81SMauro Carvalho Chehab enum fe_sec_tone_mode tone) 93*3a137f81SMauro Carvalho Chehab { 94*3a137f81SMauro Carvalho Chehab return 0; 95*3a137f81SMauro Carvalho Chehab } 96*3a137f81SMauro Carvalho Chehab 97*3a137f81SMauro Carvalho Chehab static int dvb_dummy_fe_set_voltage(struct dvb_frontend *fe, 98*3a137f81SMauro Carvalho Chehab enum fe_sec_voltage voltage) 99*3a137f81SMauro Carvalho Chehab { 100*3a137f81SMauro Carvalho Chehab return 0; 101*3a137f81SMauro Carvalho Chehab } 102*3a137f81SMauro Carvalho Chehab 103*3a137f81SMauro Carvalho Chehab static void dvb_dummy_fe_release(struct dvb_frontend *fe) 104*3a137f81SMauro Carvalho Chehab { 105*3a137f81SMauro Carvalho Chehab struct dvb_dummy_fe_state *state = fe->demodulator_priv; 106*3a137f81SMauro Carvalho Chehab 107*3a137f81SMauro Carvalho Chehab kfree(state); 108*3a137f81SMauro Carvalho Chehab } 109*3a137f81SMauro Carvalho Chehab 110*3a137f81SMauro Carvalho Chehab static const struct dvb_frontend_ops dvb_dummy_fe_ofdm_ops; 111*3a137f81SMauro Carvalho Chehab 112*3a137f81SMauro Carvalho Chehab struct dvb_frontend *dvb_dummy_fe_ofdm_attach(void) 113*3a137f81SMauro Carvalho Chehab { 114*3a137f81SMauro Carvalho Chehab struct dvb_dummy_fe_state *state = NULL; 115*3a137f81SMauro Carvalho Chehab 116*3a137f81SMauro Carvalho Chehab /* allocate memory for the internal state */ 117*3a137f81SMauro Carvalho Chehab state = kzalloc(sizeof(struct dvb_dummy_fe_state), GFP_KERNEL); 118*3a137f81SMauro Carvalho Chehab if (!state) 119*3a137f81SMauro Carvalho Chehab return NULL; 120*3a137f81SMauro Carvalho Chehab 121*3a137f81SMauro Carvalho Chehab /* create dvb_frontend */ 122*3a137f81SMauro Carvalho Chehab memcpy(&state->frontend.ops, 123*3a137f81SMauro Carvalho Chehab &dvb_dummy_fe_ofdm_ops, 124*3a137f81SMauro Carvalho Chehab sizeof(struct dvb_frontend_ops)); 125*3a137f81SMauro Carvalho Chehab 126*3a137f81SMauro Carvalho Chehab state->frontend.demodulator_priv = state; 127*3a137f81SMauro Carvalho Chehab return &state->frontend; 128*3a137f81SMauro Carvalho Chehab } 129*3a137f81SMauro Carvalho Chehab EXPORT_SYMBOL(dvb_dummy_fe_ofdm_attach); 130*3a137f81SMauro Carvalho Chehab 131*3a137f81SMauro Carvalho Chehab static const struct dvb_frontend_ops dvb_dummy_fe_qpsk_ops; 132*3a137f81SMauro Carvalho Chehab 133*3a137f81SMauro Carvalho Chehab struct dvb_frontend *dvb_dummy_fe_qpsk_attach(void) 134*3a137f81SMauro Carvalho Chehab { 135*3a137f81SMauro Carvalho Chehab struct dvb_dummy_fe_state *state = NULL; 136*3a137f81SMauro Carvalho Chehab 137*3a137f81SMauro Carvalho Chehab /* allocate memory for the internal state */ 138*3a137f81SMauro Carvalho Chehab state = kzalloc(sizeof(struct dvb_dummy_fe_state), GFP_KERNEL); 139*3a137f81SMauro Carvalho Chehab if (!state) 140*3a137f81SMauro Carvalho Chehab return NULL; 141*3a137f81SMauro Carvalho Chehab 142*3a137f81SMauro Carvalho Chehab /* create dvb_frontend */ 143*3a137f81SMauro Carvalho Chehab memcpy(&state->frontend.ops, 144*3a137f81SMauro Carvalho Chehab &dvb_dummy_fe_qpsk_ops, 145*3a137f81SMauro Carvalho Chehab sizeof(struct dvb_frontend_ops)); 146*3a137f81SMauro Carvalho Chehab 147*3a137f81SMauro Carvalho Chehab state->frontend.demodulator_priv = state; 148*3a137f81SMauro Carvalho Chehab return &state->frontend; 149*3a137f81SMauro Carvalho Chehab } 150*3a137f81SMauro Carvalho Chehab EXPORT_SYMBOL(dvb_dummy_fe_qpsk_attach); 151*3a137f81SMauro Carvalho Chehab 152*3a137f81SMauro Carvalho Chehab static const struct dvb_frontend_ops dvb_dummy_fe_qam_ops; 153*3a137f81SMauro Carvalho Chehab 154*3a137f81SMauro Carvalho Chehab struct dvb_frontend *dvb_dummy_fe_qam_attach(void) 155*3a137f81SMauro Carvalho Chehab { 156*3a137f81SMauro Carvalho Chehab struct dvb_dummy_fe_state *state = NULL; 157*3a137f81SMauro Carvalho Chehab 158*3a137f81SMauro Carvalho Chehab /* allocate memory for the internal state */ 159*3a137f81SMauro Carvalho Chehab state = kzalloc(sizeof(struct dvb_dummy_fe_state), GFP_KERNEL); 160*3a137f81SMauro Carvalho Chehab if (!state) 161*3a137f81SMauro Carvalho Chehab return NULL; 162*3a137f81SMauro Carvalho Chehab 163*3a137f81SMauro Carvalho Chehab /* create dvb_frontend */ 164*3a137f81SMauro Carvalho Chehab memcpy(&state->frontend.ops, 165*3a137f81SMauro Carvalho Chehab &dvb_dummy_fe_qam_ops, 166*3a137f81SMauro Carvalho Chehab sizeof(struct dvb_frontend_ops)); 167*3a137f81SMauro Carvalho Chehab 168*3a137f81SMauro Carvalho Chehab state->frontend.demodulator_priv = state; 169*3a137f81SMauro Carvalho Chehab return &state->frontend; 170*3a137f81SMauro Carvalho Chehab } 171*3a137f81SMauro Carvalho Chehab EXPORT_SYMBOL(dvb_dummy_fe_qam_attach); 172*3a137f81SMauro Carvalho Chehab 173*3a137f81SMauro Carvalho Chehab static const struct dvb_frontend_ops dvb_dummy_fe_ofdm_ops = { 174*3a137f81SMauro Carvalho Chehab .delsys = { SYS_DVBT }, 175*3a137f81SMauro Carvalho Chehab .info = { 176*3a137f81SMauro Carvalho Chehab .name = "Dummy DVB-T", 177*3a137f81SMauro Carvalho Chehab .frequency_min_hz = 0, 178*3a137f81SMauro Carvalho Chehab .frequency_max_hz = 863250 * kHz, 179*3a137f81SMauro Carvalho Chehab .frequency_stepsize_hz = 62500, 180*3a137f81SMauro Carvalho Chehab .caps = FE_CAN_FEC_1_2 | 181*3a137f81SMauro Carvalho Chehab FE_CAN_FEC_2_3 | 182*3a137f81SMauro Carvalho Chehab FE_CAN_FEC_3_4 | 183*3a137f81SMauro Carvalho Chehab FE_CAN_FEC_4_5 | 184*3a137f81SMauro Carvalho Chehab FE_CAN_FEC_5_6 | 185*3a137f81SMauro Carvalho Chehab FE_CAN_FEC_6_7 | 186*3a137f81SMauro Carvalho Chehab FE_CAN_FEC_7_8 | 187*3a137f81SMauro Carvalho Chehab FE_CAN_FEC_8_9 | 188*3a137f81SMauro Carvalho Chehab FE_CAN_FEC_AUTO | 189*3a137f81SMauro Carvalho Chehab FE_CAN_QAM_16 | 190*3a137f81SMauro Carvalho Chehab FE_CAN_QAM_64 | 191*3a137f81SMauro Carvalho Chehab FE_CAN_QAM_AUTO | 192*3a137f81SMauro Carvalho Chehab FE_CAN_TRANSMISSION_MODE_AUTO | 193*3a137f81SMauro Carvalho Chehab FE_CAN_GUARD_INTERVAL_AUTO | 194*3a137f81SMauro Carvalho Chehab FE_CAN_HIERARCHY_AUTO, 195*3a137f81SMauro Carvalho Chehab }, 196*3a137f81SMauro Carvalho Chehab 197*3a137f81SMauro Carvalho Chehab .release = dvb_dummy_fe_release, 198*3a137f81SMauro Carvalho Chehab 199*3a137f81SMauro Carvalho Chehab .init = dvb_dummy_fe_init, 200*3a137f81SMauro Carvalho Chehab .sleep = dvb_dummy_fe_sleep, 201*3a137f81SMauro Carvalho Chehab 202*3a137f81SMauro Carvalho Chehab .set_frontend = dvb_dummy_fe_set_frontend, 203*3a137f81SMauro Carvalho Chehab .get_frontend = dvb_dummy_fe_get_frontend, 204*3a137f81SMauro Carvalho Chehab 205*3a137f81SMauro Carvalho Chehab .read_status = dvb_dummy_fe_read_status, 206*3a137f81SMauro Carvalho Chehab .read_ber = dvb_dummy_fe_read_ber, 207*3a137f81SMauro Carvalho Chehab .read_signal_strength = dvb_dummy_fe_read_signal_strength, 208*3a137f81SMauro Carvalho Chehab .read_snr = dvb_dummy_fe_read_snr, 209*3a137f81SMauro Carvalho Chehab .read_ucblocks = dvb_dummy_fe_read_ucblocks, 210*3a137f81SMauro Carvalho Chehab }; 211*3a137f81SMauro Carvalho Chehab 212*3a137f81SMauro Carvalho Chehab static const struct dvb_frontend_ops dvb_dummy_fe_qam_ops = { 213*3a137f81SMauro Carvalho Chehab .delsys = { SYS_DVBC_ANNEX_A }, 214*3a137f81SMauro Carvalho Chehab .info = { 215*3a137f81SMauro Carvalho Chehab .name = "Dummy DVB-C", 216*3a137f81SMauro Carvalho Chehab .frequency_min_hz = 51 * MHz, 217*3a137f81SMauro Carvalho Chehab .frequency_max_hz = 858 * MHz, 218*3a137f81SMauro Carvalho Chehab .frequency_stepsize_hz = 62500, 219*3a137f81SMauro Carvalho Chehab /* symbol_rate_min: SACLK/64 == (XIN/2)/64 */ 220*3a137f81SMauro Carvalho Chehab .symbol_rate_min = (57840000 / 2) / 64, 221*3a137f81SMauro Carvalho Chehab .symbol_rate_max = (57840000 / 2) / 4, /* SACLK/4 */ 222*3a137f81SMauro Carvalho Chehab .caps = FE_CAN_QAM_16 | 223*3a137f81SMauro Carvalho Chehab FE_CAN_QAM_32 | 224*3a137f81SMauro Carvalho Chehab FE_CAN_QAM_64 | 225*3a137f81SMauro Carvalho Chehab FE_CAN_QAM_128 | 226*3a137f81SMauro Carvalho Chehab FE_CAN_QAM_256 | 227*3a137f81SMauro Carvalho Chehab FE_CAN_FEC_AUTO | 228*3a137f81SMauro Carvalho Chehab FE_CAN_INVERSION_AUTO 229*3a137f81SMauro Carvalho Chehab }, 230*3a137f81SMauro Carvalho Chehab 231*3a137f81SMauro Carvalho Chehab .release = dvb_dummy_fe_release, 232*3a137f81SMauro Carvalho Chehab 233*3a137f81SMauro Carvalho Chehab .init = dvb_dummy_fe_init, 234*3a137f81SMauro Carvalho Chehab .sleep = dvb_dummy_fe_sleep, 235*3a137f81SMauro Carvalho Chehab 236*3a137f81SMauro Carvalho Chehab .set_frontend = dvb_dummy_fe_set_frontend, 237*3a137f81SMauro Carvalho Chehab .get_frontend = dvb_dummy_fe_get_frontend, 238*3a137f81SMauro Carvalho Chehab 239*3a137f81SMauro Carvalho Chehab .read_status = dvb_dummy_fe_read_status, 240*3a137f81SMauro Carvalho Chehab .read_ber = dvb_dummy_fe_read_ber, 241*3a137f81SMauro Carvalho Chehab .read_signal_strength = dvb_dummy_fe_read_signal_strength, 242*3a137f81SMauro Carvalho Chehab .read_snr = dvb_dummy_fe_read_snr, 243*3a137f81SMauro Carvalho Chehab .read_ucblocks = dvb_dummy_fe_read_ucblocks, 244*3a137f81SMauro Carvalho Chehab }; 245*3a137f81SMauro Carvalho Chehab 246*3a137f81SMauro Carvalho Chehab static const struct dvb_frontend_ops dvb_dummy_fe_qpsk_ops = { 247*3a137f81SMauro Carvalho Chehab .delsys = { SYS_DVBS }, 248*3a137f81SMauro Carvalho Chehab .info = { 249*3a137f81SMauro Carvalho Chehab .name = "Dummy DVB-S", 250*3a137f81SMauro Carvalho Chehab .frequency_min_hz = 950 * MHz, 251*3a137f81SMauro Carvalho Chehab .frequency_max_hz = 2150 * MHz, 252*3a137f81SMauro Carvalho Chehab .frequency_stepsize_hz = 250 * kHz, 253*3a137f81SMauro Carvalho Chehab .frequency_tolerance_hz = 29500 * kHz, 254*3a137f81SMauro Carvalho Chehab .symbol_rate_min = 1000000, 255*3a137f81SMauro Carvalho Chehab .symbol_rate_max = 45000000, 256*3a137f81SMauro Carvalho Chehab .caps = FE_CAN_INVERSION_AUTO | 257*3a137f81SMauro Carvalho Chehab FE_CAN_FEC_1_2 | 258*3a137f81SMauro Carvalho Chehab FE_CAN_FEC_2_3 | 259*3a137f81SMauro Carvalho Chehab FE_CAN_FEC_3_4 | 260*3a137f81SMauro Carvalho Chehab FE_CAN_FEC_5_6 | 261*3a137f81SMauro Carvalho Chehab FE_CAN_FEC_7_8 | 262*3a137f81SMauro Carvalho Chehab FE_CAN_FEC_AUTO | 263*3a137f81SMauro Carvalho Chehab FE_CAN_QPSK 264*3a137f81SMauro Carvalho Chehab }, 265*3a137f81SMauro Carvalho Chehab 266*3a137f81SMauro Carvalho Chehab .release = dvb_dummy_fe_release, 267*3a137f81SMauro Carvalho Chehab 268*3a137f81SMauro Carvalho Chehab .init = dvb_dummy_fe_init, 269*3a137f81SMauro Carvalho Chehab .sleep = dvb_dummy_fe_sleep, 270*3a137f81SMauro Carvalho Chehab 271*3a137f81SMauro Carvalho Chehab .set_frontend = dvb_dummy_fe_set_frontend, 272*3a137f81SMauro Carvalho Chehab .get_frontend = dvb_dummy_fe_get_frontend, 273*3a137f81SMauro Carvalho Chehab 274*3a137f81SMauro Carvalho Chehab .read_status = dvb_dummy_fe_read_status, 275*3a137f81SMauro Carvalho Chehab .read_ber = dvb_dummy_fe_read_ber, 276*3a137f81SMauro Carvalho Chehab .read_signal_strength = dvb_dummy_fe_read_signal_strength, 277*3a137f81SMauro Carvalho Chehab .read_snr = dvb_dummy_fe_read_snr, 278*3a137f81SMauro Carvalho Chehab .read_ucblocks = dvb_dummy_fe_read_ucblocks, 279*3a137f81SMauro Carvalho Chehab 280*3a137f81SMauro Carvalho Chehab .set_voltage = dvb_dummy_fe_set_voltage, 281*3a137f81SMauro Carvalho Chehab .set_tone = dvb_dummy_fe_set_tone, 282*3a137f81SMauro Carvalho Chehab }; 283*3a137f81SMauro Carvalho Chehab 284*3a137f81SMauro Carvalho Chehab MODULE_DESCRIPTION("DVB DUMMY Frontend"); 285*3a137f81SMauro Carvalho Chehab MODULE_AUTHOR("Emard"); 286*3a137f81SMauro Carvalho Chehab MODULE_LICENSE("GPL"); 287