^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * Driver for the ST STV6111 tuner
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Copyright (C) 2014 Digital Devices GmbH
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * This program is free software; you can redistribute it and/or
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * modify it under the terms of the GNU General Public License
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) * version 2 only, as published by the Free Software Foundation.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) * This program is distributed in the hope that it will be useful,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) * but WITHOUT ANY WARRANTY; without even the implied warranty of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) * GNU General Public License for more details.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include <linux/moduleparam.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include <linux/init.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #include <linux/delay.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #include <linux/firmware.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #include <linux/i2c.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #include <asm/div64.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) #include "stv6111.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) #include <media/dvb_frontend.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) struct stv {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) struct i2c_adapter *i2c;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) u8 adr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) u8 reg[11];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) u32 ref_freq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) u32 frequency;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) struct slookup {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) s16 value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) u16 reg_value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) static const struct slookup lnagain_nf_lookup[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) /* Gain *100dB // Reg */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) { 2572, 0 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) { 2575, 1 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) { 2580, 2 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) { 2588, 3 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) { 2596, 4 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) { 2611, 5 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) { 2633, 6 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) { 2664, 7 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) { 2701, 8 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) { 2753, 9 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) { 2816, 10 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) { 2902, 11 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) { 2995, 12 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) { 3104, 13 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) { 3215, 14 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) { 3337, 15 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) { 3492, 16 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) { 3614, 17 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) { 3731, 18 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) { 3861, 19 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) { 3988, 20 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) { 4124, 21 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) { 4253, 22 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) { 4386, 23 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) { 4505, 24 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) { 4623, 25 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) { 4726, 26 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) { 4821, 27 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) { 4903, 28 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) { 4979, 29 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) { 5045, 30 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) { 5102, 31 }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) static const struct slookup lnagain_iip3_lookup[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) /* Gain *100dB // reg */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) { 1548, 0 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) { 1552, 1 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) { 1569, 2 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) { 1565, 3 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) { 1577, 4 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) { 1594, 5 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) { 1627, 6 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) { 1656, 7 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) { 1700, 8 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) { 1748, 9 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) { 1805, 10 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) { 1896, 11 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) { 1995, 12 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) { 2113, 13 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) { 2233, 14 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) { 2366, 15 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) { 2543, 16 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) { 2687, 17 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) { 2842, 18 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) { 2999, 19 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) { 3167, 20 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) { 3342, 21 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) { 3507, 22 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) { 3679, 23 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) { 3827, 24 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) { 3970, 25 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) { 4094, 26 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) { 4210, 27 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) { 4308, 28 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) { 4396, 29 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) { 4468, 30 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) { 4535, 31 }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) static const struct slookup gain_rfagc_lookup[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) /* Gain *100dB // reg */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) { 4870, 0x3000 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) { 4850, 0x3C00 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) { 4800, 0x4500 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) { 4750, 0x4800 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) { 4700, 0x4B00 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) { 4650, 0x4D00 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) { 4600, 0x4F00 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) { 4550, 0x5100 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) { 4500, 0x5200 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) { 4420, 0x5500 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) { 4316, 0x5800 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) { 4200, 0x5B00 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) { 4119, 0x5D00 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) { 3999, 0x6000 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) { 3950, 0x6100 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) { 3876, 0x6300 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) { 3755, 0x6600 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) { 3641, 0x6900 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) { 3567, 0x6B00 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) { 3425, 0x6F00 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) { 3350, 0x7100 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) { 3236, 0x7400 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) { 3118, 0x7700 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) { 3004, 0x7A00 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) { 2917, 0x7C00 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) { 2776, 0x7F00 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) { 2635, 0x8200 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) { 2516, 0x8500 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) { 2406, 0x8800 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) { 2290, 0x8B00 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) { 2170, 0x8E00 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) { 2073, 0x9100 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) { 1949, 0x9400 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) { 1836, 0x9700 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) { 1712, 0x9A00 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) { 1631, 0x9C00 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) { 1515, 0x9F00 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) { 1400, 0xA200 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) { 1323, 0xA400 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) { 1203, 0xA700 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) { 1091, 0xAA00 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) { 1011, 0xAC00 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) { 904, 0xAF00 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) { 787, 0xB200 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) { 685, 0xB500 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) { 571, 0xB800 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) { 464, 0xBB00 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) { 374, 0xBE00 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) { 275, 0xC200 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) { 181, 0xC600 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) { 102, 0xCC00 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) { 49, 0xD900 }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) * This table is 6 dB too low comapred to the others (probably created with
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) * a different BB_MAG setting)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) static const struct slookup gain_channel_agc_nf_lookup[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) /* Gain *100dB // reg */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) { 7082, 0x3000 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) { 7052, 0x4000 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) { 7007, 0x4600 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) { 6954, 0x4A00 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) { 6909, 0x4D00 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) { 6833, 0x5100 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) { 6753, 0x5400 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) { 6659, 0x5700 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) { 6561, 0x5A00 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) { 6472, 0x5C00 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) { 6366, 0x5F00 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) { 6259, 0x6100 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) { 6151, 0x6400 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) { 6026, 0x6700 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) { 5920, 0x6900 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) { 5835, 0x6B00 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) { 5770, 0x6C00 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) { 5681, 0x6E00 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) { 5596, 0x7000 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) { 5503, 0x7200 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) { 5429, 0x7300 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) { 5319, 0x7500 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) { 5220, 0x7700 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) { 5111, 0x7900 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) { 4983, 0x7B00 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) { 4876, 0x7D00 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) { 4755, 0x7F00 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) { 4635, 0x8100 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) { 4499, 0x8300 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) { 4405, 0x8500 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) { 4323, 0x8600 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) { 4233, 0x8800 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) { 4156, 0x8A00 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) { 4038, 0x8C00 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) { 3935, 0x8E00 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) { 3823, 0x9000 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) { 3712, 0x9200 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) { 3601, 0x9500 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) { 3511, 0x9700 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) { 3413, 0x9900 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) { 3309, 0x9B00 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) { 3213, 0x9D00 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) { 3088, 0x9F00 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) { 2992, 0xA100 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) { 2878, 0xA400 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) { 2769, 0xA700 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) { 2645, 0xAA00 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) { 2538, 0xAD00 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) { 2441, 0xB000 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) { 2350, 0xB600 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) { 2237, 0xBA00 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) { 2137, 0xBF00 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) { 2039, 0xC500 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) { 1938, 0xDF00 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) { 1927, 0xFF00 }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) static const struct slookup gain_channel_agc_iip3_lookup[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) /* Gain *100dB // reg */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) { 7070, 0x3000 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) { 7028, 0x4000 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) { 7019, 0x4600 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) { 6900, 0x4A00 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) { 6811, 0x4D00 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) { 6763, 0x5100 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) { 6690, 0x5400 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) { 6644, 0x5700 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) { 6617, 0x5A00 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) { 6598, 0x5C00 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) { 6462, 0x5F00 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) { 6348, 0x6100 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) { 6197, 0x6400 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) { 6154, 0x6700 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) { 6098, 0x6900 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) { 5893, 0x6B00 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) { 5812, 0x6C00 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) { 5773, 0x6E00 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) { 5723, 0x7000 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) { 5661, 0x7200 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) { 5579, 0x7300 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) { 5460, 0x7500 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) { 5308, 0x7700 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) { 5099, 0x7900 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) { 4910, 0x7B00 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) { 4800, 0x7D00 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) { 4785, 0x7F00 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) { 4635, 0x8100 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) { 4466, 0x8300 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) { 4314, 0x8500 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) { 4295, 0x8600 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) { 4144, 0x8800 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) { 3920, 0x8A00 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) { 3889, 0x8C00 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) { 3771, 0x8E00 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) { 3655, 0x9000 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) { 3446, 0x9200 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) { 3298, 0x9500 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) { 3083, 0x9700 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) { 3015, 0x9900 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) { 2833, 0x9B00 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) { 2746, 0x9D00 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) { 2632, 0x9F00 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) { 2598, 0xA100 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) { 2480, 0xA400 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) { 2236, 0xA700 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) { 2171, 0xAA00 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) { 2060, 0xAD00 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) { 1999, 0xB000 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) { 1974, 0xB600 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) { 1820, 0xBA00 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) { 1741, 0xBF00 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) { 1655, 0xC500 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) { 1444, 0xDF00 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) { 1325, 0xFF00 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) static inline u32 muldiv32(u32 a, u32 b, u32 c)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) u64 tmp64;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) tmp64 = (u64)a * (u64)b;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) do_div(tmp64, c);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) return (u32)tmp64;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) static int i2c_read(struct i2c_adapter *adap,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) u8 adr, u8 *msg, int len, u8 *answ, int alen)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) struct i2c_msg msgs[2] = { { .addr = adr, .flags = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) .buf = msg, .len = len},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) { .addr = adr, .flags = I2C_M_RD,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) .buf = answ, .len = alen } };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) if (i2c_transfer(adap, msgs, 2) != 2) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) dev_err(&adap->dev, "i2c read error\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) static int i2c_write(struct i2c_adapter *adap, u8 adr, u8 *data, int len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) struct i2c_msg msg = {.addr = adr, .flags = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) .buf = data, .len = len};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) if (i2c_transfer(adap, &msg, 1) != 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) dev_err(&adap->dev, "i2c write error\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) static int write_regs(struct stv *state, int reg, int len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) u8 d[12];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) memcpy(&d[1], &state->reg[reg], len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) d[0] = reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) return i2c_write(state->i2c, state->adr, d, len + 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) static int write_reg(struct stv *state, u8 reg, u8 val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) u8 d[2] = {reg, val};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) return i2c_write(state->i2c, state->adr, d, 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) static int read_reg(struct stv *state, u8 reg, u8 *val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) return i2c_read(state->i2c, state->adr, ®, 1, val, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) static int wait_for_call_done(struct stv *state, u8 mask)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) int status = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) u32 lock_retry_count = 10;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) while (lock_retry_count > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) u8 regval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) status = read_reg(state, 9, ®val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) if (status < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) return status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) if ((regval & mask) == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) usleep_range(4000, 6000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) lock_retry_count -= 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) status = -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) return status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) static void init_state(struct stv *state)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) u32 clkdiv = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) u32 agcmode = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) u32 agcref = 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) u32 agcset = 0xffffffff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) u32 bbmode = 0xffffffff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) state->reg[0] = 0x08;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) state->reg[1] = 0x41;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) state->reg[2] = 0x8f;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) state->reg[3] = 0x00;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) state->reg[4] = 0xce;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) state->reg[5] = 0x54;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) state->reg[6] = 0x55;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) state->reg[7] = 0x45;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) state->reg[8] = 0x46;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) state->reg[9] = 0xbd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) state->reg[10] = 0x11;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) state->ref_freq = 16000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) if (clkdiv <= 3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) state->reg[0x00] |= (clkdiv & 0x03);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) if (agcmode <= 3) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) state->reg[0x03] |= (agcmode << 5);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) if (agcmode == 0x01)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) state->reg[0x01] |= 0x30;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) if (bbmode <= 3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) state->reg[0x01] = (state->reg[0x01] & ~0x30) | (bbmode << 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) if (agcref <= 7)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) state->reg[0x03] |= agcref;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) if (agcset <= 31)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) state->reg[0x02] = (state->reg[0x02] & ~0x1F) | agcset | 0x40;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) static int attach_init(struct stv *state)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) if (write_regs(state, 0, 11))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) static void release(struct dvb_frontend *fe)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) kfree(fe->tuner_priv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) fe->tuner_priv = NULL;
^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 set_bandwidth(struct dvb_frontend *fe, u32 cutoff_frequency)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) struct stv *state = fe->tuner_priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) u32 index = (cutoff_frequency + 999999) / 1000000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) int stat = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) if (index < 6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) index = 6;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) if (index > 50)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) index = 50;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) if ((state->reg[0x08] & ~0xFC) == ((index - 6) << 2))
^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) state->reg[0x08] = (state->reg[0x08] & ~0xFC) | ((index - 6) << 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) state->reg[0x09] = (state->reg[0x09] & ~0x0C) | 0x08;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) if (fe->ops.i2c_gate_ctrl)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) stat = fe->ops.i2c_gate_ctrl(fe, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) if (!stat) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) write_regs(state, 0x08, 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) wait_for_call_done(state, 0x08);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) if (fe->ops.i2c_gate_ctrl && !stat)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) fe->ops.i2c_gate_ctrl(fe, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) return stat;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) static int set_lof(struct stv *state, u32 local_frequency, u32 cutoff_frequency)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) u32 index = (cutoff_frequency + 999999) / 1000000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) u32 frequency = (local_frequency + 500) / 1000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) u32 p = 1, psel = 0, fvco, div, frac;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) u8 icp, tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) if (index < 6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) index = 6;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) if (index > 50)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) index = 50;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) if (frequency <= 1300000) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) p = 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) psel = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) p = 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) psel = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) fvco = frequency * p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) div = fvco / state->ref_freq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) frac = fvco % state->ref_freq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) frac = muldiv32(frac, 0x40000, state->ref_freq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) icp = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) if (fvco < 2700000)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) icp = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) else if (fvco < 2950000)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) icp = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) else if (fvco < 3300000)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) icp = 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) else if (fvco < 3700000)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) icp = 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) else if (fvco < 4200000)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) icp = 5;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) else if (fvco < 4800000)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) icp = 6;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) icp = 7;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) state->reg[0x02] |= 0x80; /* LNA IIP3 Mode */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) state->reg[0x03] = (state->reg[0x03] & ~0x80) | (psel << 7);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) state->reg[0x04] = (div & 0xFF);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) state->reg[0x05] = (((div >> 8) & 0x01) | ((frac & 0x7F) << 1)) & 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) state->reg[0x06] = ((frac >> 7) & 0xFF);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) state->reg[0x07] = (state->reg[0x07] & ~0x07) | ((frac >> 15) & 0x07);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) state->reg[0x07] = (state->reg[0x07] & ~0xE0) | (icp << 5);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) state->reg[0x08] = (state->reg[0x08] & ~0xFC) | ((index - 6) << 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) /* Start cal vco,CF */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) state->reg[0x09] = (state->reg[0x09] & ~0x0C) | 0x0C;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) write_regs(state, 2, 8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) wait_for_call_done(state, 0x0C);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) usleep_range(10000, 12000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) read_reg(state, 0x03, &tmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) if (tmp & 0x10) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) state->reg[0x02] &= ~0x80; /* LNA NF Mode */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) write_regs(state, 2, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) read_reg(state, 0x08, &tmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) state->frequency = frequency;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) static int set_params(struct dvb_frontend *fe)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) struct stv *state = fe->tuner_priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) struct dtv_frontend_properties *p = &fe->dtv_property_cache;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) u32 freq, cutoff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) int stat = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) if (p->delivery_system != SYS_DVBS && p->delivery_system != SYS_DVBS2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) freq = p->frequency * 1000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) cutoff = 5000000 + muldiv32(p->symbol_rate, 135, 200);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) if (fe->ops.i2c_gate_ctrl)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) stat = fe->ops.i2c_gate_ctrl(fe, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) if (!stat)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) set_lof(state, freq, cutoff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) if (fe->ops.i2c_gate_ctrl && !stat)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) fe->ops.i2c_gate_ctrl(fe, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) static s32 table_lookup(const struct slookup *table,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) int table_size, u16 reg_value)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) s32 gain;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) s32 reg_diff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) int imin = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) int imax = table_size - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) /* Assumes Table[0].RegValue < Table[imax].RegValue */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) if (reg_value <= table[0].reg_value) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) gain = table[0].value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) } else if (reg_value >= table[imax].reg_value) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) gain = table[imax].value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) while ((imax - imin) > 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) i = (imax + imin) / 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) if ((table[imin].reg_value <= reg_value) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) (reg_value <= table[i].reg_value))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) imax = i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) imin = i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) reg_diff = table[imax].reg_value - table[imin].reg_value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) gain = table[imin].value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) if (reg_diff != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) gain += ((s32)(reg_value - table[imin].reg_value) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) (s32)(table[imax].value
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) - table[imin].value)) / reg_diff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) return gain;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) static int get_rf_strength(struct dvb_frontend *fe, u16 *st)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) struct stv *state = fe->tuner_priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) u16 rfagc = *st;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) s32 gain;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) if ((state->reg[0x03] & 0x60) == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) /* RF Mode, Read AGC ADC */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) u8 reg = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) int stat = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) if (fe->ops.i2c_gate_ctrl)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) stat = fe->ops.i2c_gate_ctrl(fe, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) if (!stat) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) write_reg(state, 0x02, state->reg[0x02] | 0x20);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) read_reg(state, 2, ®);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) if (reg & 0x20)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) read_reg(state, 2, ®);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) if (fe->ops.i2c_gate_ctrl && !stat)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) fe->ops.i2c_gate_ctrl(fe, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) if ((state->reg[0x02] & 0x80) == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) /* NF */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) gain = table_lookup(lnagain_nf_lookup,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) ARRAY_SIZE(lnagain_nf_lookup),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) reg & 0x1F);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) /* IIP3 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) gain = table_lookup(lnagain_iip3_lookup,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) ARRAY_SIZE(lnagain_iip3_lookup),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) reg & 0x1F);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) gain += table_lookup(gain_rfagc_lookup,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) ARRAY_SIZE(gain_rfagc_lookup), rfagc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) gain -= 2400;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) /* Channel Mode */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) if ((state->reg[0x02] & 0x80) == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) /* NF */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) gain = table_lookup(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) gain_channel_agc_nf_lookup,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) ARRAY_SIZE(gain_channel_agc_nf_lookup), rfagc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) gain += 600;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) /* IIP3 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) gain = table_lookup(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) gain_channel_agc_iip3_lookup,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) ARRAY_SIZE(gain_channel_agc_iip3_lookup),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) rfagc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) if (state->frequency > 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) /* Tilt correction ( 0.00016 dB/MHz ) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) gain -= ((((s32)(state->frequency / 1000) - 1550) * 2) / 12);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) /* + (BBGain * 10); */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) gain += (s32)((state->reg[0x01] & 0xC0) >> 6) * 600 - 1300;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) if (gain < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) gain = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) else if (gain > 10000)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) gain = 10000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) *st = 10000 - gain;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) static const struct dvb_tuner_ops tuner_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) .info = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) .name = "ST STV6111",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) .frequency_min_hz = 950 * MHz,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) .frequency_max_hz = 2150 * MHz,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) .set_params = set_params,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) .release = release,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) .get_rf_strength = get_rf_strength,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) .set_bandwidth = set_bandwidth,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) struct dvb_frontend *stv6111_attach(struct dvb_frontend *fe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) struct i2c_adapter *i2c, u8 adr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) struct stv *state;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) int stat = -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) int gatestat = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) state = kzalloc(sizeof(*state), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) if (!state)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) state->adr = adr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) state->i2c = i2c;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) memcpy(&fe->ops.tuner_ops, &tuner_ops, sizeof(struct dvb_tuner_ops));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) init_state(state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) if (fe->ops.i2c_gate_ctrl)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) gatestat = fe->ops.i2c_gate_ctrl(fe, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) if (!gatestat)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) stat = attach_init(state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) if (fe->ops.i2c_gate_ctrl && !gatestat)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) fe->ops.i2c_gate_ctrl(fe, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) if (stat < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) kfree(state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) fe->tuner_priv = state;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) return fe;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) EXPORT_SYMBOL_GPL(stv6111_attach);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) MODULE_DESCRIPTION("ST STV6111 satellite tuner driver");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) MODULE_AUTHOR("Ralph Metzler, Manfred Voelkel");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) MODULE_LICENSE("GPL v2");