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 "ddbridge-dummy-fe.h" 158c2ecf20Sopenharmony_ci 168c2ecf20Sopenharmony_cistruct ddbridge_dummy_fe_state { 178c2ecf20Sopenharmony_ci struct dvb_frontend frontend; 188c2ecf20Sopenharmony_ci}; 198c2ecf20Sopenharmony_ci 208c2ecf20Sopenharmony_cistatic int ddbridge_dummy_fe_read_status(struct dvb_frontend *fe, 218c2ecf20Sopenharmony_ci enum fe_status *status) 228c2ecf20Sopenharmony_ci{ 238c2ecf20Sopenharmony_ci *status = FE_HAS_SIGNAL 248c2ecf20Sopenharmony_ci | FE_HAS_CARRIER 258c2ecf20Sopenharmony_ci | FE_HAS_VITERBI 268c2ecf20Sopenharmony_ci | FE_HAS_SYNC 278c2ecf20Sopenharmony_ci | FE_HAS_LOCK; 288c2ecf20Sopenharmony_ci 298c2ecf20Sopenharmony_ci return 0; 308c2ecf20Sopenharmony_ci} 318c2ecf20Sopenharmony_ci 328c2ecf20Sopenharmony_cistatic int ddbridge_dummy_fe_read_ber(struct dvb_frontend *fe, u32 *ber) 338c2ecf20Sopenharmony_ci{ 348c2ecf20Sopenharmony_ci *ber = 0; 358c2ecf20Sopenharmony_ci return 0; 368c2ecf20Sopenharmony_ci} 378c2ecf20Sopenharmony_ci 388c2ecf20Sopenharmony_cistatic int ddbridge_dummy_fe_read_signal_strength(struct dvb_frontend *fe, 398c2ecf20Sopenharmony_ci u16 *strength) 408c2ecf20Sopenharmony_ci{ 418c2ecf20Sopenharmony_ci *strength = 0; 428c2ecf20Sopenharmony_ci return 0; 438c2ecf20Sopenharmony_ci} 448c2ecf20Sopenharmony_ci 458c2ecf20Sopenharmony_cistatic int ddbridge_dummy_fe_read_snr(struct dvb_frontend *fe, u16 *snr) 468c2ecf20Sopenharmony_ci{ 478c2ecf20Sopenharmony_ci *snr = 0; 488c2ecf20Sopenharmony_ci return 0; 498c2ecf20Sopenharmony_ci} 508c2ecf20Sopenharmony_ci 518c2ecf20Sopenharmony_cistatic int ddbridge_dummy_fe_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks) 528c2ecf20Sopenharmony_ci{ 538c2ecf20Sopenharmony_ci *ucblocks = 0; 548c2ecf20Sopenharmony_ci return 0; 558c2ecf20Sopenharmony_ci} 568c2ecf20Sopenharmony_ci 578c2ecf20Sopenharmony_ci/* 588c2ecf20Sopenharmony_ci * Should only be implemented if it actually reads something from the hardware. 598c2ecf20Sopenharmony_ci * Also, it should check for the locks, in order to avoid report wrong data 608c2ecf20Sopenharmony_ci * to userspace. 618c2ecf20Sopenharmony_ci */ 628c2ecf20Sopenharmony_cistatic int ddbridge_dummy_fe_get_frontend(struct dvb_frontend *fe, 638c2ecf20Sopenharmony_ci struct dtv_frontend_properties *p) 648c2ecf20Sopenharmony_ci{ 658c2ecf20Sopenharmony_ci return 0; 668c2ecf20Sopenharmony_ci} 678c2ecf20Sopenharmony_ci 688c2ecf20Sopenharmony_cistatic int ddbridge_dummy_fe_set_frontend(struct dvb_frontend *fe) 698c2ecf20Sopenharmony_ci{ 708c2ecf20Sopenharmony_ci if (fe->ops.tuner_ops.set_params) { 718c2ecf20Sopenharmony_ci fe->ops.tuner_ops.set_params(fe); 728c2ecf20Sopenharmony_ci if (fe->ops.i2c_gate_ctrl) 738c2ecf20Sopenharmony_ci fe->ops.i2c_gate_ctrl(fe, 0); 748c2ecf20Sopenharmony_ci } 758c2ecf20Sopenharmony_ci 768c2ecf20Sopenharmony_ci return 0; 778c2ecf20Sopenharmony_ci} 788c2ecf20Sopenharmony_ci 798c2ecf20Sopenharmony_cistatic int ddbridge_dummy_fe_sleep(struct dvb_frontend *fe) 808c2ecf20Sopenharmony_ci{ 818c2ecf20Sopenharmony_ci return 0; 828c2ecf20Sopenharmony_ci} 838c2ecf20Sopenharmony_ci 848c2ecf20Sopenharmony_cistatic int ddbridge_dummy_fe_init(struct dvb_frontend *fe) 858c2ecf20Sopenharmony_ci{ 868c2ecf20Sopenharmony_ci return 0; 878c2ecf20Sopenharmony_ci} 888c2ecf20Sopenharmony_ci 898c2ecf20Sopenharmony_cistatic void ddbridge_dummy_fe_release(struct dvb_frontend *fe) 908c2ecf20Sopenharmony_ci{ 918c2ecf20Sopenharmony_ci struct ddbridge_dummy_fe_state *state = fe->demodulator_priv; 928c2ecf20Sopenharmony_ci 938c2ecf20Sopenharmony_ci kfree(state); 948c2ecf20Sopenharmony_ci} 958c2ecf20Sopenharmony_ci 968c2ecf20Sopenharmony_cistatic const struct dvb_frontend_ops ddbridge_dummy_fe_qam_ops; 978c2ecf20Sopenharmony_ci 988c2ecf20Sopenharmony_cistruct dvb_frontend *ddbridge_dummy_fe_qam_attach(void) 998c2ecf20Sopenharmony_ci{ 1008c2ecf20Sopenharmony_ci struct ddbridge_dummy_fe_state *state = NULL; 1018c2ecf20Sopenharmony_ci 1028c2ecf20Sopenharmony_ci /* allocate memory for the internal state */ 1038c2ecf20Sopenharmony_ci state = kzalloc(sizeof(struct ddbridge_dummy_fe_state), GFP_KERNEL); 1048c2ecf20Sopenharmony_ci if (!state) 1058c2ecf20Sopenharmony_ci return NULL; 1068c2ecf20Sopenharmony_ci 1078c2ecf20Sopenharmony_ci /* create dvb_frontend */ 1088c2ecf20Sopenharmony_ci memcpy(&state->frontend.ops, 1098c2ecf20Sopenharmony_ci &ddbridge_dummy_fe_qam_ops, 1108c2ecf20Sopenharmony_ci sizeof(struct dvb_frontend_ops)); 1118c2ecf20Sopenharmony_ci 1128c2ecf20Sopenharmony_ci state->frontend.demodulator_priv = state; 1138c2ecf20Sopenharmony_ci return &state->frontend; 1148c2ecf20Sopenharmony_ci} 1158c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(ddbridge_dummy_fe_qam_attach); 1168c2ecf20Sopenharmony_ci 1178c2ecf20Sopenharmony_cistatic const struct dvb_frontend_ops ddbridge_dummy_fe_qam_ops = { 1188c2ecf20Sopenharmony_ci .delsys = { SYS_DVBC_ANNEX_A }, 1198c2ecf20Sopenharmony_ci .info = { 1208c2ecf20Sopenharmony_ci .name = "ddbridge dummy DVB-C", 1218c2ecf20Sopenharmony_ci .frequency_min_hz = 51 * MHz, 1228c2ecf20Sopenharmony_ci .frequency_max_hz = 858 * MHz, 1238c2ecf20Sopenharmony_ci .frequency_stepsize_hz = 62500, 1248c2ecf20Sopenharmony_ci /* symbol_rate_min: SACLK/64 == (XIN/2)/64 */ 1258c2ecf20Sopenharmony_ci .symbol_rate_min = (57840000 / 2) / 64, 1268c2ecf20Sopenharmony_ci .symbol_rate_max = (57840000 / 2) / 4, /* SACLK/4 */ 1278c2ecf20Sopenharmony_ci .caps = FE_CAN_QAM_16 | 1288c2ecf20Sopenharmony_ci FE_CAN_QAM_32 | 1298c2ecf20Sopenharmony_ci FE_CAN_QAM_64 | 1308c2ecf20Sopenharmony_ci FE_CAN_QAM_128 | 1318c2ecf20Sopenharmony_ci FE_CAN_QAM_256 | 1328c2ecf20Sopenharmony_ci FE_CAN_FEC_AUTO | 1338c2ecf20Sopenharmony_ci FE_CAN_INVERSION_AUTO 1348c2ecf20Sopenharmony_ci }, 1358c2ecf20Sopenharmony_ci 1368c2ecf20Sopenharmony_ci .release = ddbridge_dummy_fe_release, 1378c2ecf20Sopenharmony_ci 1388c2ecf20Sopenharmony_ci .init = ddbridge_dummy_fe_init, 1398c2ecf20Sopenharmony_ci .sleep = ddbridge_dummy_fe_sleep, 1408c2ecf20Sopenharmony_ci 1418c2ecf20Sopenharmony_ci .set_frontend = ddbridge_dummy_fe_set_frontend, 1428c2ecf20Sopenharmony_ci .get_frontend = ddbridge_dummy_fe_get_frontend, 1438c2ecf20Sopenharmony_ci 1448c2ecf20Sopenharmony_ci .read_status = ddbridge_dummy_fe_read_status, 1458c2ecf20Sopenharmony_ci .read_ber = ddbridge_dummy_fe_read_ber, 1468c2ecf20Sopenharmony_ci .read_signal_strength = ddbridge_dummy_fe_read_signal_strength, 1478c2ecf20Sopenharmony_ci .read_snr = ddbridge_dummy_fe_read_snr, 1488c2ecf20Sopenharmony_ci .read_ucblocks = ddbridge_dummy_fe_read_ucblocks, 1498c2ecf20Sopenharmony_ci}; 1508c2ecf20Sopenharmony_ci 1518c2ecf20Sopenharmony_ciMODULE_DESCRIPTION("ddbridge dummy Frontend"); 1528c2ecf20Sopenharmony_ciMODULE_AUTHOR("Emard"); 1538c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL"); 154