18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * Frontend driver for the GENPIX 8pks/qpsk/DCII USB2.0 DVB-S module 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * Copyright (C) 2006,2007 Alan Nisota (alannisota@gmail.com) 68c2ecf20Sopenharmony_ci * Copyright (C) 2006,2007 Genpix Electronics (genpix@genpix-electronics.com) 78c2ecf20Sopenharmony_ci * 88c2ecf20Sopenharmony_ci * Thanks to GENPIX for the sample code used to implement this module. 98c2ecf20Sopenharmony_ci * 108c2ecf20Sopenharmony_ci * This module is based off the vp7045 and vp702x modules 118c2ecf20Sopenharmony_ci */ 128c2ecf20Sopenharmony_ci 138c2ecf20Sopenharmony_ci#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 148c2ecf20Sopenharmony_ci 158c2ecf20Sopenharmony_ci#include "gp8psk-fe.h" 168c2ecf20Sopenharmony_ci#include <media/dvb_frontend.h> 178c2ecf20Sopenharmony_ci 188c2ecf20Sopenharmony_cistatic int debug; 198c2ecf20Sopenharmony_cimodule_param(debug, int, 0644); 208c2ecf20Sopenharmony_ciMODULE_PARM_DESC(debug, "Turn on/off debugging (default:off)."); 218c2ecf20Sopenharmony_ci 228c2ecf20Sopenharmony_ci#define dprintk(fmt, arg...) do { \ 238c2ecf20Sopenharmony_ci if (debug) \ 248c2ecf20Sopenharmony_ci printk(KERN_DEBUG pr_fmt("%s: " fmt), \ 258c2ecf20Sopenharmony_ci __func__, ##arg); \ 268c2ecf20Sopenharmony_ci} while (0) 278c2ecf20Sopenharmony_ci 288c2ecf20Sopenharmony_cistruct gp8psk_fe_state { 298c2ecf20Sopenharmony_ci struct dvb_frontend fe; 308c2ecf20Sopenharmony_ci void *priv; 318c2ecf20Sopenharmony_ci const struct gp8psk_fe_ops *ops; 328c2ecf20Sopenharmony_ci bool is_rev1; 338c2ecf20Sopenharmony_ci u8 lock; 348c2ecf20Sopenharmony_ci u16 snr; 358c2ecf20Sopenharmony_ci unsigned long next_status_check; 368c2ecf20Sopenharmony_ci unsigned long status_check_interval; 378c2ecf20Sopenharmony_ci}; 388c2ecf20Sopenharmony_ci 398c2ecf20Sopenharmony_cistatic int gp8psk_tuned_to_DCII(struct dvb_frontend *fe) 408c2ecf20Sopenharmony_ci{ 418c2ecf20Sopenharmony_ci struct gp8psk_fe_state *st = fe->demodulator_priv; 428c2ecf20Sopenharmony_ci u8 status; 438c2ecf20Sopenharmony_ci 448c2ecf20Sopenharmony_ci st->ops->in(st->priv, GET_8PSK_CONFIG, 0, 0, &status, 1); 458c2ecf20Sopenharmony_ci return status & bmDCtuned; 468c2ecf20Sopenharmony_ci} 478c2ecf20Sopenharmony_ci 488c2ecf20Sopenharmony_cistatic int gp8psk_set_tuner_mode(struct dvb_frontend *fe, int mode) 498c2ecf20Sopenharmony_ci{ 508c2ecf20Sopenharmony_ci struct gp8psk_fe_state *st = fe->demodulator_priv; 518c2ecf20Sopenharmony_ci 528c2ecf20Sopenharmony_ci return st->ops->out(st->priv, SET_8PSK_CONFIG, mode, 0, NULL, 0); 538c2ecf20Sopenharmony_ci} 548c2ecf20Sopenharmony_ci 558c2ecf20Sopenharmony_cistatic int gp8psk_fe_update_status(struct gp8psk_fe_state *st) 568c2ecf20Sopenharmony_ci{ 578c2ecf20Sopenharmony_ci u8 buf[6]; 588c2ecf20Sopenharmony_ci if (time_after(jiffies,st->next_status_check)) { 598c2ecf20Sopenharmony_ci st->ops->in(st->priv, GET_SIGNAL_LOCK, 0, 0, &st->lock, 1); 608c2ecf20Sopenharmony_ci st->ops->in(st->priv, GET_SIGNAL_STRENGTH, 0, 0, buf, 6); 618c2ecf20Sopenharmony_ci st->snr = (buf[1]) << 8 | buf[0]; 628c2ecf20Sopenharmony_ci st->next_status_check = jiffies + (st->status_check_interval*HZ)/1000; 638c2ecf20Sopenharmony_ci } 648c2ecf20Sopenharmony_ci return 0; 658c2ecf20Sopenharmony_ci} 668c2ecf20Sopenharmony_ci 678c2ecf20Sopenharmony_cistatic int gp8psk_fe_read_status(struct dvb_frontend *fe, 688c2ecf20Sopenharmony_ci enum fe_status *status) 698c2ecf20Sopenharmony_ci{ 708c2ecf20Sopenharmony_ci struct gp8psk_fe_state *st = fe->demodulator_priv; 718c2ecf20Sopenharmony_ci gp8psk_fe_update_status(st); 728c2ecf20Sopenharmony_ci 738c2ecf20Sopenharmony_ci if (st->lock) 748c2ecf20Sopenharmony_ci *status = FE_HAS_LOCK | FE_HAS_SYNC | FE_HAS_VITERBI | FE_HAS_SIGNAL | FE_HAS_CARRIER; 758c2ecf20Sopenharmony_ci else 768c2ecf20Sopenharmony_ci *status = 0; 778c2ecf20Sopenharmony_ci 788c2ecf20Sopenharmony_ci if (*status & FE_HAS_LOCK) 798c2ecf20Sopenharmony_ci st->status_check_interval = 1000; 808c2ecf20Sopenharmony_ci else 818c2ecf20Sopenharmony_ci st->status_check_interval = 100; 828c2ecf20Sopenharmony_ci return 0; 838c2ecf20Sopenharmony_ci} 848c2ecf20Sopenharmony_ci 858c2ecf20Sopenharmony_ci/* not supported by this Frontend */ 868c2ecf20Sopenharmony_cistatic int gp8psk_fe_read_ber(struct dvb_frontend* fe, u32 *ber) 878c2ecf20Sopenharmony_ci{ 888c2ecf20Sopenharmony_ci (void) fe; 898c2ecf20Sopenharmony_ci *ber = 0; 908c2ecf20Sopenharmony_ci return 0; 918c2ecf20Sopenharmony_ci} 928c2ecf20Sopenharmony_ci 938c2ecf20Sopenharmony_ci/* not supported by this Frontend */ 948c2ecf20Sopenharmony_cistatic int gp8psk_fe_read_unc_blocks(struct dvb_frontend* fe, u32 *unc) 958c2ecf20Sopenharmony_ci{ 968c2ecf20Sopenharmony_ci (void) fe; 978c2ecf20Sopenharmony_ci *unc = 0; 988c2ecf20Sopenharmony_ci return 0; 998c2ecf20Sopenharmony_ci} 1008c2ecf20Sopenharmony_ci 1018c2ecf20Sopenharmony_cistatic int gp8psk_fe_read_snr(struct dvb_frontend* fe, u16 *snr) 1028c2ecf20Sopenharmony_ci{ 1038c2ecf20Sopenharmony_ci struct gp8psk_fe_state *st = fe->demodulator_priv; 1048c2ecf20Sopenharmony_ci gp8psk_fe_update_status(st); 1058c2ecf20Sopenharmony_ci /* snr is reported in dBu*256 */ 1068c2ecf20Sopenharmony_ci *snr = st->snr; 1078c2ecf20Sopenharmony_ci return 0; 1088c2ecf20Sopenharmony_ci} 1098c2ecf20Sopenharmony_ci 1108c2ecf20Sopenharmony_cistatic int gp8psk_fe_read_signal_strength(struct dvb_frontend* fe, u16 *strength) 1118c2ecf20Sopenharmony_ci{ 1128c2ecf20Sopenharmony_ci struct gp8psk_fe_state *st = fe->demodulator_priv; 1138c2ecf20Sopenharmony_ci gp8psk_fe_update_status(st); 1148c2ecf20Sopenharmony_ci /* snr is reported in dBu*256 */ 1158c2ecf20Sopenharmony_ci /* snr / 38.4 ~= 100% strength */ 1168c2ecf20Sopenharmony_ci /* snr * 17 returns 100% strength as 65535 */ 1178c2ecf20Sopenharmony_ci if (st->snr > 0xf00) 1188c2ecf20Sopenharmony_ci *strength = 0xffff; 1198c2ecf20Sopenharmony_ci else 1208c2ecf20Sopenharmony_ci *strength = (st->snr << 4) + st->snr; /* snr*17 */ 1218c2ecf20Sopenharmony_ci return 0; 1228c2ecf20Sopenharmony_ci} 1238c2ecf20Sopenharmony_ci 1248c2ecf20Sopenharmony_cistatic int gp8psk_fe_get_tune_settings(struct dvb_frontend* fe, struct dvb_frontend_tune_settings *tune) 1258c2ecf20Sopenharmony_ci{ 1268c2ecf20Sopenharmony_ci tune->min_delay_ms = 800; 1278c2ecf20Sopenharmony_ci return 0; 1288c2ecf20Sopenharmony_ci} 1298c2ecf20Sopenharmony_ci 1308c2ecf20Sopenharmony_cistatic int gp8psk_fe_set_frontend(struct dvb_frontend *fe) 1318c2ecf20Sopenharmony_ci{ 1328c2ecf20Sopenharmony_ci struct gp8psk_fe_state *st = fe->demodulator_priv; 1338c2ecf20Sopenharmony_ci struct dtv_frontend_properties *c = &fe->dtv_property_cache; 1348c2ecf20Sopenharmony_ci u8 cmd[10]; 1358c2ecf20Sopenharmony_ci u32 freq = c->frequency * 1000; 1368c2ecf20Sopenharmony_ci 1378c2ecf20Sopenharmony_ci dprintk("%s()\n", __func__); 1388c2ecf20Sopenharmony_ci 1398c2ecf20Sopenharmony_ci cmd[4] = freq & 0xff; 1408c2ecf20Sopenharmony_ci cmd[5] = (freq >> 8) & 0xff; 1418c2ecf20Sopenharmony_ci cmd[6] = (freq >> 16) & 0xff; 1428c2ecf20Sopenharmony_ci cmd[7] = (freq >> 24) & 0xff; 1438c2ecf20Sopenharmony_ci 1448c2ecf20Sopenharmony_ci /* backwards compatibility: DVB-S + 8-PSK were used for Turbo-FEC */ 1458c2ecf20Sopenharmony_ci if (c->delivery_system == SYS_DVBS && c->modulation == PSK_8) 1468c2ecf20Sopenharmony_ci c->delivery_system = SYS_TURBO; 1478c2ecf20Sopenharmony_ci 1488c2ecf20Sopenharmony_ci switch (c->delivery_system) { 1498c2ecf20Sopenharmony_ci case SYS_DVBS: 1508c2ecf20Sopenharmony_ci if (c->modulation != QPSK) { 1518c2ecf20Sopenharmony_ci dprintk("%s: unsupported modulation selected (%d)\n", 1528c2ecf20Sopenharmony_ci __func__, c->modulation); 1538c2ecf20Sopenharmony_ci return -EOPNOTSUPP; 1548c2ecf20Sopenharmony_ci } 1558c2ecf20Sopenharmony_ci c->fec_inner = FEC_AUTO; 1568c2ecf20Sopenharmony_ci break; 1578c2ecf20Sopenharmony_ci case SYS_DVBS2: /* kept for backwards compatibility */ 1588c2ecf20Sopenharmony_ci dprintk("%s: DVB-S2 delivery system selected\n", __func__); 1598c2ecf20Sopenharmony_ci break; 1608c2ecf20Sopenharmony_ci case SYS_TURBO: 1618c2ecf20Sopenharmony_ci dprintk("%s: Turbo-FEC delivery system selected\n", __func__); 1628c2ecf20Sopenharmony_ci break; 1638c2ecf20Sopenharmony_ci 1648c2ecf20Sopenharmony_ci default: 1658c2ecf20Sopenharmony_ci dprintk("%s: unsupported delivery system selected (%d)\n", 1668c2ecf20Sopenharmony_ci __func__, c->delivery_system); 1678c2ecf20Sopenharmony_ci return -EOPNOTSUPP; 1688c2ecf20Sopenharmony_ci } 1698c2ecf20Sopenharmony_ci 1708c2ecf20Sopenharmony_ci cmd[0] = c->symbol_rate & 0xff; 1718c2ecf20Sopenharmony_ci cmd[1] = (c->symbol_rate >> 8) & 0xff; 1728c2ecf20Sopenharmony_ci cmd[2] = (c->symbol_rate >> 16) & 0xff; 1738c2ecf20Sopenharmony_ci cmd[3] = (c->symbol_rate >> 24) & 0xff; 1748c2ecf20Sopenharmony_ci switch (c->modulation) { 1758c2ecf20Sopenharmony_ci case QPSK: 1768c2ecf20Sopenharmony_ci if (st->is_rev1) 1778c2ecf20Sopenharmony_ci if (gp8psk_tuned_to_DCII(fe)) 1788c2ecf20Sopenharmony_ci st->ops->reload(st->priv); 1798c2ecf20Sopenharmony_ci switch (c->fec_inner) { 1808c2ecf20Sopenharmony_ci case FEC_1_2: 1818c2ecf20Sopenharmony_ci cmd[9] = 0; break; 1828c2ecf20Sopenharmony_ci case FEC_2_3: 1838c2ecf20Sopenharmony_ci cmd[9] = 1; break; 1848c2ecf20Sopenharmony_ci case FEC_3_4: 1858c2ecf20Sopenharmony_ci cmd[9] = 2; break; 1868c2ecf20Sopenharmony_ci case FEC_5_6: 1878c2ecf20Sopenharmony_ci cmd[9] = 3; break; 1888c2ecf20Sopenharmony_ci case FEC_7_8: 1898c2ecf20Sopenharmony_ci cmd[9] = 4; break; 1908c2ecf20Sopenharmony_ci case FEC_AUTO: 1918c2ecf20Sopenharmony_ci cmd[9] = 5; break; 1928c2ecf20Sopenharmony_ci default: 1938c2ecf20Sopenharmony_ci cmd[9] = 5; break; 1948c2ecf20Sopenharmony_ci } 1958c2ecf20Sopenharmony_ci if (c->delivery_system == SYS_TURBO) 1968c2ecf20Sopenharmony_ci cmd[8] = ADV_MOD_TURBO_QPSK; 1978c2ecf20Sopenharmony_ci else 1988c2ecf20Sopenharmony_ci cmd[8] = ADV_MOD_DVB_QPSK; 1998c2ecf20Sopenharmony_ci break; 2008c2ecf20Sopenharmony_ci case PSK_8: /* PSK_8 is for compatibility with DN */ 2018c2ecf20Sopenharmony_ci cmd[8] = ADV_MOD_TURBO_8PSK; 2028c2ecf20Sopenharmony_ci switch (c->fec_inner) { 2038c2ecf20Sopenharmony_ci case FEC_2_3: 2048c2ecf20Sopenharmony_ci cmd[9] = 0; break; 2058c2ecf20Sopenharmony_ci case FEC_3_4: 2068c2ecf20Sopenharmony_ci cmd[9] = 1; break; 2078c2ecf20Sopenharmony_ci case FEC_3_5: 2088c2ecf20Sopenharmony_ci cmd[9] = 2; break; 2098c2ecf20Sopenharmony_ci case FEC_5_6: 2108c2ecf20Sopenharmony_ci cmd[9] = 3; break; 2118c2ecf20Sopenharmony_ci case FEC_8_9: 2128c2ecf20Sopenharmony_ci cmd[9] = 4; break; 2138c2ecf20Sopenharmony_ci default: 2148c2ecf20Sopenharmony_ci cmd[9] = 0; break; 2158c2ecf20Sopenharmony_ci } 2168c2ecf20Sopenharmony_ci break; 2178c2ecf20Sopenharmony_ci case QAM_16: /* QAM_16 is for compatibility with DN */ 2188c2ecf20Sopenharmony_ci cmd[8] = ADV_MOD_TURBO_16QAM; 2198c2ecf20Sopenharmony_ci cmd[9] = 0; 2208c2ecf20Sopenharmony_ci break; 2218c2ecf20Sopenharmony_ci default: /* Unknown modulation */ 2228c2ecf20Sopenharmony_ci dprintk("%s: unsupported modulation selected (%d)\n", 2238c2ecf20Sopenharmony_ci __func__, c->modulation); 2248c2ecf20Sopenharmony_ci return -EOPNOTSUPP; 2258c2ecf20Sopenharmony_ci } 2268c2ecf20Sopenharmony_ci 2278c2ecf20Sopenharmony_ci if (st->is_rev1) 2288c2ecf20Sopenharmony_ci gp8psk_set_tuner_mode(fe, 0); 2298c2ecf20Sopenharmony_ci st->ops->out(st->priv, TUNE_8PSK, 0, 0, cmd, 10); 2308c2ecf20Sopenharmony_ci 2318c2ecf20Sopenharmony_ci st->lock = 0; 2328c2ecf20Sopenharmony_ci st->next_status_check = jiffies; 2338c2ecf20Sopenharmony_ci st->status_check_interval = 200; 2348c2ecf20Sopenharmony_ci 2358c2ecf20Sopenharmony_ci return 0; 2368c2ecf20Sopenharmony_ci} 2378c2ecf20Sopenharmony_ci 2388c2ecf20Sopenharmony_cistatic int gp8psk_fe_send_diseqc_msg (struct dvb_frontend* fe, 2398c2ecf20Sopenharmony_ci struct dvb_diseqc_master_cmd *m) 2408c2ecf20Sopenharmony_ci{ 2418c2ecf20Sopenharmony_ci struct gp8psk_fe_state *st = fe->demodulator_priv; 2428c2ecf20Sopenharmony_ci 2438c2ecf20Sopenharmony_ci dprintk("%s\n", __func__); 2448c2ecf20Sopenharmony_ci 2458c2ecf20Sopenharmony_ci if (st->ops->out(st->priv, SEND_DISEQC_COMMAND, m->msg[0], 0, 2468c2ecf20Sopenharmony_ci m->msg, m->msg_len)) { 2478c2ecf20Sopenharmony_ci return -EINVAL; 2488c2ecf20Sopenharmony_ci } 2498c2ecf20Sopenharmony_ci return 0; 2508c2ecf20Sopenharmony_ci} 2518c2ecf20Sopenharmony_ci 2528c2ecf20Sopenharmony_cistatic int gp8psk_fe_send_diseqc_burst(struct dvb_frontend *fe, 2538c2ecf20Sopenharmony_ci enum fe_sec_mini_cmd burst) 2548c2ecf20Sopenharmony_ci{ 2558c2ecf20Sopenharmony_ci struct gp8psk_fe_state *st = fe->demodulator_priv; 2568c2ecf20Sopenharmony_ci u8 cmd; 2578c2ecf20Sopenharmony_ci 2588c2ecf20Sopenharmony_ci dprintk("%s\n", __func__); 2598c2ecf20Sopenharmony_ci 2608c2ecf20Sopenharmony_ci /* These commands are certainly wrong */ 2618c2ecf20Sopenharmony_ci cmd = (burst == SEC_MINI_A) ? 0x00 : 0x01; 2628c2ecf20Sopenharmony_ci 2638c2ecf20Sopenharmony_ci if (st->ops->out(st->priv, SEND_DISEQC_COMMAND, cmd, 0, 2648c2ecf20Sopenharmony_ci &cmd, 0)) { 2658c2ecf20Sopenharmony_ci return -EINVAL; 2668c2ecf20Sopenharmony_ci } 2678c2ecf20Sopenharmony_ci return 0; 2688c2ecf20Sopenharmony_ci} 2698c2ecf20Sopenharmony_ci 2708c2ecf20Sopenharmony_cistatic int gp8psk_fe_set_tone(struct dvb_frontend *fe, 2718c2ecf20Sopenharmony_ci enum fe_sec_tone_mode tone) 2728c2ecf20Sopenharmony_ci{ 2738c2ecf20Sopenharmony_ci struct gp8psk_fe_state *st = fe->demodulator_priv; 2748c2ecf20Sopenharmony_ci 2758c2ecf20Sopenharmony_ci if (st->ops->out(st->priv, SET_22KHZ_TONE, 2768c2ecf20Sopenharmony_ci (tone == SEC_TONE_ON), 0, NULL, 0)) { 2778c2ecf20Sopenharmony_ci return -EINVAL; 2788c2ecf20Sopenharmony_ci } 2798c2ecf20Sopenharmony_ci return 0; 2808c2ecf20Sopenharmony_ci} 2818c2ecf20Sopenharmony_ci 2828c2ecf20Sopenharmony_cistatic int gp8psk_fe_set_voltage(struct dvb_frontend *fe, 2838c2ecf20Sopenharmony_ci enum fe_sec_voltage voltage) 2848c2ecf20Sopenharmony_ci{ 2858c2ecf20Sopenharmony_ci struct gp8psk_fe_state *st = fe->demodulator_priv; 2868c2ecf20Sopenharmony_ci 2878c2ecf20Sopenharmony_ci if (st->ops->out(st->priv, SET_LNB_VOLTAGE, 2888c2ecf20Sopenharmony_ci voltage == SEC_VOLTAGE_18, 0, NULL, 0)) { 2898c2ecf20Sopenharmony_ci return -EINVAL; 2908c2ecf20Sopenharmony_ci } 2918c2ecf20Sopenharmony_ci return 0; 2928c2ecf20Sopenharmony_ci} 2938c2ecf20Sopenharmony_ci 2948c2ecf20Sopenharmony_cistatic int gp8psk_fe_enable_high_lnb_voltage(struct dvb_frontend* fe, long onoff) 2958c2ecf20Sopenharmony_ci{ 2968c2ecf20Sopenharmony_ci struct gp8psk_fe_state *st = fe->demodulator_priv; 2978c2ecf20Sopenharmony_ci 2988c2ecf20Sopenharmony_ci return st->ops->out(st->priv, USE_EXTRA_VOLT, onoff, 0, NULL, 0); 2998c2ecf20Sopenharmony_ci} 3008c2ecf20Sopenharmony_ci 3018c2ecf20Sopenharmony_cistatic int gp8psk_fe_send_legacy_dish_cmd (struct dvb_frontend* fe, unsigned long sw_cmd) 3028c2ecf20Sopenharmony_ci{ 3038c2ecf20Sopenharmony_ci struct gp8psk_fe_state *st = fe->demodulator_priv; 3048c2ecf20Sopenharmony_ci u8 cmd = sw_cmd & 0x7f; 3058c2ecf20Sopenharmony_ci 3068c2ecf20Sopenharmony_ci if (st->ops->out(st->priv, SET_DN_SWITCH, cmd, 0, NULL, 0)) 3078c2ecf20Sopenharmony_ci return -EINVAL; 3088c2ecf20Sopenharmony_ci 3098c2ecf20Sopenharmony_ci if (st->ops->out(st->priv, SET_LNB_VOLTAGE, !!(sw_cmd & 0x80), 3108c2ecf20Sopenharmony_ci 0, NULL, 0)) 3118c2ecf20Sopenharmony_ci return -EINVAL; 3128c2ecf20Sopenharmony_ci 3138c2ecf20Sopenharmony_ci return 0; 3148c2ecf20Sopenharmony_ci} 3158c2ecf20Sopenharmony_ci 3168c2ecf20Sopenharmony_cistatic void gp8psk_fe_release(struct dvb_frontend* fe) 3178c2ecf20Sopenharmony_ci{ 3188c2ecf20Sopenharmony_ci struct gp8psk_fe_state *st = fe->demodulator_priv; 3198c2ecf20Sopenharmony_ci 3208c2ecf20Sopenharmony_ci kfree(st); 3218c2ecf20Sopenharmony_ci} 3228c2ecf20Sopenharmony_ci 3238c2ecf20Sopenharmony_cistatic const struct dvb_frontend_ops gp8psk_fe_ops; 3248c2ecf20Sopenharmony_ci 3258c2ecf20Sopenharmony_cistruct dvb_frontend *gp8psk_fe_attach(const struct gp8psk_fe_ops *ops, 3268c2ecf20Sopenharmony_ci void *priv, bool is_rev1) 3278c2ecf20Sopenharmony_ci{ 3288c2ecf20Sopenharmony_ci struct gp8psk_fe_state *st; 3298c2ecf20Sopenharmony_ci 3308c2ecf20Sopenharmony_ci if (!ops || !ops->in || !ops->out || !ops->reload) { 3318c2ecf20Sopenharmony_ci pr_err("Error! gp8psk-fe ops not defined.\n"); 3328c2ecf20Sopenharmony_ci return NULL; 3338c2ecf20Sopenharmony_ci } 3348c2ecf20Sopenharmony_ci 3358c2ecf20Sopenharmony_ci st = kzalloc(sizeof(struct gp8psk_fe_state), GFP_KERNEL); 3368c2ecf20Sopenharmony_ci if (!st) 3378c2ecf20Sopenharmony_ci return NULL; 3388c2ecf20Sopenharmony_ci 3398c2ecf20Sopenharmony_ci memcpy(&st->fe.ops, &gp8psk_fe_ops, sizeof(struct dvb_frontend_ops)); 3408c2ecf20Sopenharmony_ci st->fe.demodulator_priv = st; 3418c2ecf20Sopenharmony_ci st->ops = ops; 3428c2ecf20Sopenharmony_ci st->priv = priv; 3438c2ecf20Sopenharmony_ci st->is_rev1 = is_rev1; 3448c2ecf20Sopenharmony_ci 3458c2ecf20Sopenharmony_ci pr_info("Frontend %sattached\n", is_rev1 ? "revision 1 " : ""); 3468c2ecf20Sopenharmony_ci 3478c2ecf20Sopenharmony_ci return &st->fe; 3488c2ecf20Sopenharmony_ci} 3498c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(gp8psk_fe_attach); 3508c2ecf20Sopenharmony_ci 3518c2ecf20Sopenharmony_cistatic const struct dvb_frontend_ops gp8psk_fe_ops = { 3528c2ecf20Sopenharmony_ci .delsys = { SYS_DVBS }, 3538c2ecf20Sopenharmony_ci .info = { 3548c2ecf20Sopenharmony_ci .name = "Genpix DVB-S", 3558c2ecf20Sopenharmony_ci .frequency_min_hz = 800 * MHz, 3568c2ecf20Sopenharmony_ci .frequency_max_hz = 2250 * MHz, 3578c2ecf20Sopenharmony_ci .frequency_stepsize_hz = 100 * kHz, 3588c2ecf20Sopenharmony_ci .symbol_rate_min = 1000000, 3598c2ecf20Sopenharmony_ci .symbol_rate_max = 45000000, 3608c2ecf20Sopenharmony_ci .symbol_rate_tolerance = 500, /* ppm */ 3618c2ecf20Sopenharmony_ci .caps = FE_CAN_INVERSION_AUTO | 3628c2ecf20Sopenharmony_ci FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 | 3638c2ecf20Sopenharmony_ci FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO | 3648c2ecf20Sopenharmony_ci /* 3658c2ecf20Sopenharmony_ci * FE_CAN_QAM_16 is for compatibility 3668c2ecf20Sopenharmony_ci * (Myth incorrectly detects Turbo-QPSK as plain QAM-16) 3678c2ecf20Sopenharmony_ci */ 3688c2ecf20Sopenharmony_ci FE_CAN_QPSK | FE_CAN_QAM_16 | FE_CAN_TURBO_FEC 3698c2ecf20Sopenharmony_ci }, 3708c2ecf20Sopenharmony_ci 3718c2ecf20Sopenharmony_ci .release = gp8psk_fe_release, 3728c2ecf20Sopenharmony_ci 3738c2ecf20Sopenharmony_ci .init = NULL, 3748c2ecf20Sopenharmony_ci .sleep = NULL, 3758c2ecf20Sopenharmony_ci 3768c2ecf20Sopenharmony_ci .set_frontend = gp8psk_fe_set_frontend, 3778c2ecf20Sopenharmony_ci 3788c2ecf20Sopenharmony_ci .get_tune_settings = gp8psk_fe_get_tune_settings, 3798c2ecf20Sopenharmony_ci 3808c2ecf20Sopenharmony_ci .read_status = gp8psk_fe_read_status, 3818c2ecf20Sopenharmony_ci .read_ber = gp8psk_fe_read_ber, 3828c2ecf20Sopenharmony_ci .read_signal_strength = gp8psk_fe_read_signal_strength, 3838c2ecf20Sopenharmony_ci .read_snr = gp8psk_fe_read_snr, 3848c2ecf20Sopenharmony_ci .read_ucblocks = gp8psk_fe_read_unc_blocks, 3858c2ecf20Sopenharmony_ci 3868c2ecf20Sopenharmony_ci .diseqc_send_master_cmd = gp8psk_fe_send_diseqc_msg, 3878c2ecf20Sopenharmony_ci .diseqc_send_burst = gp8psk_fe_send_diseqc_burst, 3888c2ecf20Sopenharmony_ci .set_tone = gp8psk_fe_set_tone, 3898c2ecf20Sopenharmony_ci .set_voltage = gp8psk_fe_set_voltage, 3908c2ecf20Sopenharmony_ci .dishnetwork_send_legacy_command = gp8psk_fe_send_legacy_dish_cmd, 3918c2ecf20Sopenharmony_ci .enable_high_lnb_voltage = gp8psk_fe_enable_high_lnb_voltage 3928c2ecf20Sopenharmony_ci}; 3938c2ecf20Sopenharmony_ci 3948c2ecf20Sopenharmony_ciMODULE_AUTHOR("Alan Nisota <alannisota@gamil.com>"); 3958c2ecf20Sopenharmony_ciMODULE_DESCRIPTION("Frontend Driver for Genpix DVB-S"); 3968c2ecf20Sopenharmony_ciMODULE_VERSION("1.1"); 3978c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL"); 398