^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 cx24117/cx24132 - Dual 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) 2013 Luis Alves <ljalvs@gmail.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) July, 6th 2013
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) First release based on cx24116 driver by:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) Steven Toth and Georg Acher, Darron Broad, Igor Liplianin
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) Cards currently supported:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) TBS6980 - Dual DVBS/S2 PCIe card
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) TBS6981 - Dual DVBS/S2 PCIe card
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include <linux/moduleparam.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include <linux/init.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include <linux/firmware.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #include "tuner-i2c.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #include <media/dvb_frontend.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #include "cx24117.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) #define CX24117_DEFAULT_FIRMWARE "dvb-fe-cx24117.fw"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) #define CX24117_SEARCH_RANGE_KHZ 5000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) /* known registers */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) #define CX24117_REG_COMMAND (0x00) /* command buffer */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) #define CX24117_REG_EXECUTE (0x1f) /* execute command */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) #define CX24117_REG_FREQ3_0 (0x34) /* frequency */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) #define CX24117_REG_FREQ2_0 (0x35)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) #define CX24117_REG_FREQ1_0 (0x36)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) #define CX24117_REG_STATE0 (0x39)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) #define CX24117_REG_SSTATUS0 (0x3a) /* demod0 signal high / status */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) #define CX24117_REG_SIGNAL0 (0x3b)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) #define CX24117_REG_FREQ5_0 (0x3c) /* +-freq */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) #define CX24117_REG_FREQ6_0 (0x3d)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) #define CX24117_REG_SRATE2_0 (0x3e) /* +- 1000 * srate */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) #define CX24117_REG_SRATE1_0 (0x3f)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) #define CX24117_REG_QUALITY2_0 (0x40)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) #define CX24117_REG_QUALITY1_0 (0x41)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) #define CX24117_REG_BER4_0 (0x47)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) #define CX24117_REG_BER3_0 (0x48)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) #define CX24117_REG_BER2_0 (0x49)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) #define CX24117_REG_BER1_0 (0x4a)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) #define CX24117_REG_DVBS_UCB2_0 (0x4b)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) #define CX24117_REG_DVBS_UCB1_0 (0x4c)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) #define CX24117_REG_DVBS2_UCB2_0 (0x50)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) #define CX24117_REG_DVBS2_UCB1_0 (0x51)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) #define CX24117_REG_QSTATUS0 (0x93)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) #define CX24117_REG_CLKDIV0 (0xe6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) #define CX24117_REG_RATEDIV0 (0xf0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) #define CX24117_REG_FREQ3_1 (0x55) /* frequency */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) #define CX24117_REG_FREQ2_1 (0x56)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) #define CX24117_REG_FREQ1_1 (0x57)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) #define CX24117_REG_STATE1 (0x5a)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) #define CX24117_REG_SSTATUS1 (0x5b) /* demod1 signal high / status */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) #define CX24117_REG_SIGNAL1 (0x5c)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) #define CX24117_REG_FREQ5_1 (0x5d) /* +- freq */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) #define CX24117_REG_FREQ4_1 (0x5e)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) #define CX24117_REG_SRATE2_1 (0x5f)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) #define CX24117_REG_SRATE1_1 (0x60)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) #define CX24117_REG_QUALITY2_1 (0x61)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) #define CX24117_REG_QUALITY1_1 (0x62)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) #define CX24117_REG_BER4_1 (0x68)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) #define CX24117_REG_BER3_1 (0x69)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) #define CX24117_REG_BER2_1 (0x6a)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) #define CX24117_REG_BER1_1 (0x6b)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) #define CX24117_REG_DVBS_UCB2_1 (0x6c)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) #define CX24117_REG_DVBS_UCB1_1 (0x6d)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) #define CX24117_REG_DVBS2_UCB2_1 (0x71)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) #define CX24117_REG_DVBS2_UCB1_1 (0x72)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) #define CX24117_REG_QSTATUS1 (0x9f)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) #define CX24117_REG_CLKDIV1 (0xe7)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) #define CX24117_REG_RATEDIV1 (0xf1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) /* arg buffer size */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) #define CX24117_ARGLEN (0x1e)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) /* rolloff */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) #define CX24117_ROLLOFF_020 (0x00)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) #define CX24117_ROLLOFF_025 (0x01)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) #define CX24117_ROLLOFF_035 (0x02)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) /* pilot bit */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) #define CX24117_PILOT_OFF (0x00)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) #define CX24117_PILOT_ON (0x40)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) #define CX24117_PILOT_AUTO (0x80)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) /* signal status */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) #define CX24117_HAS_SIGNAL (0x01)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) #define CX24117_HAS_CARRIER (0x02)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) #define CX24117_HAS_VITERBI (0x04)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) #define CX24117_HAS_SYNCLOCK (0x08)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) #define CX24117_STATUS_MASK (0x0f)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) #define CX24117_SIGNAL_MASK (0xc0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105)
^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 CX24117_DISEQC_DEMOD (1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) #define CX24117_DISEQC_BURST (2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) #define CX24117_DISEQC_ARG3_2 (3) /* unknown value=2 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) #define CX24117_DISEQC_ARG4_0 (4) /* unknown value=0 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) #define CX24117_DISEQC_ARG5_0 (5) /* unknown value=0 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) #define CX24117_DISEQC_MSGLEN (6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) #define CX24117_DISEQC_MSGOFS (7)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) /* DiSEqC burst */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) #define CX24117_DISEQC_MINI_A (0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) #define CX24117_DISEQC_MINI_B (1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) #define CX24117_PNE (0) /* 0 disabled / 2 enabled */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) #define CX24117_OCC (1) /* 0 disabled / 1 enabled */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) enum cmds {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) CMD_SET_VCOFREQ = 0x10,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) CMD_TUNEREQUEST = 0x11,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) CMD_GLOBAL_MPEGCFG = 0x13,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) CMD_MPEGCFG = 0x14,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) CMD_TUNERINIT = 0x15,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) CMD_GET_SRATE = 0x18,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) CMD_SET_GOLDCODE = 0x19,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) CMD_GET_AGCACC = 0x1a,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) CMD_DEMODINIT = 0x1b,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) CMD_GETCTLACC = 0x1c,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) CMD_LNBCONFIG = 0x20,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) CMD_LNBSEND = 0x21,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) CMD_LNBDCLEVEL = 0x22,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) CMD_LNBPCBCONFIG = 0x23,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) CMD_LNBSENDTONEBST = 0x24,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) CMD_LNBUPDREPLY = 0x25,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) CMD_SET_GPIOMODE = 0x30,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) CMD_SET_GPIOEN = 0x31,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) CMD_SET_GPIODIR = 0x32,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) CMD_SET_GPIOOUT = 0x33,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) CMD_ENABLERSCORR = 0x34,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) CMD_FWVERSION = 0x35,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) CMD_SET_SLEEPMODE = 0x36,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) CMD_BERCTRL = 0x3c,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) CMD_EVENTCTRL = 0x3d,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) static LIST_HEAD(hybrid_tuner_instance_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) static DEFINE_MUTEX(cx24117_list_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) /* The Demod/Tuner can't easily provide these, we cache them */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) struct cx24117_tuning {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) u32 frequency;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) u32 symbol_rate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) enum fe_spectral_inversion inversion;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) enum fe_code_rate fec;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) enum fe_delivery_system delsys;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) enum fe_modulation modulation;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) enum fe_pilot pilot;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) enum fe_rolloff rolloff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) /* Demod values */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) u8 fec_val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) u8 fec_mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) u8 inversion_val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) u8 pilot_val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) u8 rolloff_val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) /* Basic commands that are sent to the firmware */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) struct cx24117_cmd {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) u8 len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) u8 args[CX24117_ARGLEN];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) /* common to both fe's */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) struct cx24117_priv {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) u8 demod_address;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) struct i2c_adapter *i2c;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) u8 skip_fw_load;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) struct mutex fe_lock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) /* Used for sharing this struct between demods */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) struct tuner_i2c_props i2c_props;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) struct list_head hybrid_tuner_instance_list;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) /* one per each fe */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) struct cx24117_state {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) struct cx24117_priv *priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) struct dvb_frontend frontend;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) struct cx24117_tuning dcur;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) struct cx24117_tuning dnxt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) struct cx24117_cmd dsec_cmd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) int demod;
^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) /* modfec (modulation and FEC) lookup table */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) /* Check cx24116.c for a detailed description of each field */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) static struct cx24117_modfec {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) enum fe_delivery_system delivery_system;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) enum fe_modulation modulation;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) enum fe_code_rate fec;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) u8 mask; /* In DVBS mode this is used to autodetect */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) u8 val; /* Passed to the firmware to indicate mode selection */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) } cx24117_modfec_modes[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) /* QPSK. For unknown rates we set hardware to auto detect 0xfe 0x30 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) /*mod fec mask val */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) { SYS_DVBS, QPSK, FEC_NONE, 0xfe, 0x30 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) { SYS_DVBS, QPSK, FEC_1_2, 0x02, 0x2e }, /* 00000010 00101110 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) { SYS_DVBS, QPSK, FEC_2_3, 0x04, 0x2f }, /* 00000100 00101111 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) { SYS_DVBS, QPSK, FEC_3_4, 0x08, 0x30 }, /* 00001000 00110000 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) { SYS_DVBS, QPSK, FEC_4_5, 0xfe, 0x30 }, /* 000?0000 ? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) { SYS_DVBS, QPSK, FEC_5_6, 0x20, 0x31 }, /* 00100000 00110001 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) { SYS_DVBS, QPSK, FEC_6_7, 0xfe, 0x30 }, /* 0?000000 ? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) { SYS_DVBS, QPSK, FEC_7_8, 0x80, 0x32 }, /* 10000000 00110010 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) { SYS_DVBS, QPSK, FEC_8_9, 0xfe, 0x30 }, /* 0000000? ? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) { SYS_DVBS, QPSK, FEC_AUTO, 0xfe, 0x30 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) /* NBC-QPSK */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) { SYS_DVBS2, QPSK, FEC_NONE, 0x00, 0x00 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) { SYS_DVBS2, QPSK, FEC_1_2, 0x00, 0x04 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) { SYS_DVBS2, QPSK, FEC_3_5, 0x00, 0x05 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) { SYS_DVBS2, QPSK, FEC_2_3, 0x00, 0x06 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) { SYS_DVBS2, QPSK, FEC_3_4, 0x00, 0x07 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) { SYS_DVBS2, QPSK, FEC_4_5, 0x00, 0x08 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) { SYS_DVBS2, QPSK, FEC_5_6, 0x00, 0x09 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) { SYS_DVBS2, QPSK, FEC_8_9, 0x00, 0x0a },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) { SYS_DVBS2, QPSK, FEC_9_10, 0x00, 0x0b },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) { SYS_DVBS2, QPSK, FEC_AUTO, 0x00, 0x00 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) /* 8PSK */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) { SYS_DVBS2, PSK_8, FEC_NONE, 0x00, 0x00 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) { SYS_DVBS2, PSK_8, FEC_3_5, 0x00, 0x0c },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) { SYS_DVBS2, PSK_8, FEC_2_3, 0x00, 0x0d },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) { SYS_DVBS2, PSK_8, FEC_3_4, 0x00, 0x0e },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) { SYS_DVBS2, PSK_8, FEC_5_6, 0x00, 0x0f },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) { SYS_DVBS2, PSK_8, FEC_8_9, 0x00, 0x10 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) { SYS_DVBS2, PSK_8, FEC_9_10, 0x00, 0x11 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) { SYS_DVBS2, PSK_8, FEC_AUTO, 0x00, 0x00 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) * 'val' can be found in the FECSTATUS register when tuning.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) * FECSTATUS will give the actual FEC in use if tuning was successful.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) */
^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)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) static int cx24117_writereg(struct cx24117_state *state, u8 reg, u8 data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) u8 buf[] = { reg, data };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) struct i2c_msg msg = { .addr = state->priv->demod_address,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) .flags = 0, .buf = buf, .len = 2 };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) dev_dbg(&state->priv->i2c->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) "%s() demod%d i2c wr @0x%02x=0x%02x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) __func__, state->demod, reg, data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) ret = i2c_transfer(state->priv->i2c, &msg, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) dev_warn(&state->priv->i2c->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) "%s: demod%d i2c wr err(%i) @0x%02x=0x%02x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) KBUILD_MODNAME, state->demod, ret, reg, data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) static int cx24117_writecmd(struct cx24117_state *state,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) struct cx24117_cmd *cmd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) struct i2c_msg msg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) u8 buf[CX24117_ARGLEN+1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) dev_dbg(&state->priv->i2c->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) "%s() demod%d i2c wr cmd len=%d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) __func__, state->demod, cmd->len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) buf[0] = CX24117_REG_COMMAND;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) memcpy(&buf[1], cmd->args, cmd->len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) msg.addr = state->priv->demod_address;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) msg.flags = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) msg.len = cmd->len+1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) msg.buf = buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) ret = i2c_transfer(state->priv->i2c, &msg, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) dev_warn(&state->priv->i2c->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) "%s: demod%d i2c wr cmd err(%i) len=%d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) KBUILD_MODNAME, state->demod, ret, cmd->len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) static int cx24117_readreg(struct cx24117_state *state, u8 reg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) u8 recv = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) struct i2c_msg msg[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) { .addr = state->priv->demod_address, .flags = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) .buf = ®, .len = 1 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) { .addr = state->priv->demod_address, .flags = I2C_M_RD,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) .buf = &recv, .len = 1 }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) ret = i2c_transfer(state->priv->i2c, msg, 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) dev_warn(&state->priv->i2c->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) "%s: demod%d i2c rd err(%d) @0x%x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) KBUILD_MODNAME, state->demod, ret, reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) dev_dbg(&state->priv->i2c->dev, "%s() demod%d i2c rd @0x%02x=0x%02x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) __func__, state->demod, reg, recv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) return recv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) static int cx24117_readregN(struct cx24117_state *state,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) u8 reg, u8 *buf, int len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) struct i2c_msg msg[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) { .addr = state->priv->demod_address, .flags = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) .buf = ®, .len = 1 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) { .addr = state->priv->demod_address, .flags = I2C_M_RD,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) .buf = buf, .len = len }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) ret = i2c_transfer(state->priv->i2c, msg, 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) dev_warn(&state->priv->i2c->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) "%s: demod%d i2c rd err(%d) @0x%x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) KBUILD_MODNAME, state->demod, ret, reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) static int cx24117_set_inversion(struct cx24117_state *state,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) enum fe_spectral_inversion inversion)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) dev_dbg(&state->priv->i2c->dev, "%s(%d) demod%d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) __func__, inversion, state->demod);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) switch (inversion) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) case INVERSION_OFF:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) state->dnxt.inversion_val = 0x00;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) case INVERSION_ON:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) state->dnxt.inversion_val = 0x04;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) case INVERSION_AUTO:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) state->dnxt.inversion_val = 0x0C;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) state->dnxt.inversion = inversion;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) static int cx24117_lookup_fecmod(struct cx24117_state *state,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) enum fe_delivery_system d, enum fe_modulation m, enum fe_code_rate f)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) int i, ret = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) dev_dbg(&state->priv->i2c->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) "%s(demod(0x%02x,0x%02x) demod%d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) __func__, m, f, state->demod);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) for (i = 0; i < ARRAY_SIZE(cx24117_modfec_modes); i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) if ((d == cx24117_modfec_modes[i].delivery_system) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) (m == cx24117_modfec_modes[i].modulation) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) (f == cx24117_modfec_modes[i].fec)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) ret = i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) static int cx24117_set_fec(struct cx24117_state *state,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) enum fe_delivery_system delsys,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) enum fe_modulation mod,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) enum fe_code_rate fec)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) dev_dbg(&state->priv->i2c->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) "%s(0x%02x,0x%02x) demod%d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) __func__, mod, fec, state->demod);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) ret = cx24117_lookup_fecmod(state, delsys, mod, fec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) state->dnxt.fec = fec;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) state->dnxt.fec_val = cx24117_modfec_modes[ret].val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) state->dnxt.fec_mask = cx24117_modfec_modes[ret].mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) dev_dbg(&state->priv->i2c->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) "%s() demod%d mask/val = 0x%02x/0x%02x\n", __func__,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) state->demod, state->dnxt.fec_mask, state->dnxt.fec_val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) static int cx24117_set_symbolrate(struct cx24117_state *state, u32 rate)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) dev_dbg(&state->priv->i2c->dev, "%s(%d) demod%d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) __func__, rate, state->demod);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) state->dnxt.symbol_rate = rate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) dev_dbg(&state->priv->i2c->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) "%s() demod%d symbol_rate = %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) __func__, state->demod, rate);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) static int cx24117_load_firmware(struct dvb_frontend *fe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) const struct firmware *fw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) static int cx24117_firmware_ondemand(struct dvb_frontend *fe)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) struct cx24117_state *state = fe->demodulator_priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) const struct firmware *fw;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) dev_dbg(&state->priv->i2c->dev, "%s() demod%d skip_fw_load=%d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) __func__, state->demod, state->priv->skip_fw_load);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) if (state->priv->skip_fw_load)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) /* check if firmware is already running */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) if (cx24117_readreg(state, 0xeb) != 0xa) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) /* Load firmware */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) /* request the firmware, this will block until loaded */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) dev_dbg(&state->priv->i2c->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) "%s: Waiting for firmware upload (%s)...\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) __func__, CX24117_DEFAULT_FIRMWARE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) ret = request_firmware(&fw, CX24117_DEFAULT_FIRMWARE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) state->priv->i2c->dev.parent);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) dev_dbg(&state->priv->i2c->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) "%s: Waiting for firmware upload(2)...\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) dev_err(&state->priv->i2c->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) "%s: No firmware uploaded (timeout or file not found?)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) /* Make sure we don't recurse back through here
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) * during loading */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) state->priv->skip_fw_load = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) ret = cx24117_load_firmware(fe, fw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) dev_err(&state->priv->i2c->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) "%s: Writing firmware failed\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) release_firmware(fw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) dev_info(&state->priv->i2c->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) "%s: Firmware upload %s\n", __func__,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) ret == 0 ? "complete" : "failed");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) /* Ensure firmware is always loaded if required */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) state->priv->skip_fw_load = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) /* Take a basic firmware command structure, format it
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) * and forward it for processing
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) static int cx24117_cmd_execute_nolock(struct dvb_frontend *fe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) struct cx24117_cmd *cmd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) struct cx24117_state *state = fe->demodulator_priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) int i, ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) dev_dbg(&state->priv->i2c->dev, "%s() demod%d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) __func__, state->demod);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) /* Load the firmware if required */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) ret = cx24117_firmware_ondemand(fe);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) if (ret != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) /* Write the command */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) cx24117_writecmd(state, cmd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) /* Start execution and wait for cmd to terminate */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) cx24117_writereg(state, CX24117_REG_EXECUTE, 0x01);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) i = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) while (cx24117_readreg(state, CX24117_REG_EXECUTE)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) msleep(20);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) if (i++ > 40) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) /* Avoid looping forever if the firmware does
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) not respond */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) dev_warn(&state->priv->i2c->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) "%s() Firmware not responding\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) static int cx24117_cmd_execute(struct dvb_frontend *fe, struct cx24117_cmd *cmd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) struct cx24117_state *state = fe->demodulator_priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) mutex_lock(&state->priv->fe_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) ret = cx24117_cmd_execute_nolock(fe, cmd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) mutex_unlock(&state->priv->fe_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) static int cx24117_load_firmware(struct dvb_frontend *fe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) const struct firmware *fw)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) struct cx24117_state *state = fe->demodulator_priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) struct cx24117_cmd cmd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) int i, ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) unsigned char vers[4];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) struct i2c_msg msg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) u8 *buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) dev_dbg(&state->priv->i2c->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) "%s() demod%d FW is %zu bytes (%02x %02x .. %02x %02x)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) __func__, state->demod, fw->size, fw->data[0], fw->data[1],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) fw->data[fw->size - 2], fw->data[fw->size - 1]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) cx24117_writereg(state, 0xea, 0x00);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) cx24117_writereg(state, 0xea, 0x01);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) cx24117_writereg(state, 0xea, 0x00);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) cx24117_writereg(state, 0xce, 0x92);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) cx24117_writereg(state, 0xfb, 0x00);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) cx24117_writereg(state, 0xfc, 0x00);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) cx24117_writereg(state, 0xc3, 0x04);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) cx24117_writereg(state, 0xc4, 0x04);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) cx24117_writereg(state, 0xce, 0x00);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) cx24117_writereg(state, 0xcf, 0x00);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) cx24117_writereg(state, 0xea, 0x00);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) cx24117_writereg(state, 0xeb, 0x0c);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) cx24117_writereg(state, 0xec, 0x06);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) cx24117_writereg(state, 0xed, 0x05);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) cx24117_writereg(state, 0xee, 0x03);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) cx24117_writereg(state, 0xef, 0x05);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) cx24117_writereg(state, 0xf3, 0x03);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) cx24117_writereg(state, 0xf4, 0x44);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) cx24117_writereg(state, CX24117_REG_RATEDIV0, 0x04);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) cx24117_writereg(state, CX24117_REG_CLKDIV0, 0x02);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) cx24117_writereg(state, CX24117_REG_RATEDIV1, 0x04);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) cx24117_writereg(state, CX24117_REG_CLKDIV1, 0x02);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) cx24117_writereg(state, 0xf2, 0x04);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) cx24117_writereg(state, 0xe8, 0x02);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) cx24117_writereg(state, 0xea, 0x01);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) cx24117_writereg(state, 0xc8, 0x00);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) cx24117_writereg(state, 0xc9, 0x00);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) cx24117_writereg(state, 0xca, 0x00);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) cx24117_writereg(state, 0xcb, 0x00);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) cx24117_writereg(state, 0xcc, 0x00);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) cx24117_writereg(state, 0xcd, 0x00);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) cx24117_writereg(state, 0xe4, 0x03);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) cx24117_writereg(state, 0xeb, 0x0a);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) cx24117_writereg(state, 0xfb, 0x00);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) cx24117_writereg(state, 0xe0, 0x76);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) cx24117_writereg(state, 0xf7, 0x81);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) cx24117_writereg(state, 0xf8, 0x00);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) cx24117_writereg(state, 0xf9, 0x00);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) buf = kmalloc(fw->size + 1, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) if (buf == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) state->priv->skip_fw_load = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) /* fw upload reg */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) buf[0] = 0xfa;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) memcpy(&buf[1], fw->data, fw->size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) /* prepare i2c message to send */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) msg.addr = state->priv->demod_address;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) msg.flags = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) msg.len = fw->size + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) msg.buf = buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) /* send fw */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) ret = i2c_transfer(state->priv->i2c, &msg, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) kfree(buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) kfree(buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) cx24117_writereg(state, 0xf7, 0x0c);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) cx24117_writereg(state, 0xe0, 0x00);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) /* Init demodulator */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) cmd.args[0] = CMD_DEMODINIT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) cmd.args[1] = 0x00;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) cmd.args[2] = 0x01;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) cmd.args[3] = 0x00;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) cmd.len = 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) ret = cx24117_cmd_execute_nolock(fe, &cmd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) if (ret != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) /* Set VCO frequency */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) cmd.args[0] = CMD_SET_VCOFREQ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) cmd.args[1] = 0x06;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) cmd.args[2] = 0x2b;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) cmd.args[3] = 0xd8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) cmd.args[4] = 0xa5;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) cmd.args[5] = 0xee;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) cmd.args[6] = 0x03;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) cmd.args[7] = 0x9d;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) cmd.args[8] = 0xfc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) cmd.args[9] = 0x06;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) cmd.args[10] = 0x02;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) cmd.args[11] = 0x9d;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) cmd.args[12] = 0xfc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) cmd.len = 13;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) ret = cx24117_cmd_execute_nolock(fe, &cmd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) if (ret != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) /* Tuner init */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) cmd.args[0] = CMD_TUNERINIT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) cmd.args[1] = 0x00;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) cmd.args[2] = 0x01;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) cmd.args[3] = 0x00;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) cmd.args[4] = 0x00;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) cmd.args[5] = 0x01;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) cmd.args[6] = 0x01;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) cmd.args[7] = 0x01;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) cmd.args[8] = 0x00;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) cmd.args[9] = 0x05;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) cmd.args[10] = 0x02;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) cmd.args[11] = 0x02;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) cmd.args[12] = 0x00;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) cmd.len = 13;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) ret = cx24117_cmd_execute_nolock(fe, &cmd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) if (ret != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) /* Global MPEG config */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) cmd.args[0] = CMD_GLOBAL_MPEGCFG;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) cmd.args[1] = 0x00;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) cmd.args[2] = 0x00;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) cmd.args[3] = 0x00;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) cmd.args[4] = 0x01;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) cmd.args[5] = 0x00;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) cmd.len = 6;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) ret = cx24117_cmd_execute_nolock(fe, &cmd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) if (ret != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) /* MPEG config for each demod */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) for (i = 0; i < 2; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) cmd.args[0] = CMD_MPEGCFG;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) cmd.args[1] = (u8) i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) cmd.args[2] = 0x00;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) cmd.args[3] = 0x05;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) cmd.args[4] = 0x00;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) cmd.args[5] = 0x00;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) cmd.args[6] = 0x55;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) cmd.args[7] = 0x00;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) cmd.len = 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) ret = cx24117_cmd_execute_nolock(fe, &cmd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) if (ret != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) cx24117_writereg(state, 0xce, 0xc0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) cx24117_writereg(state, 0xcf, 0x00);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) cx24117_writereg(state, 0xe5, 0x04);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) /* Get firmware version */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) cmd.args[0] = CMD_FWVERSION;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714) cmd.len = 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) for (i = 0; i < 4; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) cmd.args[1] = i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) ret = cx24117_cmd_execute_nolock(fe, &cmd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) if (ret != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719) goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) vers[i] = cx24117_readreg(state, 0x33);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) dev_info(&state->priv->i2c->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723) "%s: FW version %i.%i.%i.%i\n", __func__,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) vers[0], vers[1], vers[2], vers[3]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726) error:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727) state->priv->skip_fw_load = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) dev_err(&state->priv->i2c->dev, "%s() Error running FW.\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732) static int cx24117_read_status(struct dvb_frontend *fe, enum fe_status *status)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) struct cx24117_state *state = fe->demodulator_priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735) int lock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) lock = cx24117_readreg(state,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738) (state->demod == 0) ? CX24117_REG_SSTATUS0 :
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739) CX24117_REG_SSTATUS1) &
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740) CX24117_STATUS_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742) dev_dbg(&state->priv->i2c->dev, "%s() demod%d status = 0x%02x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) __func__, state->demod, lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) *status = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747) if (lock & CX24117_HAS_SIGNAL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748) *status |= FE_HAS_SIGNAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) if (lock & CX24117_HAS_CARRIER)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) *status |= FE_HAS_CARRIER;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) if (lock & CX24117_HAS_VITERBI)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752) *status |= FE_HAS_VITERBI;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753) if (lock & CX24117_HAS_SYNCLOCK)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754) *status |= FE_HAS_SYNC | FE_HAS_LOCK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759) static int cx24117_read_ber(struct dvb_frontend *fe, u32 *ber)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761) struct cx24117_state *state = fe->demodulator_priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763) u8 buf[4];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764) u8 base_reg = (state->demod == 0) ?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765) CX24117_REG_BER4_0 :
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766) CX24117_REG_BER4_1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768) ret = cx24117_readregN(state, base_reg, buf, 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769) if (ret != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772) *ber = (buf[0] << 24) | (buf[1] << 16) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773) (buf[1] << 8) | buf[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775) dev_dbg(&state->priv->i2c->dev, "%s() demod%d ber=0x%04x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776) __func__, state->demod, *ber);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781) static int cx24117_read_signal_strength(struct dvb_frontend *fe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782) u16 *signal_strength)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784) struct cx24117_state *state = fe->demodulator_priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785) struct cx24117_cmd cmd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787) u16 sig_reading;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788) u8 buf[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789) u8 reg = (state->demod == 0) ?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790) CX24117_REG_SSTATUS0 : CX24117_REG_SSTATUS1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792) /* Read AGC accumulator register */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793) cmd.args[0] = CMD_GET_AGCACC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794) cmd.args[1] = (u8) state->demod;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795) cmd.len = 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796) ret = cx24117_cmd_execute(fe, &cmd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797) if (ret != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800) ret = cx24117_readregN(state, reg, buf, 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801) if (ret != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803) sig_reading = ((buf[0] & CX24117_SIGNAL_MASK) << 2) | buf[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805) *signal_strength = -100 * sig_reading + 94324;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807) dev_dbg(&state->priv->i2c->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808) "%s() demod%d raw / cooked = 0x%04x / 0x%04x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809) __func__, state->demod, sig_reading, *signal_strength);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814) static int cx24117_read_snr(struct dvb_frontend *fe, u16 *snr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816) struct cx24117_state *state = fe->demodulator_priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818) u8 buf[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819) u8 reg = (state->demod == 0) ?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820) CX24117_REG_QUALITY2_0 : CX24117_REG_QUALITY2_1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822) ret = cx24117_readregN(state, reg, buf, 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823) if (ret != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826) *snr = (buf[0] << 8) | buf[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828) dev_dbg(&state->priv->i2c->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829) "%s() demod%d snr = 0x%04x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830) __func__, state->demod, *snr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835) static int cx24117_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837) struct cx24117_state *state = fe->demodulator_priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838) enum fe_delivery_system delsys = fe->dtv_property_cache.delivery_system;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840) u8 buf[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841) u8 reg = (state->demod == 0) ?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842) CX24117_REG_DVBS_UCB2_0 :
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843) CX24117_REG_DVBS_UCB2_1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845) switch (delsys) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846) case SYS_DVBS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848) case SYS_DVBS2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849) reg += (CX24117_REG_DVBS2_UCB2_0 - CX24117_REG_DVBS_UCB2_0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 851) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 853) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 855) ret = cx24117_readregN(state, reg, buf, 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 856) if (ret != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 857) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 858) *ucblocks = (buf[0] << 8) | buf[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 859)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 860) dev_dbg(&state->priv->i2c->dev, "%s() demod%d ucb=0x%04x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 861) __func__, state->demod, *ucblocks);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 862)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 863) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 864) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 865)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 866) /* Overwrite the current tuning params, we are about to tune */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 867) static void cx24117_clone_params(struct dvb_frontend *fe)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 868) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 869) struct cx24117_state *state = fe->demodulator_priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 870) state->dcur = state->dnxt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 871) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 872)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 873) /* Wait for LNB */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 874) static int cx24117_wait_for_lnb(struct dvb_frontend *fe)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 875) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 876) struct cx24117_state *state = fe->demodulator_priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 877) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 878) u8 val, reg = (state->demod == 0) ? CX24117_REG_QSTATUS0 :
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 879) CX24117_REG_QSTATUS1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 880)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 881) dev_dbg(&state->priv->i2c->dev, "%s() demod%d qstatus = 0x%02x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 882) __func__, state->demod, cx24117_readreg(state, reg));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 883)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 884) /* Wait for up to 300 ms */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 885) for (i = 0; i < 10; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 886) val = cx24117_readreg(state, reg) & 0x01;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 887) if (val != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 888) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 889) msleep(30);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 890) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 891)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 892) dev_warn(&state->priv->i2c->dev, "%s: demod%d LNB not ready\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 893) KBUILD_MODNAME, state->demod);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 894)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 895) return -ETIMEDOUT; /* -EBUSY ? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 896) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 897)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 898) static int cx24117_set_voltage(struct dvb_frontend *fe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 899) enum fe_sec_voltage voltage)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 900) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 901) struct cx24117_state *state = fe->demodulator_priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 902) struct cx24117_cmd cmd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 903) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 904) u8 reg = (state->demod == 0) ? 0x10 : 0x20;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 905)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 906) dev_dbg(&state->priv->i2c->dev, "%s() demod%d %s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 907) __func__, state->demod,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 908) voltage == SEC_VOLTAGE_13 ? "SEC_VOLTAGE_13" :
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 909) voltage == SEC_VOLTAGE_18 ? "SEC_VOLTAGE_18" :
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 910) "SEC_VOLTAGE_OFF");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 911)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 912) /* Prepare a set GPIO logic level CMD */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 913) cmd.args[0] = CMD_SET_GPIOOUT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 914) cmd.args[2] = reg; /* mask */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 915) cmd.len = 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 916)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 917) if ((voltage == SEC_VOLTAGE_13) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 918) (voltage == SEC_VOLTAGE_18)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 919) /* power on LNB */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 920) cmd.args[1] = reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 921) ret = cx24117_cmd_execute(fe, &cmd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 922) if (ret != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 923) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 924)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 925) ret = cx24117_wait_for_lnb(fe);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 926) if (ret != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 927) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 928)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 929) /* Wait for voltage/min repeat delay */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 930) msleep(100);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 931)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 932) /* Set 13V/18V select pin */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 933) cmd.args[0] = CMD_LNBDCLEVEL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 934) cmd.args[1] = state->demod ? 0 : 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 935) cmd.args[2] = (voltage == SEC_VOLTAGE_18 ? 0x01 : 0x00);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 936) cmd.len = 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 937) ret = cx24117_cmd_execute(fe, &cmd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 938)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 939) /* Min delay time before DiSEqC send */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 940) msleep(20);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 941) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 942) /* power off LNB */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 943) cmd.args[1] = 0x00;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 944) ret = cx24117_cmd_execute(fe, &cmd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 945) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 946)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 947) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 948) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 949)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 950) static int cx24117_set_tone(struct dvb_frontend *fe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 951) enum fe_sec_tone_mode tone)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 952) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 953) struct cx24117_state *state = fe->demodulator_priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 954) struct cx24117_cmd cmd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 955) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 956)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 957) dev_dbg(&state->priv->i2c->dev, "%s(%d) demod%d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 958) __func__, state->demod, tone);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 959) if ((tone != SEC_TONE_ON) && (tone != SEC_TONE_OFF)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 960) dev_warn(&state->priv->i2c->dev, "%s: demod%d invalid tone=%d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 961) KBUILD_MODNAME, state->demod, tone);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 962) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 963) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 964)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 965) /* Wait for LNB ready */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 966) ret = cx24117_wait_for_lnb(fe);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 967) if (ret != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 968) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 969)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 970) /* Min delay time after DiSEqC send */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 971) msleep(20);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 972)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 973) /* Set the tone */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 974) cmd.args[0] = CMD_LNBPCBCONFIG;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 975) cmd.args[1] = (state->demod ? 0 : 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 976) cmd.args[2] = 0x00;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 977) cmd.args[3] = 0x00;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 978) cmd.len = 5;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 979) switch (tone) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 980) case SEC_TONE_ON:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 981) cmd.args[4] = 0x01;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 982) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 983) case SEC_TONE_OFF:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 984) cmd.args[4] = 0x00;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 985) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 986) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 987)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 988) msleep(20);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 989)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 990) return cx24117_cmd_execute(fe, &cmd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 991) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 992)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 993) /* Initialise DiSEqC */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 994) static int cx24117_diseqc_init(struct dvb_frontend *fe)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 995) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 996) struct cx24117_state *state = fe->demodulator_priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 997)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 998) /* Prepare a DiSEqC command */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 999) state->dsec_cmd.args[0] = CMD_LNBSEND;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1000)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1001) /* demod */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1002) state->dsec_cmd.args[CX24117_DISEQC_DEMOD] = state->demod ? 0 : 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1003)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1004) /* DiSEqC burst */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1005) state->dsec_cmd.args[CX24117_DISEQC_BURST] = CX24117_DISEQC_MINI_A;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1006)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1007) /* Unknown */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1008) state->dsec_cmd.args[CX24117_DISEQC_ARG3_2] = 0x02;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1009) state->dsec_cmd.args[CX24117_DISEQC_ARG4_0] = 0x00;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1010)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1011) /* Continuation flag? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1012) state->dsec_cmd.args[CX24117_DISEQC_ARG5_0] = 0x00;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1013)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1014) /* DiSEqC message length */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1015) state->dsec_cmd.args[CX24117_DISEQC_MSGLEN] = 0x00;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1016)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1017) /* Command length */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1018) state->dsec_cmd.len = 7;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1019)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1020) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1021) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1022)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1023) /* Send DiSEqC message */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1024) static int cx24117_send_diseqc_msg(struct dvb_frontend *fe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1025) struct dvb_diseqc_master_cmd *d)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1026) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1027) struct cx24117_state *state = fe->demodulator_priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1028) int i, ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1029)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1030) /* Dump DiSEqC message */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1031) dev_dbg(&state->priv->i2c->dev, "%s: demod %d (",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1032) __func__, state->demod);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1033) for (i = 0; i < d->msg_len; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1034) dev_dbg(&state->priv->i2c->dev, "0x%02x ", d->msg[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1035) dev_dbg(&state->priv->i2c->dev, ")\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1036)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1037) /* Validate length */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1038) if (d->msg_len > sizeof(d->msg))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1039) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1040)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1041) /* DiSEqC message */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1042) for (i = 0; i < d->msg_len; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1043) state->dsec_cmd.args[CX24117_DISEQC_MSGOFS + i] = d->msg[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1044)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1045) /* DiSEqC message length */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1046) state->dsec_cmd.args[CX24117_DISEQC_MSGLEN] = d->msg_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1047)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1048) /* Command length */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1049) state->dsec_cmd.len = CX24117_DISEQC_MSGOFS +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1050) state->dsec_cmd.args[CX24117_DISEQC_MSGLEN];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1051)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1052) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1053) * Message is sent with derived else cached burst
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1054) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1055) * WRITE PORT GROUP COMMAND 38
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1056) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1057) * 0/A/A: E0 10 38 F0..F3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1058) * 1/B/B: E0 10 38 F4..F7
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1059) * 2/C/A: E0 10 38 F8..FB
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1060) * 3/D/B: E0 10 38 FC..FF
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1061) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1062) * databyte[3]= 8421:8421
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1063) * ABCD:WXYZ
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1064) * CLR :SET
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1065) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1066) * WX= PORT SELECT 0..3 (X=TONEBURST)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1067) * Y = VOLTAGE (0=13V, 1=18V)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1068) * Z = BAND (0=LOW, 1=HIGH(22K))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1069) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1070) if (d->msg_len >= 4 && d->msg[2] == 0x38)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1071) state->dsec_cmd.args[CX24117_DISEQC_BURST] =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1072) ((d->msg[3] & 4) >> 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1073)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1074) dev_dbg(&state->priv->i2c->dev, "%s() demod%d burst=%d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1075) __func__, state->demod,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1076) state->dsec_cmd.args[CX24117_DISEQC_BURST]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1077)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1078) /* Wait for LNB ready */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1079) ret = cx24117_wait_for_lnb(fe);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1080) if (ret != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1081) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1082)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1083) /* Wait for voltage/min repeat delay */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1084) msleep(100);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1085)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1086) /* Command */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1087) ret = cx24117_cmd_execute(fe, &state->dsec_cmd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1088) if (ret != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1089) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1090) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1091) * Wait for send
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1092) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1093) * Eutelsat spec:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1094) * >15ms delay + (XXX determine if FW does this, see set_tone)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1095) * 13.5ms per byte +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1096) * >15ms delay +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1097) * 12.5ms burst +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1098) * >15ms delay (XXX determine if FW does this, see set_tone)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1099) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1100) msleep((state->dsec_cmd.args[CX24117_DISEQC_MSGLEN] << 4) + 60);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1101)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1102) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1103) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1104)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1105) /* Send DiSEqC burst */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1106) static int cx24117_diseqc_send_burst(struct dvb_frontend *fe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1107) enum fe_sec_mini_cmd burst)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1108) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1109) struct cx24117_state *state = fe->demodulator_priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1110)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1111) dev_dbg(&state->priv->i2c->dev, "%s(%d) demod=%d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1112) __func__, burst, state->demod);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1113)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1114) /* DiSEqC burst */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1115) if (burst == SEC_MINI_A)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1116) state->dsec_cmd.args[CX24117_DISEQC_BURST] =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1117) CX24117_DISEQC_MINI_A;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1118) else if (burst == SEC_MINI_B)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1119) state->dsec_cmd.args[CX24117_DISEQC_BURST] =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1120) CX24117_DISEQC_MINI_B;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1121) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1122) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1123)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1124) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1125) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1126)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1127) static int cx24117_get_priv(struct cx24117_priv **priv,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1128) struct i2c_adapter *i2c, u8 client_address)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1129) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1130) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1131)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1132) mutex_lock(&cx24117_list_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1133) ret = hybrid_tuner_request_state(struct cx24117_priv, (*priv),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1134) hybrid_tuner_instance_list, i2c, client_address, "cx24117");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1135) mutex_unlock(&cx24117_list_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1136)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1137) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1138) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1139)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1140) static void cx24117_release_priv(struct cx24117_priv *priv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1141) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1142) mutex_lock(&cx24117_list_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1143) if (priv != NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1144) hybrid_tuner_release_state(priv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1145) mutex_unlock(&cx24117_list_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1146) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1147)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1148) static void cx24117_release(struct dvb_frontend *fe)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1149) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1150) struct cx24117_state *state = fe->demodulator_priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1151) dev_dbg(&state->priv->i2c->dev, "%s demod%d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1152) __func__, state->demod);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1153) cx24117_release_priv(state->priv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1154) kfree(state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1155) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1156)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1157) static const struct dvb_frontend_ops cx24117_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1158)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1159) struct dvb_frontend *cx24117_attach(const struct cx24117_config *config,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1160) struct i2c_adapter *i2c)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1161) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1162) struct cx24117_state *state = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1163) struct cx24117_priv *priv = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1164) int demod = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1165)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1166) /* get the common data struct for both demods */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1167) demod = cx24117_get_priv(&priv, i2c, config->demod_address);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1168)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1169) switch (demod) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1170) case 0:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1171) dev_err(&i2c->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1172) "%s: Error attaching frontend %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1173) KBUILD_MODNAME, demod);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1174) goto error1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1175) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1176) case 1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1177) /* new priv instance */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1178) priv->i2c = i2c;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1179) priv->demod_address = config->demod_address;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1180) mutex_init(&priv->fe_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1181) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1182) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1183) /* existing priv instance */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1184) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1185) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1186)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1187) /* allocate memory for the internal state */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1188) state = kzalloc(sizeof(struct cx24117_state), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1189) if (state == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1190) goto error2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1191)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1192) state->demod = demod - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1193) state->priv = priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1194)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1195) dev_info(&state->priv->i2c->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1196) "%s: Attaching frontend %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1197) KBUILD_MODNAME, state->demod);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1198)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1199) /* create dvb_frontend */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1200) memcpy(&state->frontend.ops, &cx24117_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1201) sizeof(struct dvb_frontend_ops));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1202) state->frontend.demodulator_priv = state;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1203) return &state->frontend;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1204)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1205) error2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1206) cx24117_release_priv(priv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1207) error1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1208) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1209) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1210) EXPORT_SYMBOL_GPL(cx24117_attach);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1211)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1212) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1213) * Initialise or wake up device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1214) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1215) * Power config will reset and load initial firmware if required
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1216) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1217) static int cx24117_initfe(struct dvb_frontend *fe)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1218) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1219) struct cx24117_state *state = fe->demodulator_priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1220) struct cx24117_cmd cmd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1221) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1222)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1223) dev_dbg(&state->priv->i2c->dev, "%s() demod%d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1224) __func__, state->demod);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1225)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1226) mutex_lock(&state->priv->fe_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1227)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1228) /* Set sleep mode off */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1229) cmd.args[0] = CMD_SET_SLEEPMODE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1230) cmd.args[1] = (state->demod ? 1 : 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1231) cmd.args[2] = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1232) cmd.len = 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1233) ret = cx24117_cmd_execute_nolock(fe, &cmd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1234) if (ret != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1235) goto exit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1236)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1237) ret = cx24117_diseqc_init(fe);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1238) if (ret != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1239) goto exit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1240)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1241) /* Set BER control */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1242) cmd.args[0] = CMD_BERCTRL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1243) cmd.args[1] = (state->demod ? 1 : 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1244) cmd.args[2] = 0x10;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1245) cmd.args[3] = 0x10;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1246) cmd.len = 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1247) ret = cx24117_cmd_execute_nolock(fe, &cmd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1248) if (ret != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1249) goto exit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1250)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1251) /* Set RS correction (enable/disable) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1252) cmd.args[0] = CMD_ENABLERSCORR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1253) cmd.args[1] = (state->demod ? 1 : 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1254) cmd.args[2] = CX24117_OCC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1255) cmd.len = 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1256) ret = cx24117_cmd_execute_nolock(fe, &cmd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1257) if (ret != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1258) goto exit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1259)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1260) /* Set GPIO direction */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1261) /* Set as output - controls LNB power on/off */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1262) cmd.args[0] = CMD_SET_GPIODIR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1263) cmd.args[1] = 0x30;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1264) cmd.args[2] = 0x30;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1265) cmd.len = 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1266) ret = cx24117_cmd_execute_nolock(fe, &cmd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1267)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1268) exit:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1269) mutex_unlock(&state->priv->fe_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1270)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1271) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1272) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1273)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1274) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1275) * Put device to sleep
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1276) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1277) static int cx24117_sleep(struct dvb_frontend *fe)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1278) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1279) struct cx24117_state *state = fe->demodulator_priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1280) struct cx24117_cmd cmd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1281)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1282) dev_dbg(&state->priv->i2c->dev, "%s() demod%d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1283) __func__, state->demod);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1284)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1285) /* Set sleep mode on */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1286) cmd.args[0] = CMD_SET_SLEEPMODE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1287) cmd.args[1] = (state->demod ? 1 : 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1288) cmd.args[2] = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1289) cmd.len = 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1290) return cx24117_cmd_execute(fe, &cmd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1291) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1292)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1293) /* dvb-core told us to tune, the tv property cache will be complete,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1294) * it's safe for is to pull values and use them for tuning purposes.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1295) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1296) static int cx24117_set_frontend(struct dvb_frontend *fe)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1297) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1298) struct cx24117_state *state = fe->demodulator_priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1299) struct dtv_frontend_properties *c = &fe->dtv_property_cache;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1300) struct cx24117_cmd cmd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1301) enum fe_status tunerstat;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1302) int i, status, ret, retune = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1303) u8 reg_clkdiv, reg_ratediv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1304)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1305) dev_dbg(&state->priv->i2c->dev, "%s() demod%d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1306) __func__, state->demod);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1307)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1308) switch (c->delivery_system) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1309) case SYS_DVBS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1310) dev_dbg(&state->priv->i2c->dev, "%s() demod%d DVB-S\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1311) __func__, state->demod);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1312)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1313) /* Only QPSK is supported for DVB-S */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1314) if (c->modulation != QPSK) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1315) dev_dbg(&state->priv->i2c->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1316) "%s() demod%d unsupported modulation (%d)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1317) __func__, state->demod, c->modulation);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1318) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1319) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1320)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1321) /* Pilot doesn't exist in DVB-S, turn bit off */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1322) state->dnxt.pilot_val = CX24117_PILOT_OFF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1323)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1324) /* DVB-S only supports 0.35 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1325) state->dnxt.rolloff_val = CX24117_ROLLOFF_035;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1326) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1327)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1328) case SYS_DVBS2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1329) dev_dbg(&state->priv->i2c->dev, "%s() demod%d DVB-S2\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1330) __func__, state->demod);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1331)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1332) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1333) * NBC 8PSK/QPSK with DVB-S is supported for DVB-S2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1334) * but not hardware auto detection
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1335) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1336) if (c->modulation != PSK_8 && c->modulation != QPSK) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1337) dev_dbg(&state->priv->i2c->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1338) "%s() demod%d unsupported modulation (%d)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1339) __func__, state->demod, c->modulation);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1340) return -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1341) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1342)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1343) switch (c->pilot) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1344) case PILOT_AUTO:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1345) state->dnxt.pilot_val = CX24117_PILOT_AUTO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1346) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1347) case PILOT_OFF:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1348) state->dnxt.pilot_val = CX24117_PILOT_OFF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1349) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1350) case PILOT_ON:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1351) state->dnxt.pilot_val = CX24117_PILOT_ON;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1352) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1353) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1354) dev_dbg(&state->priv->i2c->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1355) "%s() demod%d unsupported pilot mode (%d)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1356) __func__, state->demod, c->pilot);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1357) return -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1358) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1359)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1360) switch (c->rolloff) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1361) case ROLLOFF_20:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1362) state->dnxt.rolloff_val = CX24117_ROLLOFF_020;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1363) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1364) case ROLLOFF_25:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1365) state->dnxt.rolloff_val = CX24117_ROLLOFF_025;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1366) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1367) case ROLLOFF_35:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1368) state->dnxt.rolloff_val = CX24117_ROLLOFF_035;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1369) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1370) case ROLLOFF_AUTO:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1371) state->dnxt.rolloff_val = CX24117_ROLLOFF_035;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1372) /* soft-auto rolloff */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1373) retune = 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1374) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1375) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1376) dev_warn(&state->priv->i2c->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1377) "%s: demod%d unsupported rolloff (%d)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1378) KBUILD_MODNAME, state->demod, c->rolloff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1379) return -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1380) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1381) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1382)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1383) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1384) dev_warn(&state->priv->i2c->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1385) "%s: demod %d unsupported delivery system (%d)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1386) KBUILD_MODNAME, state->demod, c->delivery_system);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1387) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1388) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1389)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1390) state->dnxt.delsys = c->delivery_system;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1391) state->dnxt.modulation = c->modulation;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1392) state->dnxt.frequency = c->frequency;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1393) state->dnxt.pilot = c->pilot;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1394) state->dnxt.rolloff = c->rolloff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1395)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1396) ret = cx24117_set_inversion(state, c->inversion);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1397) if (ret != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1398) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1399)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1400) ret = cx24117_set_fec(state,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1401) c->delivery_system, c->modulation, c->fec_inner);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1402) if (ret != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1403) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1404)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1405) ret = cx24117_set_symbolrate(state, c->symbol_rate);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1406) if (ret != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1407) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1408)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1409) /* discard the 'current' tuning parameters and prepare to tune */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1410) cx24117_clone_params(fe);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1411)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1412) dev_dbg(&state->priv->i2c->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1413) "%s: delsys = %d\n", __func__, state->dcur.delsys);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1414) dev_dbg(&state->priv->i2c->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1415) "%s: modulation = %d\n", __func__, state->dcur.modulation);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1416) dev_dbg(&state->priv->i2c->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1417) "%s: frequency = %d\n", __func__, state->dcur.frequency);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1418) dev_dbg(&state->priv->i2c->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1419) "%s: pilot = %d (val = 0x%02x)\n", __func__,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1420) state->dcur.pilot, state->dcur.pilot_val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1421) dev_dbg(&state->priv->i2c->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1422) "%s: retune = %d\n", __func__, retune);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1423) dev_dbg(&state->priv->i2c->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1424) "%s: rolloff = %d (val = 0x%02x)\n", __func__,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1425) state->dcur.rolloff, state->dcur.rolloff_val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1426) dev_dbg(&state->priv->i2c->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1427) "%s: symbol_rate = %d\n", __func__, state->dcur.symbol_rate);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1428) dev_dbg(&state->priv->i2c->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1429) "%s: FEC = %d (mask/val = 0x%02x/0x%02x)\n", __func__,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1430) state->dcur.fec, state->dcur.fec_mask, state->dcur.fec_val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1431) dev_dbg(&state->priv->i2c->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1432) "%s: Inversion = %d (val = 0x%02x)\n", __func__,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1433) state->dcur.inversion, state->dcur.inversion_val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1434)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1435) /* Prepare a tune request */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1436) cmd.args[0] = CMD_TUNEREQUEST;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1437)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1438) /* demod */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1439) cmd.args[1] = state->demod;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1440)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1441) /* Frequency */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1442) cmd.args[2] = (state->dcur.frequency & 0xff0000) >> 16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1443) cmd.args[3] = (state->dcur.frequency & 0x00ff00) >> 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1444) cmd.args[4] = (state->dcur.frequency & 0x0000ff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1445)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1446) /* Symbol Rate */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1447) cmd.args[5] = ((state->dcur.symbol_rate / 1000) & 0xff00) >> 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1448) cmd.args[6] = ((state->dcur.symbol_rate / 1000) & 0x00ff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1449)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1450) /* Automatic Inversion */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1451) cmd.args[7] = state->dcur.inversion_val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1452)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1453) /* Modulation / FEC / Pilot */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1454) cmd.args[8] = state->dcur.fec_val | state->dcur.pilot_val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1455)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1456) cmd.args[9] = CX24117_SEARCH_RANGE_KHZ >> 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1457) cmd.args[10] = CX24117_SEARCH_RANGE_KHZ & 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1458)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1459) cmd.args[11] = state->dcur.rolloff_val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1460) cmd.args[12] = state->dcur.fec_mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1461)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1462) if (state->dcur.symbol_rate > 30000000) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1463) reg_ratediv = 0x04;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1464) reg_clkdiv = 0x02;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1465) } else if (state->dcur.symbol_rate > 10000000) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1466) reg_ratediv = 0x06;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1467) reg_clkdiv = 0x03;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1468) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1469) reg_ratediv = 0x0a;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1470) reg_clkdiv = 0x05;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1471) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1472)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1473) cmd.args[13] = reg_ratediv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1474) cmd.args[14] = reg_clkdiv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1475)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1476) cx24117_writereg(state, (state->demod == 0) ?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1477) CX24117_REG_CLKDIV0 : CX24117_REG_CLKDIV1, reg_clkdiv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1478) cx24117_writereg(state, (state->demod == 0) ?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1479) CX24117_REG_RATEDIV0 : CX24117_REG_RATEDIV1, reg_ratediv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1480)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1481) cmd.args[15] = CX24117_PNE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1482) cmd.len = 16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1483)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1484) do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1485) /* Reset status register */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1486) status = cx24117_readreg(state, (state->demod == 0) ?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1487) CX24117_REG_SSTATUS0 : CX24117_REG_SSTATUS1) &
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1488) CX24117_SIGNAL_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1489)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1490) dev_dbg(&state->priv->i2c->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1491) "%s() demod%d status_setfe = %02x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1492) __func__, state->demod, status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1493)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1494) cx24117_writereg(state, (state->demod == 0) ?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1495) CX24117_REG_SSTATUS0 : CX24117_REG_SSTATUS1, status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1496)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1497) /* Tune */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1498) ret = cx24117_cmd_execute(fe, &cmd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1499) if (ret != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1500) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1501)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1502) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1503) * Wait for up to 500 ms before retrying
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1504) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1505) * If we are able to tune then generally it occurs within 100ms.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1506) * If it takes longer, try a different rolloff setting.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1507) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1508) for (i = 0; i < 50; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1509) cx24117_read_status(fe, &tunerstat);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1510) status = tunerstat & (FE_HAS_SIGNAL | FE_HAS_SYNC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1511) if (status == (FE_HAS_SIGNAL | FE_HAS_SYNC)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1512) dev_dbg(&state->priv->i2c->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1513) "%s() demod%d tuned\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1514) __func__, state->demod);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1515) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1516) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1517) msleep(20);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1518) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1519)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1520) dev_dbg(&state->priv->i2c->dev, "%s() demod%d not tuned\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1521) __func__, state->demod);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1522)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1523) /* try next rolloff value */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1524) if (state->dcur.rolloff == 3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1525) cmd.args[11]--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1526)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1527) } while (--retune);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1528) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1529) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1530)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1531) static int cx24117_tune(struct dvb_frontend *fe, bool re_tune,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1532) unsigned int mode_flags, unsigned int *delay, enum fe_status *status)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1533) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1534) struct cx24117_state *state = fe->demodulator_priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1535)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1536) dev_dbg(&state->priv->i2c->dev, "%s() demod%d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1537) __func__, state->demod);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1538)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1539) *delay = HZ / 5;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1540) if (re_tune) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1541) int ret = cx24117_set_frontend(fe);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1542) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1543) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1544) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1545) return cx24117_read_status(fe, status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1546) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1547)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1548) static enum dvbfe_algo cx24117_get_algo(struct dvb_frontend *fe)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1549) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1550) return DVBFE_ALGO_HW;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1551) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1552)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1553) static int cx24117_get_frontend(struct dvb_frontend *fe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1554) struct dtv_frontend_properties *c)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1555) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1556) struct cx24117_state *state = fe->demodulator_priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1557) struct cx24117_cmd cmd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1558) u8 reg, st, inv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1559) int ret, idx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1560) unsigned int freq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1561) short srate_os, freq_os;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1562)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1563) u8 buf[0x1f-4];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1564)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1565) /* Read current tune parameters */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1566) cmd.args[0] = CMD_GETCTLACC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1567) cmd.args[1] = (u8) state->demod;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1568) cmd.len = 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1569) ret = cx24117_cmd_execute(fe, &cmd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1570) if (ret != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1571) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1572)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1573) /* read all required regs at once */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1574) reg = (state->demod == 0) ? CX24117_REG_FREQ3_0 : CX24117_REG_FREQ3_1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1575) ret = cx24117_readregN(state, reg, buf, 0x1f-4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1576) if (ret != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1577) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1578)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1579) st = buf[5];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1580)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1581) /* get spectral inversion */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1582) inv = (((state->demod == 0) ? ~st : st) >> 6) & 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1583) if (inv == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1584) c->inversion = INVERSION_OFF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1585) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1586) c->inversion = INVERSION_ON;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1587)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1588) /* modulation and fec */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1589) idx = st & 0x3f;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1590) if (c->delivery_system == SYS_DVBS2) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1591) if (idx > 11)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1592) idx += 9;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1593) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1594) idx += 7;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1595) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1596)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1597) c->modulation = cx24117_modfec_modes[idx].modulation;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1598) c->fec_inner = cx24117_modfec_modes[idx].fec;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1599)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1600) /* frequency */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1601) freq = (buf[0] << 16) | (buf[1] << 8) | buf[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1602) freq_os = (buf[8] << 8) | buf[9];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1603) c->frequency = freq + freq_os;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1604)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1605) /* symbol rate */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1606) srate_os = (buf[10] << 8) | buf[11];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1607) c->symbol_rate = -1000 * srate_os + state->dcur.symbol_rate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1608) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1609) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1610)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1611) static const struct dvb_frontend_ops cx24117_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1612) .delsys = { SYS_DVBS, SYS_DVBS2 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1613) .info = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1614) .name = "Conexant CX24117/CX24132",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1615) .frequency_min_hz = 950 * MHz,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1616) .frequency_max_hz = 2150 * MHz,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1617) .frequency_stepsize_hz = 1011 * kHz,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1618) .frequency_tolerance_hz = 5 * MHz,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1619) .symbol_rate_min = 1000000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1620) .symbol_rate_max = 45000000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1621) .caps = FE_CAN_INVERSION_AUTO |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1622) FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1623) FE_CAN_FEC_4_5 | FE_CAN_FEC_5_6 | FE_CAN_FEC_6_7 |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1624) FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1625) FE_CAN_2G_MODULATION |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1626) FE_CAN_QPSK | FE_CAN_RECOVER
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1627) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1628)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1629) .release = cx24117_release,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1630)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1631) .init = cx24117_initfe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1632) .sleep = cx24117_sleep,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1633) .read_status = cx24117_read_status,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1634) .read_ber = cx24117_read_ber,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1635) .read_signal_strength = cx24117_read_signal_strength,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1636) .read_snr = cx24117_read_snr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1637) .read_ucblocks = cx24117_read_ucblocks,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1638) .set_tone = cx24117_set_tone,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1639) .set_voltage = cx24117_set_voltage,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1640) .diseqc_send_master_cmd = cx24117_send_diseqc_msg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1641) .diseqc_send_burst = cx24117_diseqc_send_burst,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1642) .get_frontend_algo = cx24117_get_algo,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1643) .tune = cx24117_tune,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1644)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1645) .set_frontend = cx24117_set_frontend,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1646) .get_frontend = cx24117_get_frontend,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1647) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1648)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1649)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1650) MODULE_DESCRIPTION("DVB Frontend module for Conexant cx24117/cx24132 hardware");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1651) MODULE_AUTHOR("Luis Alves (ljalvs@gmail.com)");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1652) MODULE_LICENSE("GPL");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1653) MODULE_VERSION("1.1");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1654) MODULE_FIRMWARE(CX24117_DEFAULT_FIRMWARE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1655)