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