^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-or-later
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) Conexant cx24116/cx24118 - DVBS/S2 Satellite demod/tuner driver
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) Copyright (C) 2006-2008 Steven Toth <stoth@hauppauge.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) Copyright (C) 2006-2007 Georg Acher
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) Copyright (C) 2007-2008 Darron Broad
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) March 2007
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) Fixed some bugs.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) Added diseqc support.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) Added corrected signal strength support.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) August 2007
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) Sync with legacy version.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) Some clean ups.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) Copyright (C) 2008 Igor Liplianin
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) September, 9th 2008
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) Fixed locking on high symbol rates (>30000).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) Implement MPEG initialization parameter.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) January, 17th 2009
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) Fill set_voltage with actually control voltage code.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) Correct set tone to not affect voltage.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) #include <linux/moduleparam.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) #include <linux/init.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) #include <linux/firmware.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) #include <media/dvb_frontend.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) #include "cx24116.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) static int debug;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) module_param(debug, int, 0644);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) MODULE_PARM_DESC(debug, "Activates frontend debugging (default:0)");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) #define dprintk(args...) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) do { \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) if (debug) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) printk(KERN_INFO "cx24116: " args); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) } while (0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) #define CX24116_DEFAULT_FIRMWARE "dvb-fe-cx24116.fw"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) #define CX24116_SEARCH_RANGE_KHZ 5000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) /* known registers */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) #define CX24116_REG_COMMAND (0x00) /* command args 0x00..0x1e */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) #define CX24116_REG_EXECUTE (0x1f) /* execute command */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) #define CX24116_REG_MAILBOX (0x96) /* FW or multipurpose mailbox? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) #define CX24116_REG_RESET (0x20) /* reset status > 0 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) #define CX24116_REG_SIGNAL (0x9e) /* signal low */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) #define CX24116_REG_SSTATUS (0x9d) /* signal high / status */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) #define CX24116_REG_QUALITY8 (0xa3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) #define CX24116_REG_QSTATUS (0xbc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) #define CX24116_REG_QUALITY0 (0xd5)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) #define CX24116_REG_BER0 (0xc9)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) #define CX24116_REG_BER8 (0xc8)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) #define CX24116_REG_BER16 (0xc7)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) #define CX24116_REG_BER24 (0xc6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) #define CX24116_REG_UCB0 (0xcb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) #define CX24116_REG_UCB8 (0xca)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) #define CX24116_REG_CLKDIV (0xf3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) #define CX24116_REG_RATEDIV (0xf9)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) /* configured fec (not tuned) or actual FEC (tuned) 1=1/2 2=2/3 etc */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) #define CX24116_REG_FECSTATUS (0x9c)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) /* FECSTATUS bits */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) /* mask to determine configured fec (not tuned) or actual fec (tuned) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) #define CX24116_FEC_FECMASK (0x1f)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) /* Select DVB-S demodulator, else DVB-S2 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) #define CX24116_FEC_DVBS (0x20)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) #define CX24116_FEC_UNKNOWN (0x40) /* Unknown/unused */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) /* Pilot mode requested when tuning else always reset when tuned */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) #define CX24116_FEC_PILOT (0x80)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) /* arg buffer size */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) #define CX24116_ARGLEN (0x1e)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) /* rolloff */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) #define CX24116_ROLLOFF_020 (0x00)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) #define CX24116_ROLLOFF_025 (0x01)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) #define CX24116_ROLLOFF_035 (0x02)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) /* pilot bit */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) #define CX24116_PILOT_OFF (0x00)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) #define CX24116_PILOT_ON (0x40)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) /* signal status */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) #define CX24116_HAS_SIGNAL (0x01)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) #define CX24116_HAS_CARRIER (0x02)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) #define CX24116_HAS_VITERBI (0x04)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) #define CX24116_HAS_SYNCLOCK (0x08)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) #define CX24116_HAS_UNKNOWN1 (0x10)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) #define CX24116_HAS_UNKNOWN2 (0x20)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) #define CX24116_STATUS_MASK (0x0f)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) #define CX24116_SIGNAL_MASK (0xc0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) #define CX24116_DISEQC_TONEOFF (0) /* toneburst never sent */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) #define CX24116_DISEQC_TONECACHE (1) /* toneburst cached */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) #define CX24116_DISEQC_MESGCACHE (2) /* message cached */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) /* arg offset for DiSEqC */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) #define CX24116_DISEQC_BURST (1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) #define CX24116_DISEQC_ARG2_2 (2) /* unknown value=2 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) #define CX24116_DISEQC_ARG3_0 (3) /* unknown value=0 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) #define CX24116_DISEQC_ARG4_0 (4) /* unknown value=0 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) #define CX24116_DISEQC_MSGLEN (5)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) #define CX24116_DISEQC_MSGOFS (6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) /* DiSEqC burst */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) #define CX24116_DISEQC_MINI_A (0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) #define CX24116_DISEQC_MINI_B (1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) /* DiSEqC tone burst */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) static int toneburst = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) module_param(toneburst, int, 0644);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) MODULE_PARM_DESC(toneburst, "DiSEqC toneburst 0=OFF, 1=TONE CACHE, "\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) "2=MESSAGE CACHE (default:1)");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) /* SNR measurements */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) static int esno_snr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) module_param(esno_snr, int, 0644);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) MODULE_PARM_DESC(esno_snr, "SNR return units, 0=PERCENTAGE 0-100, "\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) "1=ESNO(db * 10) (default:0)");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) enum cmds {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) CMD_SET_VCO = 0x10,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) CMD_TUNEREQUEST = 0x11,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) CMD_MPEGCONFIG = 0x13,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) CMD_TUNERINIT = 0x14,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) CMD_BANDWIDTH = 0x15,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) CMD_GETAGC = 0x19,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) CMD_LNBCONFIG = 0x20,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) CMD_LNBSEND = 0x21, /* Formerly CMD_SEND_DISEQC */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) CMD_LNBDCLEVEL = 0x22,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) CMD_SET_TONE = 0x23,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) CMD_UPDFWVERS = 0x35,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) CMD_TUNERSLEEP = 0x36,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) CMD_AGCCONTROL = 0x3b, /* Unknown */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) /* The Demod/Tuner can't easily provide these, we cache them */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) struct cx24116_tuning {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) u32 frequency;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) u32 symbol_rate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) enum fe_spectral_inversion inversion;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) enum fe_code_rate fec;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) enum fe_delivery_system delsys;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) enum fe_modulation modulation;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) enum fe_pilot pilot;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) enum fe_rolloff rolloff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) /* Demod values */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) u8 fec_val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) u8 fec_mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) u8 inversion_val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) u8 pilot_val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) u8 rolloff_val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) /* Basic commands that are sent to the firmware */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) struct cx24116_cmd {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) u8 len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) u8 args[CX24116_ARGLEN];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) struct cx24116_state {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) struct i2c_adapter *i2c;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) const struct cx24116_config *config;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) struct dvb_frontend frontend;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) struct cx24116_tuning dcur;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) struct cx24116_tuning dnxt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) u8 skip_fw_load;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) u8 burst;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) struct cx24116_cmd dsec_cmd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) static int cx24116_writereg(struct cx24116_state *state, int reg, int data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) u8 buf[] = { reg, data };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) struct i2c_msg msg = { .addr = state->config->demod_address,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) .flags = 0, .buf = buf, .len = 2 };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) if (debug > 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) printk("cx24116: %s: write reg 0x%02x, value 0x%02x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) __func__, reg, data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) err = i2c_transfer(state->i2c, &msg, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) if (err != 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) printk(KERN_ERR "%s: writereg error(err == %i, reg == 0x%02x, value == 0x%02x)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) __func__, err, reg, data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) return -EREMOTEIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) /* Bulk byte writes to a single I2C address, for 32k firmware load */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) static int cx24116_writeregN(struct cx24116_state *state, int reg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) const u8 *data, u16 len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) struct i2c_msg msg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) u8 *buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) buf = kmalloc(len + 1, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) if (!buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) *(buf) = reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) memcpy(buf + 1, data, len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) msg.addr = state->config->demod_address;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) msg.flags = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) msg.buf = buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) msg.len = len + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) if (debug > 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) printk(KERN_INFO "cx24116: %s: write regN 0x%02x, len = %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) __func__, reg, len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) ret = i2c_transfer(state->i2c, &msg, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) if (ret != 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) printk(KERN_ERR "%s: writereg error(err == %i, reg == 0x%02x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) __func__, ret, reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) ret = -EREMOTEIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) kfree(buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) static int cx24116_readreg(struct cx24116_state *state, u8 reg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) u8 b0[] = { reg };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) u8 b1[] = { 0 };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) struct i2c_msg msg[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) { .addr = state->config->demod_address, .flags = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) .buf = b0, .len = 1 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) { .addr = state->config->demod_address, .flags = I2C_M_RD,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) .buf = b1, .len = 1 }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) ret = i2c_transfer(state->i2c, msg, 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) if (ret != 2) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) printk(KERN_ERR "%s: reg=0x%x (error=%d)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) __func__, reg, ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) if (debug > 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) printk(KERN_INFO "cx24116: read reg 0x%02x, value 0x%02x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) reg, b1[0]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) return b1[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) static int cx24116_set_inversion(struct cx24116_state *state,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) enum fe_spectral_inversion inversion)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) dprintk("%s(%d)\n", __func__, inversion);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) switch (inversion) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) case INVERSION_OFF:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) state->dnxt.inversion_val = 0x00;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) case INVERSION_ON:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) state->dnxt.inversion_val = 0x04;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) case INVERSION_AUTO:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) state->dnxt.inversion_val = 0x0C;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) state->dnxt.inversion = inversion;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) * modfec (modulation and FEC)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) * ===========================
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) * MOD FEC mask/val standard
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) * ---- -------- ----------- --------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) * QPSK FEC_1_2 0x02 0x02+X DVB-S
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) * QPSK FEC_2_3 0x04 0x02+X DVB-S
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) * QPSK FEC_3_4 0x08 0x02+X DVB-S
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) * QPSK FEC_4_5 0x10 0x02+X DVB-S (?)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) * QPSK FEC_5_6 0x20 0x02+X DVB-S
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) * QPSK FEC_6_7 0x40 0x02+X DVB-S
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) * QPSK FEC_7_8 0x80 0x02+X DVB-S
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) * QPSK FEC_8_9 0x01 0x02+X DVB-S (?) (NOT SUPPORTED?)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) * QPSK AUTO 0xff 0x02+X DVB-S
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) * For DVB-S high byte probably represents FEC
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) * and low byte selects the modulator. The high
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) * byte is search range mask. Bit 5 may turn
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) * on DVB-S and remaining bits represent some
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) * kind of calibration (how/what i do not know).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) * Eg.(2/3) szap "Zone Horror"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) * mask/val = 0x04, 0x20
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) * status 1f | signal c3c0 | snr a333 | ber 00000098 | unc 0 | FE_HAS_LOCK
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) * mask/val = 0x04, 0x30
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) * status 1f | signal c3c0 | snr a333 | ber 00000000 | unc 0 | FE_HAS_LOCK
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) * After tuning FECSTATUS contains actual FEC
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) * in use numbered 1 through to 8 for 1/2 .. 2/3 etc
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) * NBC=NOT/NON BACKWARD COMPATIBLE WITH DVB-S (DVB-S2 only)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) * NBC-QPSK FEC_1_2 0x00, 0x04 DVB-S2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) * NBC-QPSK FEC_3_5 0x00, 0x05 DVB-S2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) * NBC-QPSK FEC_2_3 0x00, 0x06 DVB-S2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) * NBC-QPSK FEC_3_4 0x00, 0x07 DVB-S2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) * NBC-QPSK FEC_4_5 0x00, 0x08 DVB-S2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) * NBC-QPSK FEC_5_6 0x00, 0x09 DVB-S2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) * NBC-QPSK FEC_8_9 0x00, 0x0a DVB-S2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) * NBC-QPSK FEC_9_10 0x00, 0x0b DVB-S2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) * NBC-8PSK FEC_3_5 0x00, 0x0c DVB-S2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) * NBC-8PSK FEC_2_3 0x00, 0x0d DVB-S2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) * NBC-8PSK FEC_3_4 0x00, 0x0e DVB-S2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) * NBC-8PSK FEC_5_6 0x00, 0x0f DVB-S2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) * NBC-8PSK FEC_8_9 0x00, 0x10 DVB-S2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) * NBC-8PSK FEC_9_10 0x00, 0x11 DVB-S2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) * For DVB-S2 low bytes selects both modulator
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) * and FEC. High byte is meaningless here. To
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) * set pilot, bit 6 (0x40) is set. When inspecting
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) * FECSTATUS bit 7 (0x80) represents the pilot
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) * selection whilst not tuned. When tuned, actual FEC
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) * in use is found in FECSTATUS as per above. Pilot
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) * value is reset.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) /* A table of modulation, fec and configuration bytes for the demod.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) * Not all S2 mmodulation schemes are support and not all rates with
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) * a scheme are support. Especially, no auto detect when in S2 mode.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) static struct cx24116_modfec {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) enum fe_delivery_system delivery_system;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) enum fe_modulation modulation;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) enum fe_code_rate fec;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) u8 mask; /* In DVBS mode this is used to autodetect */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) u8 val; /* Passed to the firmware to indicate mode selection */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) } CX24116_MODFEC_MODES[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) /* QPSK. For unknown rates we set hardware to auto detect 0xfe 0x30 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) /*mod fec mask val */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) { SYS_DVBS, QPSK, FEC_NONE, 0xfe, 0x30 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) { SYS_DVBS, QPSK, FEC_1_2, 0x02, 0x2e }, /* 00000010 00101110 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) { SYS_DVBS, QPSK, FEC_2_3, 0x04, 0x2f }, /* 00000100 00101111 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) { SYS_DVBS, QPSK, FEC_3_4, 0x08, 0x30 }, /* 00001000 00110000 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) { SYS_DVBS, QPSK, FEC_4_5, 0xfe, 0x30 }, /* 000?0000 ? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) { SYS_DVBS, QPSK, FEC_5_6, 0x20, 0x31 }, /* 00100000 00110001 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) { SYS_DVBS, QPSK, FEC_6_7, 0xfe, 0x30 }, /* 0?000000 ? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) { SYS_DVBS, QPSK, FEC_7_8, 0x80, 0x32 }, /* 10000000 00110010 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) { SYS_DVBS, QPSK, FEC_8_9, 0xfe, 0x30 }, /* 0000000? ? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) { SYS_DVBS, QPSK, FEC_AUTO, 0xfe, 0x30 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) /* NBC-QPSK */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) { SYS_DVBS2, QPSK, FEC_1_2, 0x00, 0x04 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) { SYS_DVBS2, QPSK, FEC_3_5, 0x00, 0x05 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) { SYS_DVBS2, QPSK, FEC_2_3, 0x00, 0x06 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) { SYS_DVBS2, QPSK, FEC_3_4, 0x00, 0x07 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) { SYS_DVBS2, QPSK, FEC_4_5, 0x00, 0x08 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) { SYS_DVBS2, QPSK, FEC_5_6, 0x00, 0x09 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) { SYS_DVBS2, QPSK, FEC_8_9, 0x00, 0x0a },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) { SYS_DVBS2, QPSK, FEC_9_10, 0x00, 0x0b },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) /* 8PSK */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) { SYS_DVBS2, PSK_8, FEC_3_5, 0x00, 0x0c },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) { SYS_DVBS2, PSK_8, FEC_2_3, 0x00, 0x0d },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) { SYS_DVBS2, PSK_8, FEC_3_4, 0x00, 0x0e },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) { SYS_DVBS2, PSK_8, FEC_5_6, 0x00, 0x0f },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) { SYS_DVBS2, PSK_8, FEC_8_9, 0x00, 0x10 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) { SYS_DVBS2, PSK_8, FEC_9_10, 0x00, 0x11 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) * `val' can be found in the FECSTATUS register when tuning.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) * FECSTATUS will give the actual FEC in use if tuning was successful.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) static int cx24116_lookup_fecmod(struct cx24116_state *state,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) enum fe_delivery_system d, enum fe_modulation m, enum fe_code_rate f)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) int i, ret = -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) dprintk("%s(0x%02x,0x%02x)\n", __func__, m, f);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) for (i = 0; i < ARRAY_SIZE(CX24116_MODFEC_MODES); i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) if ((d == CX24116_MODFEC_MODES[i].delivery_system) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) (m == CX24116_MODFEC_MODES[i].modulation) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) (f == CX24116_MODFEC_MODES[i].fec)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) ret = i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) static int cx24116_set_fec(struct cx24116_state *state,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) enum fe_delivery_system delsys,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) enum fe_modulation mod,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) enum fe_code_rate fec)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) dprintk("%s(0x%02x,0x%02x)\n", __func__, mod, fec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) ret = cx24116_lookup_fecmod(state, delsys, mod, fec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) state->dnxt.fec = fec;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) state->dnxt.fec_val = CX24116_MODFEC_MODES[ret].val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) state->dnxt.fec_mask = CX24116_MODFEC_MODES[ret].mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) dprintk("%s() mask/val = 0x%02x/0x%02x\n", __func__,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) state->dnxt.fec_mask, state->dnxt.fec_val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) static int cx24116_set_symbolrate(struct cx24116_state *state, u32 rate)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) dprintk("%s(%d)\n", __func__, rate);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) /* check if symbol rate is within limits */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) if ((rate > state->frontend.ops.info.symbol_rate_max) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) (rate < state->frontend.ops.info.symbol_rate_min)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) dprintk("%s() unsupported symbol_rate = %d\n", __func__, rate);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) return -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) state->dnxt.symbol_rate = rate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) dprintk("%s() symbol_rate = %d\n", __func__, rate);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) static int cx24116_load_firmware(struct dvb_frontend *fe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) const struct firmware *fw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) static int cx24116_firmware_ondemand(struct dvb_frontend *fe)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) struct cx24116_state *state = fe->demodulator_priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) const struct firmware *fw;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) dprintk("%s()\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) if (cx24116_readreg(state, 0x20) > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) if (state->skip_fw_load)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) /* Load firmware */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) /* request the firmware, this will block until loaded */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) printk(KERN_INFO "%s: Waiting for firmware upload (%s)...\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) __func__, CX24116_DEFAULT_FIRMWARE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) ret = request_firmware(&fw, CX24116_DEFAULT_FIRMWARE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) state->i2c->dev.parent);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) printk(KERN_INFO "%s: Waiting for firmware upload(2)...\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) printk(KERN_ERR "%s: No firmware uploaded (timeout or file not found?)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) /* Make sure we don't recurse back through here
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) * during loading */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) state->skip_fw_load = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) ret = cx24116_load_firmware(fe, fw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) printk(KERN_ERR "%s: Writing firmware to device failed\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) release_firmware(fw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) printk(KERN_INFO "%s: Firmware upload %s\n", __func__,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) ret == 0 ? "complete" : "failed");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) /* Ensure firmware is always loaded if required */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) state->skip_fw_load = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) /* Take a basic firmware command structure, format it
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) * and forward it for processing
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) static int cx24116_cmd_execute(struct dvb_frontend *fe, struct cx24116_cmd *cmd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) struct cx24116_state *state = fe->demodulator_priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) int i, ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) dprintk("%s()\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) /* Load the firmware if required */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) ret = cx24116_firmware_ondemand(fe);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) if (ret != 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) printk(KERN_ERR "%s(): Unable initialise the firmware\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) /* Write the command */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) for (i = 0; i < cmd->len ; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) dprintk("%s: 0x%02x == 0x%02x\n", __func__, i, cmd->args[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) cx24116_writereg(state, i, cmd->args[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) /* Start execution and wait for cmd to terminate */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) cx24116_writereg(state, CX24116_REG_EXECUTE, 0x01);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) while (cx24116_readreg(state, CX24116_REG_EXECUTE)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) msleep(10);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) if (i++ > 64) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) /* Avoid looping forever if the firmware does
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) not respond */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) printk(KERN_WARNING "%s() Firmware not responding\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) return -EREMOTEIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) static int cx24116_load_firmware(struct dvb_frontend *fe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) const struct firmware *fw)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) struct cx24116_state *state = fe->demodulator_priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) struct cx24116_cmd cmd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) int i, ret, len, max, remaining;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) unsigned char vers[4];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) dprintk("%s\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) dprintk("Firmware is %zu bytes (%02x %02x .. %02x %02x)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) fw->size,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) fw->data[0],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) fw->data[1],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) fw->data[fw->size-2],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) fw->data[fw->size-1]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) /* Toggle 88x SRST pin to reset demod */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) if (state->config->reset_device)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) state->config->reset_device(fe);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) /* Begin the firmware load process */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) /* Prepare the demod, load the firmware, cleanup after load */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) /* Init PLL */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) cx24116_writereg(state, 0xE5, 0x00);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) cx24116_writereg(state, 0xF1, 0x08);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) cx24116_writereg(state, 0xF2, 0x13);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) /* Start PLL */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) cx24116_writereg(state, 0xe0, 0x03);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) cx24116_writereg(state, 0xe0, 0x00);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) /* Unknown */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) cx24116_writereg(state, CX24116_REG_CLKDIV, 0x46);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) cx24116_writereg(state, CX24116_REG_RATEDIV, 0x00);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) /* Unknown */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) cx24116_writereg(state, 0xF0, 0x03);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) cx24116_writereg(state, 0xF4, 0x81);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) cx24116_writereg(state, 0xF5, 0x00);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) cx24116_writereg(state, 0xF6, 0x00);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) /* Split firmware to the max I2C write len and write.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) * Writes whole firmware as one write when i2c_wr_max is set to 0. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) if (state->config->i2c_wr_max)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) max = state->config->i2c_wr_max;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) max = INT_MAX; /* enough for 32k firmware */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) for (remaining = fw->size; remaining > 0; remaining -= max - 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) len = remaining;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) if (len > max - 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) len = max - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) cx24116_writeregN(state, 0xF7, &fw->data[fw->size - remaining],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) cx24116_writereg(state, 0xF4, 0x10);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) cx24116_writereg(state, 0xF0, 0x00);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) cx24116_writereg(state, 0xF8, 0x06);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) /* Firmware CMD 10: VCO config */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) cmd.args[0x00] = CMD_SET_VCO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) cmd.args[0x01] = 0x05;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) cmd.args[0x02] = 0xdc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) cmd.args[0x03] = 0xda;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) cmd.args[0x04] = 0xae;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) cmd.args[0x05] = 0xaa;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) cmd.args[0x06] = 0x04;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) cmd.args[0x07] = 0x9d;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) cmd.args[0x08] = 0xfc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) cmd.args[0x09] = 0x06;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) cmd.len = 0x0a;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) ret = cx24116_cmd_execute(fe, &cmd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) if (ret != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) cx24116_writereg(state, CX24116_REG_SSTATUS, 0x00);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) /* Firmware CMD 14: Tuner config */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) cmd.args[0x00] = CMD_TUNERINIT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) cmd.args[0x01] = 0x00;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) cmd.args[0x02] = 0x00;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) cmd.len = 0x03;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) ret = cx24116_cmd_execute(fe, &cmd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) if (ret != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) cx24116_writereg(state, 0xe5, 0x00);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) /* Firmware CMD 13: MPEG config */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) cmd.args[0x00] = CMD_MPEGCONFIG;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) cmd.args[0x01] = 0x01;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) cmd.args[0x02] = 0x75;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) cmd.args[0x03] = 0x00;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) if (state->config->mpg_clk_pos_pol)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) cmd.args[0x04] = state->config->mpg_clk_pos_pol;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) cmd.args[0x04] = 0x02;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) cmd.args[0x05] = 0x00;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) cmd.len = 0x06;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) ret = cx24116_cmd_execute(fe, &cmd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) if (ret != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) /* Firmware CMD 35: Get firmware version */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) cmd.args[0x00] = CMD_UPDFWVERS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) cmd.len = 0x02;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) for (i = 0; i < 4; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) cmd.args[0x01] = i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) ret = cx24116_cmd_execute(fe, &cmd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) if (ret != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) vers[i] = cx24116_readreg(state, CX24116_REG_MAILBOX);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) printk(KERN_INFO "%s: FW version %i.%i.%i.%i\n", __func__,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) vers[0], vers[1], vers[2], vers[3]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) static int cx24116_read_status(struct dvb_frontend *fe, enum fe_status *status)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) struct cx24116_state *state = fe->demodulator_priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) int lock = cx24116_readreg(state, CX24116_REG_SSTATUS) &
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) CX24116_STATUS_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) dprintk("%s: status = 0x%02x\n", __func__, lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) *status = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) if (lock & CX24116_HAS_SIGNAL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) *status |= FE_HAS_SIGNAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) if (lock & CX24116_HAS_CARRIER)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) *status |= FE_HAS_CARRIER;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) if (lock & CX24116_HAS_VITERBI)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) *status |= FE_HAS_VITERBI;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) if (lock & CX24116_HAS_SYNCLOCK)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) *status |= FE_HAS_SYNC | FE_HAS_LOCK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) static int cx24116_read_ber(struct dvb_frontend *fe, u32 *ber)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) struct cx24116_state *state = fe->demodulator_priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) dprintk("%s()\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) *ber = (cx24116_readreg(state, CX24116_REG_BER24) << 24) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) (cx24116_readreg(state, CX24116_REG_BER16) << 16) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) (cx24116_readreg(state, CX24116_REG_BER8) << 8) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) cx24116_readreg(state, CX24116_REG_BER0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) /* TODO Determine function and scale appropriately */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) static int cx24116_read_signal_strength(struct dvb_frontend *fe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711) u16 *signal_strength)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) struct cx24116_state *state = fe->demodulator_priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714) struct cx24116_cmd cmd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) u16 sig_reading;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) dprintk("%s()\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) /* Firmware CMD 19: Get AGC */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) cmd.args[0x00] = CMD_GETAGC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) cmd.len = 0x01;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723) ret = cx24116_cmd_execute(fe, &cmd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) if (ret != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727) sig_reading =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) (cx24116_readreg(state,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729) CX24116_REG_SSTATUS) & CX24116_SIGNAL_MASK) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730) (cx24116_readreg(state, CX24116_REG_SIGNAL) << 6);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) *signal_strength = 0 - sig_reading;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733) dprintk("%s: raw / cooked = 0x%04x / 0x%04x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) __func__, sig_reading, *signal_strength);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739) /* SNR (0..100)% = (sig & 0xf0) * 10 + (sig & 0x0f) * 10 / 16 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740) static int cx24116_read_snr_pct(struct dvb_frontend *fe, u16 *snr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742) struct cx24116_state *state = fe->demodulator_priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) u8 snr_reading;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744) static const u32 snr_tab[] = { /* 10 x Table (rounded up) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) 0x00000, 0x0199A, 0x03333, 0x04ccD, 0x06667,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746) 0x08000, 0x0999A, 0x0b333, 0x0cccD, 0x0e667,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747) 0x10000, 0x1199A, 0x13333, 0x14ccD, 0x16667,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748) 0x18000 };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) dprintk("%s()\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752) snr_reading = cx24116_readreg(state, CX24116_REG_QUALITY0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754) if (snr_reading >= 0xa0 /* 100% */)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755) *snr = 0xffff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757) *snr = snr_tab[(snr_reading & 0xf0) >> 4] +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758) (snr_tab[(snr_reading & 0x0f)] >> 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760) dprintk("%s: raw / cooked = 0x%02x / 0x%04x\n", __func__,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761) snr_reading, *snr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766) /* The reelbox patches show the value in the registers represents
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767) * ESNO, from 0->30db (values 0->300). We provide this value by
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768) * default.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770) static int cx24116_read_snr_esno(struct dvb_frontend *fe, u16 *snr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772) struct cx24116_state *state = fe->demodulator_priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774) dprintk("%s()\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776) *snr = cx24116_readreg(state, CX24116_REG_QUALITY8) << 8 |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777) cx24116_readreg(state, CX24116_REG_QUALITY0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779) dprintk("%s: raw 0x%04x\n", __func__, *snr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784) static int cx24116_read_snr(struct dvb_frontend *fe, u16 *snr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786) if (esno_snr == 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787) return cx24116_read_snr_esno(fe, snr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789) return cx24116_read_snr_pct(fe, snr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792) static int cx24116_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794) struct cx24116_state *state = fe->demodulator_priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796) dprintk("%s()\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798) *ucblocks = (cx24116_readreg(state, CX24116_REG_UCB8) << 8) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799) cx24116_readreg(state, CX24116_REG_UCB0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804) /* Overwrite the current tuning params, we are about to tune */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805) static void cx24116_clone_params(struct dvb_frontend *fe)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807) struct cx24116_state *state = fe->demodulator_priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808) state->dcur = state->dnxt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811) /* Wait for LNB */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812) static int cx24116_wait_for_lnb(struct dvb_frontend *fe)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814) struct cx24116_state *state = fe->demodulator_priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817) dprintk("%s() qstatus = 0x%02x\n", __func__,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818) cx24116_readreg(state, CX24116_REG_QSTATUS));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820) /* Wait for up to 300 ms */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821) for (i = 0; i < 30 ; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822) if (cx24116_readreg(state, CX24116_REG_QSTATUS) & 0x20)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824) msleep(10);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827) dprintk("%s(): LNB not ready\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829) return -ETIMEDOUT; /* -EBUSY ? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832) static int cx24116_set_voltage(struct dvb_frontend *fe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833) enum fe_sec_voltage voltage)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835) struct cx24116_cmd cmd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838) dprintk("%s: %s\n", __func__,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839) voltage == SEC_VOLTAGE_13 ? "SEC_VOLTAGE_13" :
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840) voltage == SEC_VOLTAGE_18 ? "SEC_VOLTAGE_18" : "??");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842) /* Wait for LNB ready */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843) ret = cx24116_wait_for_lnb(fe);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844) if (ret != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847) /* Wait for voltage/min repeat delay */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848) msleep(100);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850) cmd.args[0x00] = CMD_LNBDCLEVEL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 851) cmd.args[0x01] = (voltage == SEC_VOLTAGE_18 ? 0x01 : 0x00);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852) cmd.len = 0x02;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 853)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854) /* Min delay time before DiSEqC send */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 855) msleep(15);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 856)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 857) return cx24116_cmd_execute(fe, &cmd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 858) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 859)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 860) static int cx24116_set_tone(struct dvb_frontend *fe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 861) enum fe_sec_tone_mode tone)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 862) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 863) struct cx24116_cmd cmd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 864) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 865)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 866) dprintk("%s(%d)\n", __func__, tone);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 867) if ((tone != SEC_TONE_ON) && (tone != SEC_TONE_OFF)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 868) printk(KERN_ERR "%s: Invalid, tone=%d\n", __func__, tone);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 869) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 870) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 871)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 872) /* Wait for LNB ready */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 873) ret = cx24116_wait_for_lnb(fe);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 874) if (ret != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 875) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 876)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 877) /* Min delay time after DiSEqC send */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 878) msleep(15); /* XXX determine is FW does this, see send_diseqc/burst */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 879)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 880) /* Now we set the tone */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 881) cmd.args[0x00] = CMD_SET_TONE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 882) cmd.args[0x01] = 0x00;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 883) cmd.args[0x02] = 0x00;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 884)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 885) switch (tone) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 886) case SEC_TONE_ON:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 887) dprintk("%s: setting tone on\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 888) cmd.args[0x03] = 0x01;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 889) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 890) case SEC_TONE_OFF:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 891) dprintk("%s: setting tone off\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 892) cmd.args[0x03] = 0x00;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 893) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 894) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 895) cmd.len = 0x04;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 896)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 897) /* Min delay time before DiSEqC send */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 898) msleep(15); /* XXX determine is FW does this, see send_diseqc/burst */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 899)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 900) return cx24116_cmd_execute(fe, &cmd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 901) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 902)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 903) /* Initialise DiSEqC */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 904) static int cx24116_diseqc_init(struct dvb_frontend *fe)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 905) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 906) struct cx24116_state *state = fe->demodulator_priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 907) struct cx24116_cmd cmd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 908) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 909)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 910) /* Firmware CMD 20: LNB/DiSEqC config */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 911) cmd.args[0x00] = CMD_LNBCONFIG;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 912) cmd.args[0x01] = 0x00;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 913) cmd.args[0x02] = 0x10;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 914) cmd.args[0x03] = 0x00;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 915) cmd.args[0x04] = 0x8f;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 916) cmd.args[0x05] = 0x28;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 917) cmd.args[0x06] = (toneburst == CX24116_DISEQC_TONEOFF) ? 0x00 : 0x01;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 918) cmd.args[0x07] = 0x01;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 919) cmd.len = 0x08;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 920) ret = cx24116_cmd_execute(fe, &cmd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 921) if (ret != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 922) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 923)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 924) /* Prepare a DiSEqC command */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 925) state->dsec_cmd.args[0x00] = CMD_LNBSEND;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 926)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 927) /* DiSEqC burst */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 928) state->dsec_cmd.args[CX24116_DISEQC_BURST] = CX24116_DISEQC_MINI_A;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 929)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 930) /* Unknown */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 931) state->dsec_cmd.args[CX24116_DISEQC_ARG2_2] = 0x02;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 932) state->dsec_cmd.args[CX24116_DISEQC_ARG3_0] = 0x00;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 933) /* Continuation flag? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 934) state->dsec_cmd.args[CX24116_DISEQC_ARG4_0] = 0x00;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 935)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 936) /* DiSEqC message length */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 937) state->dsec_cmd.args[CX24116_DISEQC_MSGLEN] = 0x00;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 938)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 939) /* Command length */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 940) state->dsec_cmd.len = CX24116_DISEQC_MSGOFS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 941)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 942) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 943) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 944)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 945) /* Send DiSEqC message with derived burst (hack) || previous burst */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 946) static int cx24116_send_diseqc_msg(struct dvb_frontend *fe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 947) struct dvb_diseqc_master_cmd *d)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 948) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 949) struct cx24116_state *state = fe->demodulator_priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 950) int i, ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 951)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 952) /* Validate length */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 953) if (d->msg_len > sizeof(d->msg))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 954) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 955)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 956) /* Dump DiSEqC message */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 957) if (debug) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 958) printk(KERN_INFO "cx24116: %s(", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 959) for (i = 0 ; i < d->msg_len ;) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 960) printk(KERN_INFO "0x%02x", d->msg[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 961) if (++i < d->msg_len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 962) printk(KERN_INFO ", ");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 963) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 964) printk(") toneburst=%d\n", toneburst);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 965) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 966)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 967) /* DiSEqC message */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 968) for (i = 0; i < d->msg_len; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 969) state->dsec_cmd.args[CX24116_DISEQC_MSGOFS + i] = d->msg[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 970)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 971) /* DiSEqC message length */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 972) state->dsec_cmd.args[CX24116_DISEQC_MSGLEN] = d->msg_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 973)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 974) /* Command length */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 975) state->dsec_cmd.len = CX24116_DISEQC_MSGOFS +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 976) state->dsec_cmd.args[CX24116_DISEQC_MSGLEN];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 977)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 978) /* DiSEqC toneburst */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 979) if (toneburst == CX24116_DISEQC_MESGCACHE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 980) /* Message is cached */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 981) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 982)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 983) else if (toneburst == CX24116_DISEQC_TONEOFF)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 984) /* Message is sent without burst */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 985) state->dsec_cmd.args[CX24116_DISEQC_BURST] = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 986)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 987) else if (toneburst == CX24116_DISEQC_TONECACHE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 988) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 989) * Message is sent with derived else cached burst
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 990) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 991) * WRITE PORT GROUP COMMAND 38
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 992) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 993) * 0/A/A: E0 10 38 F0..F3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 994) * 1/B/B: E0 10 38 F4..F7
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 995) * 2/C/A: E0 10 38 F8..FB
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 996) * 3/D/B: E0 10 38 FC..FF
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 997) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 998) * databyte[3]= 8421:8421
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 999) * ABCD:WXYZ
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1000) * CLR :SET
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1001) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1002) * WX= PORT SELECT 0..3 (X=TONEBURST)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1003) * Y = VOLTAGE (0=13V, 1=18V)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1004) * Z = BAND (0=LOW, 1=HIGH(22K))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1005) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1006) if (d->msg_len >= 4 && d->msg[2] == 0x38)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1007) state->dsec_cmd.args[CX24116_DISEQC_BURST] =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1008) ((d->msg[3] & 4) >> 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1009) if (debug)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1010) dprintk("%s burst=%d\n", __func__,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1011) state->dsec_cmd.args[CX24116_DISEQC_BURST]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1012) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1013)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1014) /* Wait for LNB ready */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1015) ret = cx24116_wait_for_lnb(fe);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1016) if (ret != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1017) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1018)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1019) /* Wait for voltage/min repeat delay */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1020) msleep(100);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1021)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1022) /* Command */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1023) ret = cx24116_cmd_execute(fe, &state->dsec_cmd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1024) if (ret != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1025) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1026) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1027) * Wait for send
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1028) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1029) * Eutelsat spec:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1030) * >15ms delay + (XXX determine if FW does this, see set_tone)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1031) * 13.5ms per byte +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1032) * >15ms delay +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1033) * 12.5ms burst +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1034) * >15ms delay (XXX determine if FW does this, see set_tone)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1035) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1036) msleep((state->dsec_cmd.args[CX24116_DISEQC_MSGLEN] << 4) +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1037) ((toneburst == CX24116_DISEQC_TONEOFF) ? 30 : 60));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1038)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1039) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1040) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1041)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1042) /* Send DiSEqC burst */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1043) static int cx24116_diseqc_send_burst(struct dvb_frontend *fe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1044) enum fe_sec_mini_cmd burst)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1045) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1046) struct cx24116_state *state = fe->demodulator_priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1047) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1048)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1049) dprintk("%s(%d) toneburst=%d\n", __func__, burst, toneburst);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1050)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1051) /* DiSEqC burst */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1052) if (burst == SEC_MINI_A)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1053) state->dsec_cmd.args[CX24116_DISEQC_BURST] =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1054) CX24116_DISEQC_MINI_A;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1055) else if (burst == SEC_MINI_B)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1056) state->dsec_cmd.args[CX24116_DISEQC_BURST] =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1057) CX24116_DISEQC_MINI_B;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1058) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1059) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1060)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1061) /* DiSEqC toneburst */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1062) if (toneburst != CX24116_DISEQC_MESGCACHE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1063) /* Burst is cached */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1064) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1065)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1066) /* Burst is to be sent with cached message */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1067)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1068) /* Wait for LNB ready */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1069) ret = cx24116_wait_for_lnb(fe);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1070) if (ret != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1071) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1072)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1073) /* Wait for voltage/min repeat delay */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1074) msleep(100);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1075)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1076) /* Command */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1077) ret = cx24116_cmd_execute(fe, &state->dsec_cmd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1078) if (ret != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1079) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1080)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1081) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1082) * Wait for send
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1083) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1084) * Eutelsat spec:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1085) * >15ms delay + (XXX determine if FW does this, see set_tone)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1086) * 13.5ms per byte +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1087) * >15ms delay +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1088) * 12.5ms burst +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1089) * >15ms delay (XXX determine if FW does this, see set_tone)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1090) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1091) msleep((state->dsec_cmd.args[CX24116_DISEQC_MSGLEN] << 4) + 60);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1092)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1093) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1094) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1095)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1096) static void cx24116_release(struct dvb_frontend *fe)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1097) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1098) struct cx24116_state *state = fe->demodulator_priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1099) dprintk("%s\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1100) kfree(state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1101) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1102)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1103) static const struct dvb_frontend_ops cx24116_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1104)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1105) struct dvb_frontend *cx24116_attach(const struct cx24116_config *config,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1106) struct i2c_adapter *i2c)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1107) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1108) struct cx24116_state *state;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1109) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1110)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1111) dprintk("%s\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1112)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1113) /* allocate memory for the internal state */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1114) state = kzalloc(sizeof(*state), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1115) if (state == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1116) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1117)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1118) state->config = config;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1119) state->i2c = i2c;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1120)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1121) /* check if the demod is present */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1122) ret = (cx24116_readreg(state, 0xFF) << 8) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1123) cx24116_readreg(state, 0xFE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1124) if (ret != 0x0501) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1125) kfree(state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1126) printk(KERN_INFO "Invalid probe, probably not a CX24116 device\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1127) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1128) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1129)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1130) /* create dvb_frontend */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1131) memcpy(&state->frontend.ops, &cx24116_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1132) sizeof(struct dvb_frontend_ops));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1133) state->frontend.demodulator_priv = state;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1134) return &state->frontend;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1135) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1136) EXPORT_SYMBOL(cx24116_attach);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1137)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1138) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1139) * Initialise or wake up device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1140) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1141) * Power config will reset and load initial firmware if required
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1142) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1143) static int cx24116_initfe(struct dvb_frontend *fe)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1144) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1145) struct cx24116_state *state = fe->demodulator_priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1146) struct cx24116_cmd cmd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1147) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1148)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1149) dprintk("%s()\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1150)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1151) /* Power on */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1152) cx24116_writereg(state, 0xe0, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1153) cx24116_writereg(state, 0xe1, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1154) cx24116_writereg(state, 0xea, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1155)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1156) /* Firmware CMD 36: Power config */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1157) cmd.args[0x00] = CMD_TUNERSLEEP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1158) cmd.args[0x01] = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1159) cmd.len = 0x02;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1160) ret = cx24116_cmd_execute(fe, &cmd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1161) if (ret != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1162) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1163)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1164) ret = cx24116_diseqc_init(fe);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1165) if (ret != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1166) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1167)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1168) /* HVR-4000 needs this */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1169) return cx24116_set_voltage(fe, SEC_VOLTAGE_13);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1170) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1171)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1172) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1173) * Put device to sleep
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1174) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1175) static int cx24116_sleep(struct dvb_frontend *fe)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1176) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1177) struct cx24116_state *state = fe->demodulator_priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1178) struct cx24116_cmd cmd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1179) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1180)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1181) dprintk("%s()\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1182)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1183) /* Firmware CMD 36: Power config */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1184) cmd.args[0x00] = CMD_TUNERSLEEP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1185) cmd.args[0x01] = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1186) cmd.len = 0x02;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1187) ret = cx24116_cmd_execute(fe, &cmd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1188) if (ret != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1189) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1190)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1191) /* Power off (Shutdown clocks) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1192) cx24116_writereg(state, 0xea, 0xff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1193) cx24116_writereg(state, 0xe1, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1194) cx24116_writereg(state, 0xe0, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1195)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1196) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1197) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1198)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1199) /* dvb-core told us to tune, the tv property cache will be complete,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1200) * it's safe for is to pull values and use them for tuning purposes.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1201) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1202) static int cx24116_set_frontend(struct dvb_frontend *fe)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1203) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1204) struct cx24116_state *state = fe->demodulator_priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1205) struct dtv_frontend_properties *c = &fe->dtv_property_cache;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1206) struct cx24116_cmd cmd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1207) enum fe_status tunerstat;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1208) int i, status, ret, retune = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1209)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1210) dprintk("%s()\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1211)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1212) switch (c->delivery_system) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1213) case SYS_DVBS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1214) dprintk("%s: DVB-S delivery system selected\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1215)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1216) /* Only QPSK is supported for DVB-S */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1217) if (c->modulation != QPSK) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1218) dprintk("%s: unsupported modulation selected (%d)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1219) __func__, c->modulation);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1220) return -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1221) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1222)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1223) /* Pilot doesn't exist in DVB-S, turn bit off */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1224) state->dnxt.pilot_val = CX24116_PILOT_OFF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1225)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1226) /* DVB-S only supports 0.35 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1227) if (c->rolloff != ROLLOFF_35) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1228) dprintk("%s: unsupported rolloff selected (%d)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1229) __func__, c->rolloff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1230) return -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1231) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1232) state->dnxt.rolloff_val = CX24116_ROLLOFF_035;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1233) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1234)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1235) case SYS_DVBS2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1236) dprintk("%s: DVB-S2 delivery system selected\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1237)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1238) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1239) * NBC 8PSK/QPSK with DVB-S is supported for DVB-S2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1240) * but not hardware auto detection
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1241) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1242) if (c->modulation != PSK_8 && c->modulation != QPSK) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1243) dprintk("%s: unsupported modulation selected (%d)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1244) __func__, c->modulation);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1245) return -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1246) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1247)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1248) switch (c->pilot) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1249) case PILOT_AUTO: /* Not supported but emulated */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1250) state->dnxt.pilot_val = (c->modulation == QPSK)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1251) ? CX24116_PILOT_OFF : CX24116_PILOT_ON;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1252) retune++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1253) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1254) case PILOT_OFF:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1255) state->dnxt.pilot_val = CX24116_PILOT_OFF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1256) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1257) case PILOT_ON:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1258) state->dnxt.pilot_val = CX24116_PILOT_ON;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1259) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1260) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1261) dprintk("%s: unsupported pilot mode selected (%d)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1262) __func__, c->pilot);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1263) return -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1264) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1265)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1266) switch (c->rolloff) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1267) case ROLLOFF_20:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1268) state->dnxt.rolloff_val = CX24116_ROLLOFF_020;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1269) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1270) case ROLLOFF_25:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1271) state->dnxt.rolloff_val = CX24116_ROLLOFF_025;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1272) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1273) case ROLLOFF_35:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1274) state->dnxt.rolloff_val = CX24116_ROLLOFF_035;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1275) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1276) case ROLLOFF_AUTO: /* Rolloff must be explicit */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1277) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1278) dprintk("%s: unsupported rolloff selected (%d)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1279) __func__, c->rolloff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1280) return -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1281) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1282) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1283)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1284) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1285) dprintk("%s: unsupported delivery system selected (%d)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1286) __func__, c->delivery_system);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1287) return -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1288) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1289) state->dnxt.delsys = c->delivery_system;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1290) state->dnxt.modulation = c->modulation;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1291) state->dnxt.frequency = c->frequency;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1292) state->dnxt.pilot = c->pilot;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1293) state->dnxt.rolloff = c->rolloff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1294)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1295) ret = cx24116_set_inversion(state, c->inversion);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1296) if (ret != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1297) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1298)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1299) /* FEC_NONE/AUTO for DVB-S2 is not supported and detected here */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1300) ret = cx24116_set_fec(state, c->delivery_system, c->modulation, c->fec_inner);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1301) if (ret != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1302) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1303)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1304) ret = cx24116_set_symbolrate(state, c->symbol_rate);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1305) if (ret != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1306) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1307)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1308) /* discard the 'current' tuning parameters and prepare to tune */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1309) cx24116_clone_params(fe);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1310)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1311) dprintk("%s: delsys = %d\n", __func__, state->dcur.delsys);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1312) dprintk("%s: modulation = %d\n", __func__, state->dcur.modulation);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1313) dprintk("%s: frequency = %d\n", __func__, state->dcur.frequency);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1314) dprintk("%s: pilot = %d (val = 0x%02x)\n", __func__,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1315) state->dcur.pilot, state->dcur.pilot_val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1316) dprintk("%s: retune = %d\n", __func__, retune);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1317) dprintk("%s: rolloff = %d (val = 0x%02x)\n", __func__,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1318) state->dcur.rolloff, state->dcur.rolloff_val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1319) dprintk("%s: symbol_rate = %d\n", __func__, state->dcur.symbol_rate);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1320) dprintk("%s: FEC = %d (mask/val = 0x%02x/0x%02x)\n", __func__,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1321) state->dcur.fec, state->dcur.fec_mask, state->dcur.fec_val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1322) dprintk("%s: Inversion = %d (val = 0x%02x)\n", __func__,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1323) state->dcur.inversion, state->dcur.inversion_val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1324)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1325) /* This is also done in advise/acquire on HVR4000 but not on LITE */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1326) if (state->config->set_ts_params)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1327) state->config->set_ts_params(fe, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1328)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1329) /* Set/Reset B/W */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1330) cmd.args[0x00] = CMD_BANDWIDTH;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1331) cmd.args[0x01] = 0x01;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1332) cmd.len = 0x02;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1333) ret = cx24116_cmd_execute(fe, &cmd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1334) if (ret != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1335) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1336)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1337) /* Prepare a tune request */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1338) cmd.args[0x00] = CMD_TUNEREQUEST;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1339)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1340) /* Frequency */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1341) cmd.args[0x01] = (state->dcur.frequency & 0xff0000) >> 16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1342) cmd.args[0x02] = (state->dcur.frequency & 0x00ff00) >> 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1343) cmd.args[0x03] = (state->dcur.frequency & 0x0000ff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1344)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1345) /* Symbol Rate */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1346) cmd.args[0x04] = ((state->dcur.symbol_rate / 1000) & 0xff00) >> 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1347) cmd.args[0x05] = ((state->dcur.symbol_rate / 1000) & 0x00ff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1348)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1349) /* Automatic Inversion */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1350) cmd.args[0x06] = state->dcur.inversion_val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1351)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1352) /* Modulation / FEC / Pilot */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1353) cmd.args[0x07] = state->dcur.fec_val | state->dcur.pilot_val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1354)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1355) cmd.args[0x08] = CX24116_SEARCH_RANGE_KHZ >> 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1356) cmd.args[0x09] = CX24116_SEARCH_RANGE_KHZ & 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1357) cmd.args[0x0a] = 0x00;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1358) cmd.args[0x0b] = 0x00;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1359) cmd.args[0x0c] = state->dcur.rolloff_val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1360) cmd.args[0x0d] = state->dcur.fec_mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1361)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1362) if (state->dcur.symbol_rate > 30000000) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1363) cmd.args[0x0e] = 0x04;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1364) cmd.args[0x0f] = 0x00;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1365) cmd.args[0x10] = 0x01;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1366) cmd.args[0x11] = 0x77;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1367) cmd.args[0x12] = 0x36;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1368) cx24116_writereg(state, CX24116_REG_CLKDIV, 0x44);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1369) cx24116_writereg(state, CX24116_REG_RATEDIV, 0x01);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1370) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1371) cmd.args[0x0e] = 0x06;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1372) cmd.args[0x0f] = 0x00;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1373) cmd.args[0x10] = 0x00;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1374) cmd.args[0x11] = 0xFA;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1375) cmd.args[0x12] = 0x24;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1376) cx24116_writereg(state, CX24116_REG_CLKDIV, 0x46);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1377) cx24116_writereg(state, CX24116_REG_RATEDIV, 0x00);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1378) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1379)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1380) cmd.len = 0x13;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1381)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1382) /* We need to support pilot and non-pilot tuning in the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1383) * driver automatically. This is a workaround for because
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1384) * the demod does not support autodetect.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1385) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1386) do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1387) /* Reset status register */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1388) status = cx24116_readreg(state, CX24116_REG_SSTATUS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1389) & CX24116_SIGNAL_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1390) cx24116_writereg(state, CX24116_REG_SSTATUS, status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1391)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1392) /* Tune */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1393) ret = cx24116_cmd_execute(fe, &cmd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1394) if (ret != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1395) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1396)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1397) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1398) * Wait for up to 500 ms before retrying
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1399) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1400) * If we are able to tune then generally it occurs within 100ms.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1401) * If it takes longer, try a different toneburst setting.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1402) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1403) for (i = 0; i < 50 ; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1404) cx24116_read_status(fe, &tunerstat);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1405) status = tunerstat & (FE_HAS_SIGNAL | FE_HAS_SYNC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1406) if (status == (FE_HAS_SIGNAL | FE_HAS_SYNC)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1407) dprintk("%s: Tuned\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1408) goto tuned;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1409) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1410) msleep(10);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1411) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1412)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1413) dprintk("%s: Not tuned\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1414)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1415) /* Toggle pilot bit when in auto-pilot */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1416) if (state->dcur.pilot == PILOT_AUTO)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1417) cmd.args[0x07] ^= CX24116_PILOT_ON;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1418) } while (--retune);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1419)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1420) tuned: /* Set/Reset B/W */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1421) cmd.args[0x00] = CMD_BANDWIDTH;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1422) cmd.args[0x01] = 0x00;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1423) cmd.len = 0x02;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1424) return cx24116_cmd_execute(fe, &cmd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1425) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1426)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1427) static int cx24116_tune(struct dvb_frontend *fe, bool re_tune,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1428) unsigned int mode_flags, unsigned int *delay, enum fe_status *status)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1429) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1430) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1431) * It is safe to discard "params" here, as the DVB core will sync
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1432) * fe->dtv_property_cache with fepriv->parameters_in, where the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1433) * DVBv3 params are stored. The only practical usage for it indicate
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1434) * that re-tuning is needed, e. g. (fepriv->state & FESTATE_RETUNE) is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1435) * true.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1436) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1437)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1438) *delay = HZ / 5;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1439) if (re_tune) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1440) int ret = cx24116_set_frontend(fe);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1441) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1442) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1443) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1444) return cx24116_read_status(fe, status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1445) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1446)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1447) static enum dvbfe_algo cx24116_get_algo(struct dvb_frontend *fe)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1448) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1449) return DVBFE_ALGO_HW;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1450) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1451)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1452) static const struct dvb_frontend_ops cx24116_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1453) .delsys = { SYS_DVBS, SYS_DVBS2 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1454) .info = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1455) .name = "Conexant CX24116/CX24118",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1456) .frequency_min_hz = 950 * MHz,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1457) .frequency_max_hz = 2150 * MHz,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1458) .frequency_stepsize_hz = 1011 * kHz,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1459) .frequency_tolerance_hz = 5 * MHz,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1460) .symbol_rate_min = 1000000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1461) .symbol_rate_max = 45000000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1462) .caps = FE_CAN_INVERSION_AUTO |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1463) FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1464) FE_CAN_FEC_4_5 | FE_CAN_FEC_5_6 | FE_CAN_FEC_6_7 |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1465) FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1466) FE_CAN_2G_MODULATION |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1467) FE_CAN_QPSK | FE_CAN_RECOVER
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1468) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1469)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1470) .release = cx24116_release,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1471)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1472) .init = cx24116_initfe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1473) .sleep = cx24116_sleep,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1474) .read_status = cx24116_read_status,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1475) .read_ber = cx24116_read_ber,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1476) .read_signal_strength = cx24116_read_signal_strength,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1477) .read_snr = cx24116_read_snr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1478) .read_ucblocks = cx24116_read_ucblocks,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1479) .set_tone = cx24116_set_tone,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1480) .set_voltage = cx24116_set_voltage,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1481) .diseqc_send_master_cmd = cx24116_send_diseqc_msg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1482) .diseqc_send_burst = cx24116_diseqc_send_burst,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1483) .get_frontend_algo = cx24116_get_algo,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1484) .tune = cx24116_tune,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1485)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1486) .set_frontend = cx24116_set_frontend,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1487) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1488)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1489) MODULE_DESCRIPTION("DVB Frontend module for Conexant cx24116/cx24118 hardware");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1490) MODULE_AUTHOR("Steven Toth");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1491) MODULE_LICENSE("GPL");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1492)