18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * Driver for Dummy Frontend 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * Written by Emard <emard@softhome.net> 68c2ecf20Sopenharmony_ci */ 78c2ecf20Sopenharmony_ci 88c2ecf20Sopenharmony_ci#include <linux/module.h> 98c2ecf20Sopenharmony_ci#include <linux/init.h> 108c2ecf20Sopenharmony_ci#include <linux/string.h> 118c2ecf20Sopenharmony_ci#include <linux/slab.h> 128c2ecf20Sopenharmony_ci 138c2ecf20Sopenharmony_ci#include <media/dvb_frontend.h> 148c2ecf20Sopenharmony_ci#include "dvb_dummy_fe.h" 158c2ecf20Sopenharmony_ci 168c2ecf20Sopenharmony_ci 178c2ecf20Sopenharmony_cistruct dvb_dummy_fe_state { 188c2ecf20Sopenharmony_ci struct dvb_frontend frontend; 198c2ecf20Sopenharmony_ci}; 208c2ecf20Sopenharmony_ci 218c2ecf20Sopenharmony_ci 228c2ecf20Sopenharmony_cistatic int dvb_dummy_fe_read_status(struct dvb_frontend *fe, 238c2ecf20Sopenharmony_ci enum fe_status *status) 248c2ecf20Sopenharmony_ci{ 258c2ecf20Sopenharmony_ci *status = FE_HAS_SIGNAL 268c2ecf20Sopenharmony_ci | FE_HAS_CARRIER 278c2ecf20Sopenharmony_ci | FE_HAS_VITERBI 288c2ecf20Sopenharmony_ci | FE_HAS_SYNC 298c2ecf20Sopenharmony_ci | FE_HAS_LOCK; 308c2ecf20Sopenharmony_ci 318c2ecf20Sopenharmony_ci return 0; 328c2ecf20Sopenharmony_ci} 338c2ecf20Sopenharmony_ci 348c2ecf20Sopenharmony_cistatic int dvb_dummy_fe_read_ber(struct dvb_frontend *fe, u32 *ber) 358c2ecf20Sopenharmony_ci{ 368c2ecf20Sopenharmony_ci *ber = 0; 378c2ecf20Sopenharmony_ci return 0; 388c2ecf20Sopenharmony_ci} 398c2ecf20Sopenharmony_ci 408c2ecf20Sopenharmony_cistatic int dvb_dummy_fe_read_signal_strength(struct dvb_frontend *fe, 418c2ecf20Sopenharmony_ci u16 *strength) 428c2ecf20Sopenharmony_ci{ 438c2ecf20Sopenharmony_ci *strength = 0; 448c2ecf20Sopenharmony_ci return 0; 458c2ecf20Sopenharmony_ci} 468c2ecf20Sopenharmony_ci 478c2ecf20Sopenharmony_cistatic int dvb_dummy_fe_read_snr(struct dvb_frontend *fe, u16 *snr) 488c2ecf20Sopenharmony_ci{ 498c2ecf20Sopenharmony_ci *snr = 0; 508c2ecf20Sopenharmony_ci return 0; 518c2ecf20Sopenharmony_ci} 528c2ecf20Sopenharmony_ci 538c2ecf20Sopenharmony_cistatic int dvb_dummy_fe_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks) 548c2ecf20Sopenharmony_ci{ 558c2ecf20Sopenharmony_ci *ucblocks = 0; 568c2ecf20Sopenharmony_ci return 0; 578c2ecf20Sopenharmony_ci} 588c2ecf20Sopenharmony_ci 598c2ecf20Sopenharmony_ci/* 608c2ecf20Sopenharmony_ci * Should only be implemented if it actually reads something from the hardware. 618c2ecf20Sopenharmony_ci * Also, it should check for the locks, in order to avoid report wrong data 628c2ecf20Sopenharmony_ci * to userspace. 638c2ecf20Sopenharmony_ci */ 648c2ecf20Sopenharmony_cistatic int dvb_dummy_fe_get_frontend(struct dvb_frontend *fe, 658c2ecf20Sopenharmony_ci struct dtv_frontend_properties *p) 668c2ecf20Sopenharmony_ci{ 678c2ecf20Sopenharmony_ci return 0; 688c2ecf20Sopenharmony_ci} 698c2ecf20Sopenharmony_ci 708c2ecf20Sopenharmony_cistatic int dvb_dummy_fe_set_frontend(struct dvb_frontend *fe) 718c2ecf20Sopenharmony_ci{ 728c2ecf20Sopenharmony_ci if (fe->ops.tuner_ops.set_params) { 738c2ecf20Sopenharmony_ci fe->ops.tuner_ops.set_params(fe); 748c2ecf20Sopenharmony_ci if (fe->ops.i2c_gate_ctrl) 758c2ecf20Sopenharmony_ci fe->ops.i2c_gate_ctrl(fe, 0); 768c2ecf20Sopenharmony_ci } 778c2ecf20Sopenharmony_ci 788c2ecf20Sopenharmony_ci return 0; 798c2ecf20Sopenharmony_ci} 808c2ecf20Sopenharmony_ci 818c2ecf20Sopenharmony_cistatic int dvb_dummy_fe_sleep(struct dvb_frontend *fe) 828c2ecf20Sopenharmony_ci{ 838c2ecf20Sopenharmony_ci return 0; 848c2ecf20Sopenharmony_ci} 858c2ecf20Sopenharmony_ci 868c2ecf20Sopenharmony_cistatic int dvb_dummy_fe_init(struct dvb_frontend *fe) 878c2ecf20Sopenharmony_ci{ 888c2ecf20Sopenharmony_ci return 0; 898c2ecf20Sopenharmony_ci} 908c2ecf20Sopenharmony_ci 918c2ecf20Sopenharmony_cistatic int dvb_dummy_fe_set_tone(struct dvb_frontend *fe, 928c2ecf20Sopenharmony_ci enum fe_sec_tone_mode tone) 938c2ecf20Sopenharmony_ci{ 948c2ecf20Sopenharmony_ci return 0; 958c2ecf20Sopenharmony_ci} 968c2ecf20Sopenharmony_ci 978c2ecf20Sopenharmony_cistatic int dvb_dummy_fe_set_voltage(struct dvb_frontend *fe, 988c2ecf20Sopenharmony_ci enum fe_sec_voltage voltage) 998c2ecf20Sopenharmony_ci{ 1008c2ecf20Sopenharmony_ci return 0; 1018c2ecf20Sopenharmony_ci} 1028c2ecf20Sopenharmony_ci 1038c2ecf20Sopenharmony_cistatic void dvb_dummy_fe_release(struct dvb_frontend *fe) 1048c2ecf20Sopenharmony_ci{ 1058c2ecf20Sopenharmony_ci struct dvb_dummy_fe_state *state = fe->demodulator_priv; 1068c2ecf20Sopenharmony_ci 1078c2ecf20Sopenharmony_ci kfree(state); 1088c2ecf20Sopenharmony_ci} 1098c2ecf20Sopenharmony_ci 1108c2ecf20Sopenharmony_cistatic const struct dvb_frontend_ops dvb_dummy_fe_ofdm_ops; 1118c2ecf20Sopenharmony_ci 1128c2ecf20Sopenharmony_cistruct dvb_frontend *dvb_dummy_fe_ofdm_attach(void) 1138c2ecf20Sopenharmony_ci{ 1148c2ecf20Sopenharmony_ci struct dvb_dummy_fe_state *state = NULL; 1158c2ecf20Sopenharmony_ci 1168c2ecf20Sopenharmony_ci /* allocate memory for the internal state */ 1178c2ecf20Sopenharmony_ci state = kzalloc(sizeof(struct dvb_dummy_fe_state), GFP_KERNEL); 1188c2ecf20Sopenharmony_ci if (!state) 1198c2ecf20Sopenharmony_ci return NULL; 1208c2ecf20Sopenharmony_ci 1218c2ecf20Sopenharmony_ci /* create dvb_frontend */ 1228c2ecf20Sopenharmony_ci memcpy(&state->frontend.ops, 1238c2ecf20Sopenharmony_ci &dvb_dummy_fe_ofdm_ops, 1248c2ecf20Sopenharmony_ci sizeof(struct dvb_frontend_ops)); 1258c2ecf20Sopenharmony_ci 1268c2ecf20Sopenharmony_ci state->frontend.demodulator_priv = state; 1278c2ecf20Sopenharmony_ci return &state->frontend; 1288c2ecf20Sopenharmony_ci} 1298c2ecf20Sopenharmony_ciEXPORT_SYMBOL(dvb_dummy_fe_ofdm_attach); 1308c2ecf20Sopenharmony_ci 1318c2ecf20Sopenharmony_cistatic const struct dvb_frontend_ops dvb_dummy_fe_qpsk_ops; 1328c2ecf20Sopenharmony_ci 1338c2ecf20Sopenharmony_cistruct dvb_frontend *dvb_dummy_fe_qpsk_attach(void) 1348c2ecf20Sopenharmony_ci{ 1358c2ecf20Sopenharmony_ci struct dvb_dummy_fe_state *state = NULL; 1368c2ecf20Sopenharmony_ci 1378c2ecf20Sopenharmony_ci /* allocate memory for the internal state */ 1388c2ecf20Sopenharmony_ci state = kzalloc(sizeof(struct dvb_dummy_fe_state), GFP_KERNEL); 1398c2ecf20Sopenharmony_ci if (!state) 1408c2ecf20Sopenharmony_ci return NULL; 1418c2ecf20Sopenharmony_ci 1428c2ecf20Sopenharmony_ci /* create dvb_frontend */ 1438c2ecf20Sopenharmony_ci memcpy(&state->frontend.ops, 1448c2ecf20Sopenharmony_ci &dvb_dummy_fe_qpsk_ops, 1458c2ecf20Sopenharmony_ci sizeof(struct dvb_frontend_ops)); 1468c2ecf20Sopenharmony_ci 1478c2ecf20Sopenharmony_ci state->frontend.demodulator_priv = state; 1488c2ecf20Sopenharmony_ci return &state->frontend; 1498c2ecf20Sopenharmony_ci} 1508c2ecf20Sopenharmony_ciEXPORT_SYMBOL(dvb_dummy_fe_qpsk_attach); 1518c2ecf20Sopenharmony_ci 1528c2ecf20Sopenharmony_cistatic const struct dvb_frontend_ops dvb_dummy_fe_qam_ops; 1538c2ecf20Sopenharmony_ci 1548c2ecf20Sopenharmony_cistruct dvb_frontend *dvb_dummy_fe_qam_attach(void) 1558c2ecf20Sopenharmony_ci{ 1568c2ecf20Sopenharmony_ci struct dvb_dummy_fe_state *state = NULL; 1578c2ecf20Sopenharmony_ci 1588c2ecf20Sopenharmony_ci /* allocate memory for the internal state */ 1598c2ecf20Sopenharmony_ci state = kzalloc(sizeof(struct dvb_dummy_fe_state), GFP_KERNEL); 1608c2ecf20Sopenharmony_ci if (!state) 1618c2ecf20Sopenharmony_ci return NULL; 1628c2ecf20Sopenharmony_ci 1638c2ecf20Sopenharmony_ci /* create dvb_frontend */ 1648c2ecf20Sopenharmony_ci memcpy(&state->frontend.ops, 1658c2ecf20Sopenharmony_ci &dvb_dummy_fe_qam_ops, 1668c2ecf20Sopenharmony_ci sizeof(struct dvb_frontend_ops)); 1678c2ecf20Sopenharmony_ci 1688c2ecf20Sopenharmony_ci state->frontend.demodulator_priv = state; 1698c2ecf20Sopenharmony_ci return &state->frontend; 1708c2ecf20Sopenharmony_ci} 1718c2ecf20Sopenharmony_ciEXPORT_SYMBOL(dvb_dummy_fe_qam_attach); 1728c2ecf20Sopenharmony_ci 1738c2ecf20Sopenharmony_cistatic const struct dvb_frontend_ops dvb_dummy_fe_ofdm_ops = { 1748c2ecf20Sopenharmony_ci .delsys = { SYS_DVBT }, 1758c2ecf20Sopenharmony_ci .info = { 1768c2ecf20Sopenharmony_ci .name = "Dummy DVB-T", 1778c2ecf20Sopenharmony_ci .frequency_min_hz = 0, 1788c2ecf20Sopenharmony_ci .frequency_max_hz = 863250 * kHz, 1798c2ecf20Sopenharmony_ci .frequency_stepsize_hz = 62500, 1808c2ecf20Sopenharmony_ci .caps = FE_CAN_FEC_1_2 | 1818c2ecf20Sopenharmony_ci FE_CAN_FEC_2_3 | 1828c2ecf20Sopenharmony_ci FE_CAN_FEC_3_4 | 1838c2ecf20Sopenharmony_ci FE_CAN_FEC_4_5 | 1848c2ecf20Sopenharmony_ci FE_CAN_FEC_5_6 | 1858c2ecf20Sopenharmony_ci FE_CAN_FEC_6_7 | 1868c2ecf20Sopenharmony_ci FE_CAN_FEC_7_8 | 1878c2ecf20Sopenharmony_ci FE_CAN_FEC_8_9 | 1888c2ecf20Sopenharmony_ci FE_CAN_FEC_AUTO | 1898c2ecf20Sopenharmony_ci FE_CAN_QAM_16 | 1908c2ecf20Sopenharmony_ci FE_CAN_QAM_64 | 1918c2ecf20Sopenharmony_ci FE_CAN_QAM_AUTO | 1928c2ecf20Sopenharmony_ci FE_CAN_TRANSMISSION_MODE_AUTO | 1938c2ecf20Sopenharmony_ci FE_CAN_GUARD_INTERVAL_AUTO | 1948c2ecf20Sopenharmony_ci FE_CAN_HIERARCHY_AUTO, 1958c2ecf20Sopenharmony_ci }, 1968c2ecf20Sopenharmony_ci 1978c2ecf20Sopenharmony_ci .release = dvb_dummy_fe_release, 1988c2ecf20Sopenharmony_ci 1998c2ecf20Sopenharmony_ci .init = dvb_dummy_fe_init, 2008c2ecf20Sopenharmony_ci .sleep = dvb_dummy_fe_sleep, 2018c2ecf20Sopenharmony_ci 2028c2ecf20Sopenharmony_ci .set_frontend = dvb_dummy_fe_set_frontend, 2038c2ecf20Sopenharmony_ci .get_frontend = dvb_dummy_fe_get_frontend, 2048c2ecf20Sopenharmony_ci 2058c2ecf20Sopenharmony_ci .read_status = dvb_dummy_fe_read_status, 2068c2ecf20Sopenharmony_ci .read_ber = dvb_dummy_fe_read_ber, 2078c2ecf20Sopenharmony_ci .read_signal_strength = dvb_dummy_fe_read_signal_strength, 2088c2ecf20Sopenharmony_ci .read_snr = dvb_dummy_fe_read_snr, 2098c2ecf20Sopenharmony_ci .read_ucblocks = dvb_dummy_fe_read_ucblocks, 2108c2ecf20Sopenharmony_ci}; 2118c2ecf20Sopenharmony_ci 2128c2ecf20Sopenharmony_cistatic const struct dvb_frontend_ops dvb_dummy_fe_qam_ops = { 2138c2ecf20Sopenharmony_ci .delsys = { SYS_DVBC_ANNEX_A }, 2148c2ecf20Sopenharmony_ci .info = { 2158c2ecf20Sopenharmony_ci .name = "Dummy DVB-C", 2168c2ecf20Sopenharmony_ci .frequency_min_hz = 51 * MHz, 2178c2ecf20Sopenharmony_ci .frequency_max_hz = 858 * MHz, 2188c2ecf20Sopenharmony_ci .frequency_stepsize_hz = 62500, 2198c2ecf20Sopenharmony_ci /* symbol_rate_min: SACLK/64 == (XIN/2)/64 */ 2208c2ecf20Sopenharmony_ci .symbol_rate_min = (57840000 / 2) / 64, 2218c2ecf20Sopenharmony_ci .symbol_rate_max = (57840000 / 2) / 4, /* SACLK/4 */ 2228c2ecf20Sopenharmony_ci .caps = FE_CAN_QAM_16 | 2238c2ecf20Sopenharmony_ci FE_CAN_QAM_32 | 2248c2ecf20Sopenharmony_ci FE_CAN_QAM_64 | 2258c2ecf20Sopenharmony_ci FE_CAN_QAM_128 | 2268c2ecf20Sopenharmony_ci FE_CAN_QAM_256 | 2278c2ecf20Sopenharmony_ci FE_CAN_FEC_AUTO | 2288c2ecf20Sopenharmony_ci FE_CAN_INVERSION_AUTO 2298c2ecf20Sopenharmony_ci }, 2308c2ecf20Sopenharmony_ci 2318c2ecf20Sopenharmony_ci .release = dvb_dummy_fe_release, 2328c2ecf20Sopenharmony_ci 2338c2ecf20Sopenharmony_ci .init = dvb_dummy_fe_init, 2348c2ecf20Sopenharmony_ci .sleep = dvb_dummy_fe_sleep, 2358c2ecf20Sopenharmony_ci 2368c2ecf20Sopenharmony_ci .set_frontend = dvb_dummy_fe_set_frontend, 2378c2ecf20Sopenharmony_ci .get_frontend = dvb_dummy_fe_get_frontend, 2388c2ecf20Sopenharmony_ci 2398c2ecf20Sopenharmony_ci .read_status = dvb_dummy_fe_read_status, 2408c2ecf20Sopenharmony_ci .read_ber = dvb_dummy_fe_read_ber, 2418c2ecf20Sopenharmony_ci .read_signal_strength = dvb_dummy_fe_read_signal_strength, 2428c2ecf20Sopenharmony_ci .read_snr = dvb_dummy_fe_read_snr, 2438c2ecf20Sopenharmony_ci .read_ucblocks = dvb_dummy_fe_read_ucblocks, 2448c2ecf20Sopenharmony_ci}; 2458c2ecf20Sopenharmony_ci 2468c2ecf20Sopenharmony_cistatic const struct dvb_frontend_ops dvb_dummy_fe_qpsk_ops = { 2478c2ecf20Sopenharmony_ci .delsys = { SYS_DVBS }, 2488c2ecf20Sopenharmony_ci .info = { 2498c2ecf20Sopenharmony_ci .name = "Dummy DVB-S", 2508c2ecf20Sopenharmony_ci .frequency_min_hz = 950 * MHz, 2518c2ecf20Sopenharmony_ci .frequency_max_hz = 2150 * MHz, 2528c2ecf20Sopenharmony_ci .frequency_stepsize_hz = 250 * kHz, 2538c2ecf20Sopenharmony_ci .frequency_tolerance_hz = 29500 * kHz, 2548c2ecf20Sopenharmony_ci .symbol_rate_min = 1000000, 2558c2ecf20Sopenharmony_ci .symbol_rate_max = 45000000, 2568c2ecf20Sopenharmony_ci .caps = FE_CAN_INVERSION_AUTO | 2578c2ecf20Sopenharmony_ci FE_CAN_FEC_1_2 | 2588c2ecf20Sopenharmony_ci FE_CAN_FEC_2_3 | 2598c2ecf20Sopenharmony_ci FE_CAN_FEC_3_4 | 2608c2ecf20Sopenharmony_ci FE_CAN_FEC_5_6 | 2618c2ecf20Sopenharmony_ci FE_CAN_FEC_7_8 | 2628c2ecf20Sopenharmony_ci FE_CAN_FEC_AUTO | 2638c2ecf20Sopenharmony_ci FE_CAN_QPSK 2648c2ecf20Sopenharmony_ci }, 2658c2ecf20Sopenharmony_ci 2668c2ecf20Sopenharmony_ci .release = dvb_dummy_fe_release, 2678c2ecf20Sopenharmony_ci 2688c2ecf20Sopenharmony_ci .init = dvb_dummy_fe_init, 2698c2ecf20Sopenharmony_ci .sleep = dvb_dummy_fe_sleep, 2708c2ecf20Sopenharmony_ci 2718c2ecf20Sopenharmony_ci .set_frontend = dvb_dummy_fe_set_frontend, 2728c2ecf20Sopenharmony_ci .get_frontend = dvb_dummy_fe_get_frontend, 2738c2ecf20Sopenharmony_ci 2748c2ecf20Sopenharmony_ci .read_status = dvb_dummy_fe_read_status, 2758c2ecf20Sopenharmony_ci .read_ber = dvb_dummy_fe_read_ber, 2768c2ecf20Sopenharmony_ci .read_signal_strength = dvb_dummy_fe_read_signal_strength, 2778c2ecf20Sopenharmony_ci .read_snr = dvb_dummy_fe_read_snr, 2788c2ecf20Sopenharmony_ci .read_ucblocks = dvb_dummy_fe_read_ucblocks, 2798c2ecf20Sopenharmony_ci 2808c2ecf20Sopenharmony_ci .set_voltage = dvb_dummy_fe_set_voltage, 2818c2ecf20Sopenharmony_ci .set_tone = dvb_dummy_fe_set_tone, 2828c2ecf20Sopenharmony_ci}; 2838c2ecf20Sopenharmony_ci 2848c2ecf20Sopenharmony_ciMODULE_DESCRIPTION("DVB DUMMY Frontend"); 2858c2ecf20Sopenharmony_ciMODULE_AUTHOR("Emard"); 2868c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL"); 287