^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) // Rafael Micro R820T driver
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) //
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) // Copyright (C) 2013 Mauro Carvalho Chehab
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) //
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) // This driver was written from scratch, based on an existing driver
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) // that it is part of rtl-sdr git tree, released under GPLv2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) // https://groups.google.com/forum/#!topic/ultra-cheap-sdr/Y3rBEOFtHug
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) // https://github.com/n1gp/gr-baz
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) //
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) // From what I understood from the threads, the original driver was converted
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) // to userspace from a Realtek tree. I couldn't find the original tree.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) // However, the original driver look awkward on my eyes. So, I decided to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) // write a new version from it from the scratch, while trying to reproduce
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) // everything found there.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) //
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) // TODO:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) // After locking, the original driver seems to have some routines to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) // improve reception. This was not implemented here yet.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) //
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) // RF Gain set/get is not implemented.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) #include <linux/videodev2.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) #include <linux/mutex.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) #include <linux/bitrev.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) #include "tuner-i2c.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) #include "r820t.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) * FIXME: I think that there are only 32 registers, but better safe than
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) * sorry. After finishing the driver, we may review it.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) #define REG_SHADOW_START 5
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) #define NUM_REGS 27
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) #define NUM_IMR 5
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) #define IMR_TRIAL 9
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) #define VER_NUM 49
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) static int debug;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) module_param(debug, int, 0644);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) MODULE_PARM_DESC(debug, "enable verbose debug messages");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) static int no_imr_cal;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) module_param(no_imr_cal, int, 0444);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) MODULE_PARM_DESC(no_imr_cal, "Disable IMR calibration at module init");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) * enums and structures
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) enum xtal_cap_value {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) XTAL_LOW_CAP_30P = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) XTAL_LOW_CAP_20P,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) XTAL_LOW_CAP_10P,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) XTAL_LOW_CAP_0P,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) XTAL_HIGH_CAP_0P
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) struct r820t_sect_type {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) u8 phase_y;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) u8 gain_x;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) u16 value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) struct r820t_priv {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) struct list_head hybrid_tuner_instance_list;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) const struct r820t_config *cfg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) struct tuner_i2c_props i2c_props;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) struct mutex lock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) u8 regs[NUM_REGS];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) u8 buf[NUM_REGS + 1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) enum xtal_cap_value xtal_cap_sel;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) u16 pll; /* kHz */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) u32 int_freq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) u8 fil_cal_code;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) bool imr_done;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) bool has_lock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) bool init_done;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) struct r820t_sect_type imr_data[NUM_IMR];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) /* Store current mode */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) u32 delsys;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) enum v4l2_tuner_type type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) v4l2_std_id std;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) u32 bw; /* in MHz */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) struct r820t_freq_range {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) u32 freq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) u8 open_d;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) u8 rf_mux_ploy;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) u8 tf_c;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) u8 xtal_cap20p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) u8 xtal_cap10p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) u8 xtal_cap0p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) u8 imr_mem; /* Not used, currently */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) #define VCO_POWER_REF 0x02
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) #define DIP_FREQ 32000000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) * Static constants
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) static LIST_HEAD(hybrid_tuner_instance_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) static DEFINE_MUTEX(r820t_list_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) /* Those initial values start from REG_SHADOW_START */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) static const u8 r820t_init_array[NUM_REGS] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) 0x83, 0x32, 0x75, /* 05 to 07 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) 0xc0, 0x40, 0xd6, 0x6c, /* 08 to 0b */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) 0xf5, 0x63, 0x75, 0x68, /* 0c to 0f */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) 0x6c, 0x83, 0x80, 0x00, /* 10 to 13 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) 0x0f, 0x00, 0xc0, 0x30, /* 14 to 17 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) 0x48, 0xcc, 0x60, 0x00, /* 18 to 1b */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) 0x54, 0xae, 0x4a, 0xc0 /* 1c to 1f */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) /* Tuner frequency ranges */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) static const struct r820t_freq_range freq_ranges[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) .freq = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) .open_d = 0x08, /* low */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) .rf_mux_ploy = 0x02, /* R26[7:6]=0 (LPF) R26[1:0]=2 (low) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) .tf_c = 0xdf, /* R27[7:0] band2,band0 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) .xtal_cap20p = 0x02, /* R16[1:0] 20pF (10) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) .xtal_cap10p = 0x01,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) .xtal_cap0p = 0x00,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) .imr_mem = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) }, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) .freq = 50, /* Start freq, in MHz */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) .open_d = 0x08, /* low */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) .rf_mux_ploy = 0x02, /* R26[7:6]=0 (LPF) R26[1:0]=2 (low) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) .tf_c = 0xbe, /* R27[7:0] band4,band1 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) .xtal_cap20p = 0x02, /* R16[1:0] 20pF (10) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) .xtal_cap10p = 0x01,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) .xtal_cap0p = 0x00,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) .imr_mem = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) }, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) .freq = 55, /* Start freq, in MHz */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) .open_d = 0x08, /* low */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) .rf_mux_ploy = 0x02, /* R26[7:6]=0 (LPF) R26[1:0]=2 (low) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) .tf_c = 0x8b, /* R27[7:0] band7,band4 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) .xtal_cap20p = 0x02, /* R16[1:0] 20pF (10) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) .xtal_cap10p = 0x01,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) .xtal_cap0p = 0x00,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) .imr_mem = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) }, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) .freq = 60, /* Start freq, in MHz */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) .open_d = 0x08, /* low */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) .rf_mux_ploy = 0x02, /* R26[7:6]=0 (LPF) R26[1:0]=2 (low) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) .tf_c = 0x7b, /* R27[7:0] band8,band4 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) .xtal_cap20p = 0x02, /* R16[1:0] 20pF (10) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) .xtal_cap10p = 0x01,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) .xtal_cap0p = 0x00,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) .imr_mem = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) }, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) .freq = 65, /* Start freq, in MHz */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) .open_d = 0x08, /* low */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) .rf_mux_ploy = 0x02, /* R26[7:6]=0 (LPF) R26[1:0]=2 (low) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) .tf_c = 0x69, /* R27[7:0] band9,band6 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) .xtal_cap20p = 0x02, /* R16[1:0] 20pF (10) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) .xtal_cap10p = 0x01,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) .xtal_cap0p = 0x00,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) .imr_mem = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) }, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) .freq = 70, /* Start freq, in MHz */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) .open_d = 0x08, /* low */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) .rf_mux_ploy = 0x02, /* R26[7:6]=0 (LPF) R26[1:0]=2 (low) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) .tf_c = 0x58, /* R27[7:0] band10,band7 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) .xtal_cap20p = 0x02, /* R16[1:0] 20pF (10) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) .xtal_cap10p = 0x01,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) .xtal_cap0p = 0x00,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) .imr_mem = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) }, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) .freq = 75, /* Start freq, in MHz */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) .open_d = 0x00, /* high */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) .rf_mux_ploy = 0x02, /* R26[7:6]=0 (LPF) R26[1:0]=2 (low) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) .tf_c = 0x44, /* R27[7:0] band11,band11 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) .xtal_cap20p = 0x02, /* R16[1:0] 20pF (10) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) .xtal_cap10p = 0x01,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) .xtal_cap0p = 0x00,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) .imr_mem = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) }, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) .freq = 80, /* Start freq, in MHz */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) .open_d = 0x00, /* high */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) .rf_mux_ploy = 0x02, /* R26[7:6]=0 (LPF) R26[1:0]=2 (low) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) .tf_c = 0x44, /* R27[7:0] band11,band11 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) .xtal_cap20p = 0x02, /* R16[1:0] 20pF (10) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) .xtal_cap10p = 0x01,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) .xtal_cap0p = 0x00,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) .imr_mem = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) }, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) .freq = 90, /* Start freq, in MHz */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) .open_d = 0x00, /* high */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) .rf_mux_ploy = 0x02, /* R26[7:6]=0 (LPF) R26[1:0]=2 (low) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) .tf_c = 0x34, /* R27[7:0] band12,band11 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) .xtal_cap20p = 0x01, /* R16[1:0] 10pF (01) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) .xtal_cap10p = 0x01,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) .xtal_cap0p = 0x00,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) .imr_mem = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) }, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) .freq = 100, /* Start freq, in MHz */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) .open_d = 0x00, /* high */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) .rf_mux_ploy = 0x02, /* R26[7:6]=0 (LPF) R26[1:0]=2 (low) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) .tf_c = 0x34, /* R27[7:0] band12,band11 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) .xtal_cap20p = 0x01, /* R16[1:0] 10pF (01) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) .xtal_cap10p = 0x01,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) .xtal_cap0p = 0x00,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) .imr_mem = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) }, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) .freq = 110, /* Start freq, in MHz */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) .open_d = 0x00, /* high */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) .rf_mux_ploy = 0x02, /* R26[7:6]=0 (LPF) R26[1:0]=2 (low) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) .tf_c = 0x24, /* R27[7:0] band13,band11 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) .xtal_cap20p = 0x01, /* R16[1:0] 10pF (01) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) .xtal_cap10p = 0x01,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) .xtal_cap0p = 0x00,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) .imr_mem = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) }, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) .freq = 120, /* Start freq, in MHz */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) .open_d = 0x00, /* high */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) .rf_mux_ploy = 0x02, /* R26[7:6]=0 (LPF) R26[1:0]=2 (low) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) .tf_c = 0x24, /* R27[7:0] band13,band11 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) .xtal_cap20p = 0x01, /* R16[1:0] 10pF (01) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) .xtal_cap10p = 0x01,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) .xtal_cap0p = 0x00,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) .imr_mem = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) }, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) .freq = 140, /* Start freq, in MHz */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) .open_d = 0x00, /* high */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) .rf_mux_ploy = 0x02, /* R26[7:6]=0 (LPF) R26[1:0]=2 (low) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) .tf_c = 0x14, /* R27[7:0] band14,band11 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) .xtal_cap20p = 0x01, /* R16[1:0] 10pF (01) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) .xtal_cap10p = 0x01,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) .xtal_cap0p = 0x00,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) .imr_mem = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) }, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) .freq = 180, /* Start freq, in MHz */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) .open_d = 0x00, /* high */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) .rf_mux_ploy = 0x02, /* R26[7:6]=0 (LPF) R26[1:0]=2 (low) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) .tf_c = 0x13, /* R27[7:0] band14,band12 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) .xtal_cap20p = 0x00, /* R16[1:0] 0pF (00) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) .xtal_cap10p = 0x00,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) .xtal_cap0p = 0x00,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) .imr_mem = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) }, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) .freq = 220, /* Start freq, in MHz */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) .open_d = 0x00, /* high */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) .rf_mux_ploy = 0x02, /* R26[7:6]=0 (LPF) R26[1:0]=2 (low) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) .tf_c = 0x13, /* R27[7:0] band14,band12 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) .xtal_cap20p = 0x00, /* R16[1:0] 0pF (00) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) .xtal_cap10p = 0x00,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) .xtal_cap0p = 0x00,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) .imr_mem = 2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) }, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) .freq = 250, /* Start freq, in MHz */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) .open_d = 0x00, /* high */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) .rf_mux_ploy = 0x02, /* R26[7:6]=0 (LPF) R26[1:0]=2 (low) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) .tf_c = 0x11, /* R27[7:0] highest,highest */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) .xtal_cap20p = 0x00, /* R16[1:0] 0pF (00) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) .xtal_cap10p = 0x00,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) .xtal_cap0p = 0x00,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) .imr_mem = 2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) }, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) .freq = 280, /* Start freq, in MHz */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) .open_d = 0x00, /* high */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) .rf_mux_ploy = 0x02, /* R26[7:6]=0 (LPF) R26[1:0]=2 (low) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) .tf_c = 0x00, /* R27[7:0] highest,highest */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) .xtal_cap20p = 0x00, /* R16[1:0] 0pF (00) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) .xtal_cap10p = 0x00,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) .xtal_cap0p = 0x00,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) .imr_mem = 2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) }, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) .freq = 310, /* Start freq, in MHz */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) .open_d = 0x00, /* high */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) .rf_mux_ploy = 0x41, /* R26[7:6]=1 (bypass) R26[1:0]=1 (middle) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) .tf_c = 0x00, /* R27[7:0] highest,highest */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) .xtal_cap20p = 0x00, /* R16[1:0] 0pF (00) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) .xtal_cap10p = 0x00,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) .xtal_cap0p = 0x00,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) .imr_mem = 2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) }, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) .freq = 450, /* Start freq, in MHz */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) .open_d = 0x00, /* high */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) .rf_mux_ploy = 0x41, /* R26[7:6]=1 (bypass) R26[1:0]=1 (middle) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) .tf_c = 0x00, /* R27[7:0] highest,highest */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) .xtal_cap20p = 0x00, /* R16[1:0] 0pF (00) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) .xtal_cap10p = 0x00,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) .xtal_cap0p = 0x00,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) .imr_mem = 3,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) }, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) .freq = 588, /* Start freq, in MHz */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) .open_d = 0x00, /* high */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) .rf_mux_ploy = 0x40, /* R26[7:6]=1 (bypass) R26[1:0]=0 (highest) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) .tf_c = 0x00, /* R27[7:0] highest,highest */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) .xtal_cap20p = 0x00, /* R16[1:0] 0pF (00) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) .xtal_cap10p = 0x00,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) .xtal_cap0p = 0x00,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) .imr_mem = 3,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) }, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) .freq = 650, /* Start freq, in MHz */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) .open_d = 0x00, /* high */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) .rf_mux_ploy = 0x40, /* R26[7:6]=1 (bypass) R26[1:0]=0 (highest) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) .tf_c = 0x00, /* R27[7:0] highest,highest */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) .xtal_cap20p = 0x00, /* R16[1:0] 0pF (00) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) .xtal_cap10p = 0x00,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) .xtal_cap0p = 0x00,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) .imr_mem = 4,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) static int r820t_xtal_capacitor[][2] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) { 0x0b, XTAL_LOW_CAP_30P },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) { 0x02, XTAL_LOW_CAP_20P },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) { 0x01, XTAL_LOW_CAP_10P },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) { 0x00, XTAL_LOW_CAP_0P },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) { 0x10, XTAL_HIGH_CAP_0P },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) };
^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) * I2C read/write code and shadow registers logic
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) static void shadow_store(struct r820t_priv *priv, u8 reg, const u8 *val,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) int len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) int r = reg - REG_SHADOW_START;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) if (r < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) len += r;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) r = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) if (len <= 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) if (len > NUM_REGS - r)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) len = NUM_REGS - r;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) tuner_dbg("%s: prev reg=%02x len=%d: %*ph\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) __func__, r + REG_SHADOW_START, len, len, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) memcpy(&priv->regs[r], val, len);
^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 r820t_write(struct r820t_priv *priv, u8 reg, const u8 *val,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) int len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) int rc, size, pos = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) /* Store the shadow registers */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) shadow_store(priv, reg, val, len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) if (len > priv->cfg->max_i2c_msg_len - 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) size = priv->cfg->max_i2c_msg_len - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) size = len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) /* Fill I2C buffer */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) priv->buf[0] = reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) memcpy(&priv->buf[1], &val[pos], size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) rc = tuner_i2c_xfer_send(&priv->i2c_props, priv->buf, size + 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) if (rc != size + 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) tuner_info("%s: i2c wr failed=%d reg=%02x len=%d: %*ph\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) __func__, rc, reg, size, size, &priv->buf[1]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) if (rc < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) return -EREMOTEIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) tuner_dbg("%s: i2c wr reg=%02x len=%d: %*ph\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) __func__, reg, size, size, &priv->buf[1]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) reg += size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) len -= size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) pos += size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) } while (len > 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) static inline int r820t_write_reg(struct r820t_priv *priv, u8 reg, u8 val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) u8 tmp = val; /* work around GCC PR81715 with asan-stack=1 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) return r820t_write(priv, reg, &tmp, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) static int r820t_read_cache_reg(struct r820t_priv *priv, int reg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) reg -= REG_SHADOW_START;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) if (reg >= 0 && reg < NUM_REGS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) return priv->regs[reg];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) static inline int r820t_write_reg_mask(struct r820t_priv *priv, u8 reg, u8 val,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) u8 bit_mask)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) u8 tmp = val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) int rc = r820t_read_cache_reg(priv, reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) if (rc < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) tmp = (rc & ~bit_mask) | (tmp & bit_mask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) return r820t_write(priv, reg, &tmp, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) static int r820t_read(struct r820t_priv *priv, u8 reg, u8 *val, int len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) int rc, i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) u8 *p = &priv->buf[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) priv->buf[0] = reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) rc = tuner_i2c_xfer_send_recv(&priv->i2c_props, priv->buf, 1, p, len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) if (rc != len) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) tuner_info("%s: i2c rd failed=%d reg=%02x len=%d: %*ph\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) __func__, rc, reg, len, len, p);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) if (rc < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) return -EREMOTEIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) /* Copy data to the output buffer */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) for (i = 0; i < len; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) val[i] = bitrev8(p[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) tuner_dbg("%s: i2c rd reg=%02x len=%d: %*ph\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) __func__, reg, len, len, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) * r820t tuning logic
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) static int r820t_set_mux(struct r820t_priv *priv, u32 freq)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) const struct r820t_freq_range *range;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) int i, rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) u8 val, reg08, reg09;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) /* Get the proper frequency range */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) freq = freq / 1000000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) for (i = 0; i < ARRAY_SIZE(freq_ranges) - 1; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) if (freq < freq_ranges[i + 1].freq)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) range = &freq_ranges[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) tuner_dbg("set r820t range#%d for frequency %d MHz\n", i, freq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) /* Open Drain */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) rc = r820t_write_reg_mask(priv, 0x17, range->open_d, 0x08);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) if (rc < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) /* RF_MUX,Polymux */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) rc = r820t_write_reg_mask(priv, 0x1a, range->rf_mux_ploy, 0xc3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) if (rc < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) /* TF BAND */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) rc = r820t_write_reg(priv, 0x1b, range->tf_c);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) if (rc < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) /* XTAL CAP & Drive */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) switch (priv->xtal_cap_sel) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) case XTAL_LOW_CAP_30P:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) case XTAL_LOW_CAP_20P:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) val = range->xtal_cap20p | 0x08;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) case XTAL_LOW_CAP_10P:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) val = range->xtal_cap10p | 0x08;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) case XTAL_HIGH_CAP_0P:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) val = range->xtal_cap0p | 0x00;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) case XTAL_LOW_CAP_0P:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) val = range->xtal_cap0p | 0x08;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) rc = r820t_write_reg_mask(priv, 0x10, val, 0x0b);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) if (rc < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) if (priv->imr_done) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) reg08 = priv->imr_data[range->imr_mem].gain_x;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) reg09 = priv->imr_data[range->imr_mem].phase_y;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) reg08 = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) reg09 = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) rc = r820t_write_reg_mask(priv, 0x08, reg08, 0x3f);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) if (rc < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) rc = r820t_write_reg_mask(priv, 0x09, reg09, 0x3f);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) static int r820t_set_pll(struct r820t_priv *priv, enum v4l2_tuner_type type,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) u32 freq)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) u32 vco_freq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) int rc, i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) unsigned sleep_time = 10000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) u32 vco_fra; /* VCO contribution by SDM (kHz) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) u32 vco_min = 1770000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) u32 vco_max = vco_min * 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) u32 pll_ref;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) u16 n_sdm = 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) u16 sdm = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) u8 mix_div = 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) u8 div_buf = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) u8 div_num = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) u8 refdiv2 = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) u8 ni, si, nint, vco_fine_tune, val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) u8 data[5];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) /* Frequency in kHz */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) freq = freq / 1000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) pll_ref = priv->cfg->xtal / 1000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) #if 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) /* Doesn't exist on rtl-sdk, and on field tests, caused troubles */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) if ((priv->cfg->rafael_chip == CHIP_R620D) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) (priv->cfg->rafael_chip == CHIP_R828D) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) (priv->cfg->rafael_chip == CHIP_R828)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) /* ref set refdiv2, reffreq = Xtal/2 on ATV application */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) if (type != V4L2_TUNER_DIGITAL_TV) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) pll_ref /= 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) refdiv2 = 0x10;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) sleep_time = 20000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) if (priv->cfg->xtal > 24000000) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) pll_ref /= 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) refdiv2 = 0x10;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) rc = r820t_write_reg_mask(priv, 0x10, refdiv2, 0x10);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) if (rc < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) /* set pll autotune = 128kHz */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) rc = r820t_write_reg_mask(priv, 0x1a, 0x00, 0x0c);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) if (rc < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) /* set VCO current = 100 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) rc = r820t_write_reg_mask(priv, 0x12, 0x80, 0xe0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) if (rc < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) /* Calculate divider */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) while (mix_div <= 64) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) if (((freq * mix_div) >= vco_min) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) ((freq * mix_div) < vco_max)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) div_buf = mix_div;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) while (div_buf > 2) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) div_buf = div_buf >> 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) div_num++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) mix_div = mix_div << 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) rc = r820t_read(priv, 0x00, data, sizeof(data));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) if (rc < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) vco_fine_tune = (data[4] & 0x30) >> 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) tuner_dbg("mix_div=%d div_num=%d vco_fine_tune=%d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) mix_div, div_num, vco_fine_tune);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) * XXX: R828D/16MHz seems to have always vco_fine_tune=1.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) * Due to that, this calculation goes wrong.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) if (priv->cfg->rafael_chip != CHIP_R828D) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) if (vco_fine_tune > VCO_POWER_REF)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) div_num = div_num - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) else if (vco_fine_tune < VCO_POWER_REF)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) div_num = div_num + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) rc = r820t_write_reg_mask(priv, 0x10, div_num << 5, 0xe0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) if (rc < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) vco_freq = freq * mix_div;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) nint = vco_freq / (2 * pll_ref);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) vco_fra = vco_freq - 2 * pll_ref * nint;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) /* boundary spur prevention */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) if (vco_fra < pll_ref / 64) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) vco_fra = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) } else if (vco_fra > pll_ref * 127 / 64) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) vco_fra = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) nint++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) } else if ((vco_fra > pll_ref * 127 / 128) && (vco_fra < pll_ref)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) vco_fra = pll_ref * 127 / 128;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) } else if ((vco_fra > pll_ref) && (vco_fra < pll_ref * 129 / 128)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) vco_fra = pll_ref * 129 / 128;
^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) ni = (nint - 13) / 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) si = nint - 4 * ni - 13;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) rc = r820t_write_reg(priv, 0x14, ni + (si << 6));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) if (rc < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) /* pw_sdm */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) if (!vco_fra)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) val = 0x08;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) val = 0x00;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) rc = r820t_write_reg_mask(priv, 0x12, val, 0x08);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) if (rc < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) /* sdm calculator */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) while (vco_fra > 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) if (vco_fra > (2 * pll_ref / n_sdm)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) sdm = sdm + 32768 / (n_sdm / 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) vco_fra = vco_fra - 2 * pll_ref / n_sdm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) if (n_sdm >= 0x8000)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) n_sdm = n_sdm << 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) tuner_dbg("freq %d kHz, pll ref %d%s, sdm=0x%04x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) freq, pll_ref, refdiv2 ? " / 2" : "", sdm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) rc = r820t_write_reg(priv, 0x16, sdm >> 8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) if (rc < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) rc = r820t_write_reg(priv, 0x15, sdm & 0xff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) if (rc < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) for (i = 0; i < 2; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) usleep_range(sleep_time, sleep_time + 1000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) /* Check if PLL has locked */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) rc = r820t_read(priv, 0x00, data, 3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) if (rc < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) if (data[2] & 0x40)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) if (!i) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) /* Didn't lock. Increase VCO current */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) rc = r820t_write_reg_mask(priv, 0x12, 0x60, 0xe0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) if (rc < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) if (!(data[2] & 0x40)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) priv->has_lock = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) priv->has_lock = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) tuner_dbg("tuner has lock at frequency %d kHz\n", freq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) /* set pll autotune = 8kHz */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) rc = r820t_write_reg_mask(priv, 0x1a, 0x08, 0x08);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) static int r820t_sysfreq_sel(struct r820t_priv *priv, u32 freq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) enum v4l2_tuner_type type,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) v4l2_std_id std,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) u32 delsys)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) u8 mixer_top, lna_top, cp_cur, div_buf_cur, lna_vth_l, mixer_vth_l;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) u8 air_cable1_in, cable2_in, pre_dect, lna_discharge, filter_cur;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) tuner_dbg("adjusting tuner parameters for the standard\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) switch (delsys) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) case SYS_DVBT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711) if ((freq == 506000000) || (freq == 666000000) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) (freq == 818000000)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) mixer_top = 0x14; /* mixer top:14 , top-1, low-discharge */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714) lna_top = 0xe5; /* detect bw 3, lna top:4, predet top:2 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) cp_cur = 0x28; /* 101, 0.2 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) div_buf_cur = 0x20; /* 10, 200u */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) mixer_top = 0x24; /* mixer top:13 , top-1, low-discharge */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719) lna_top = 0xe5; /* detect bw 3, lna top:4, predet top:2 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) cp_cur = 0x38; /* 111, auto */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) div_buf_cur = 0x30; /* 11, 150u */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723) lna_vth_l = 0x53; /* lna vth 0.84 , vtl 0.64 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) mixer_vth_l = 0x75; /* mixer vth 1.04, vtl 0.84 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) air_cable1_in = 0x00;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726) cable2_in = 0x00;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727) pre_dect = 0x40;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) lna_discharge = 14;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729) filter_cur = 0x40; /* 10, low */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) case SYS_DVBT2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732) mixer_top = 0x24; /* mixer top:13 , top-1, low-discharge */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733) lna_top = 0xe5; /* detect bw 3, lna top:4, predet top:2 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) lna_vth_l = 0x53; /* lna vth 0.84 , vtl 0.64 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735) mixer_vth_l = 0x75; /* mixer vth 1.04, vtl 0.84 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736) air_cable1_in = 0x00;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) cable2_in = 0x00;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738) pre_dect = 0x40;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739) lna_discharge = 14;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740) cp_cur = 0x38; /* 111, auto */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741) div_buf_cur = 0x30; /* 11, 150u */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742) filter_cur = 0x40; /* 10, low */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744) case SYS_ISDBT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) mixer_top = 0x24; /* mixer top:13 , top-1, low-discharge */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746) lna_top = 0xe5; /* detect bw 3, lna top:4, predet top:2 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747) lna_vth_l = 0x75; /* lna vth 1.04 , vtl 0.84 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748) mixer_vth_l = 0x75; /* mixer vth 1.04, vtl 0.84 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) air_cable1_in = 0x00;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) cable2_in = 0x00;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) pre_dect = 0x40;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752) lna_discharge = 14;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753) cp_cur = 0x38; /* 111, auto */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754) div_buf_cur = 0x30; /* 11, 150u */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755) filter_cur = 0x40; /* 10, low */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757) case SYS_DVBC_ANNEX_A:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758) mixer_top = 0x24; /* mixer top:13 , top-1, low-discharge */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759) lna_top = 0xe5;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760) lna_vth_l = 0x62;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761) mixer_vth_l = 0x75;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762) air_cable1_in = 0x60;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763) cable2_in = 0x00;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764) pre_dect = 0x40;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765) lna_discharge = 14;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766) cp_cur = 0x38; /* 111, auto */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767) div_buf_cur = 0x30; /* 11, 150u */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768) filter_cur = 0x40; /* 10, low */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770) default: /* DVB-T 8M */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771) mixer_top = 0x24; /* mixer top:13 , top-1, low-discharge */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772) lna_top = 0xe5; /* detect bw 3, lna top:4, predet top:2 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773) lna_vth_l = 0x53; /* lna vth 0.84 , vtl 0.64 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774) mixer_vth_l = 0x75; /* mixer vth 1.04, vtl 0.84 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775) air_cable1_in = 0x00;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776) cable2_in = 0x00;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777) pre_dect = 0x40;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778) lna_discharge = 14;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779) cp_cur = 0x38; /* 111, auto */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780) div_buf_cur = 0x30; /* 11, 150u */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781) filter_cur = 0x40; /* 10, low */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785) if (priv->cfg->use_diplexer &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786) ((priv->cfg->rafael_chip == CHIP_R820T) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787) (priv->cfg->rafael_chip == CHIP_R828S) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788) (priv->cfg->rafael_chip == CHIP_R820C))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789) if (freq > DIP_FREQ)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790) air_cable1_in = 0x00;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792) air_cable1_in = 0x60;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793) cable2_in = 0x00;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797) if (priv->cfg->use_predetect) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798) rc = r820t_write_reg_mask(priv, 0x06, pre_dect, 0x40);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799) if (rc < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803) rc = r820t_write_reg_mask(priv, 0x1d, lna_top, 0xc7);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804) if (rc < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806) rc = r820t_write_reg_mask(priv, 0x1c, mixer_top, 0xf8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807) if (rc < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809) rc = r820t_write_reg(priv, 0x0d, lna_vth_l);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810) if (rc < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812) rc = r820t_write_reg(priv, 0x0e, mixer_vth_l);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813) if (rc < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816) /* Air-IN only for Astrometa */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817) rc = r820t_write_reg_mask(priv, 0x05, air_cable1_in, 0x60);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818) if (rc < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820) rc = r820t_write_reg_mask(priv, 0x06, cable2_in, 0x08);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821) if (rc < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824) rc = r820t_write_reg_mask(priv, 0x11, cp_cur, 0x38);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825) if (rc < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827) rc = r820t_write_reg_mask(priv, 0x17, div_buf_cur, 0x30);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828) if (rc < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830) rc = r820t_write_reg_mask(priv, 0x0a, filter_cur, 0x60);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831) if (rc < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834) * Original driver initializes regs 0x05 and 0x06 with the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835) * same value again on this point. Probably, it is just an
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836) * error there
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840) * Set LNA
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843) tuner_dbg("adjusting LNA parameters\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844) if (type != V4L2_TUNER_ANALOG_TV) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845) /* LNA TOP: lowest */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846) rc = r820t_write_reg_mask(priv, 0x1d, 0, 0x38);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847) if (rc < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850) /* 0: normal mode */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 851) rc = r820t_write_reg_mask(priv, 0x1c, 0, 0x04);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852) if (rc < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 853) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 855) /* 0: PRE_DECT off */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 856) rc = r820t_write_reg_mask(priv, 0x06, 0, 0x40);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 857) if (rc < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 858) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 859)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 860) /* agc clk 250hz */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 861) rc = r820t_write_reg_mask(priv, 0x1a, 0x30, 0x30);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 862) if (rc < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 863) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 864)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 865) msleep(250);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 866)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 867) /* write LNA TOP = 3 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 868) rc = r820t_write_reg_mask(priv, 0x1d, 0x18, 0x38);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 869) if (rc < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 870) return rc;
^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) * write discharge mode
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 874) * FIXME: IMHO, the mask here is wrong, but it matches
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 875) * what's there at the original driver
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 876) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 877) rc = r820t_write_reg_mask(priv, 0x1c, mixer_top, 0x04);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 878) if (rc < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 879) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 880)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 881) /* LNA discharge current */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 882) rc = r820t_write_reg_mask(priv, 0x1e, lna_discharge, 0x1f);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 883) if (rc < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 884) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 885)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 886) /* agc clk 60hz */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 887) rc = r820t_write_reg_mask(priv, 0x1a, 0x20, 0x30);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 888) if (rc < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 889) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 890) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 891) /* PRE_DECT off */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 892) rc = r820t_write_reg_mask(priv, 0x06, 0, 0x40);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 893) if (rc < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 894) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 895)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 896) /* write LNA TOP */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 897) rc = r820t_write_reg_mask(priv, 0x1d, lna_top, 0x38);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 898) if (rc < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 899) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 900)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 901) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 902) * write discharge mode
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 903) * FIXME: IMHO, the mask here is wrong, but it matches
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 904) * what's there at the original driver
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 905) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 906) rc = r820t_write_reg_mask(priv, 0x1c, mixer_top, 0x04);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 907) if (rc < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 908) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 909)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 910) /* LNA discharge current */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 911) rc = r820t_write_reg_mask(priv, 0x1e, lna_discharge, 0x1f);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 912) if (rc < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 913) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 914)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 915) /* agc clk 1Khz, external det1 cap 1u */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 916) rc = r820t_write_reg_mask(priv, 0x1a, 0x00, 0x30);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 917) if (rc < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 918) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 919)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 920) rc = r820t_write_reg_mask(priv, 0x10, 0x00, 0x04);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 921) if (rc < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 922) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 923) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 924) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 925) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 926)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 927) static int r820t_set_tv_standard(struct r820t_priv *priv,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 928) unsigned bw,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 929) enum v4l2_tuner_type type,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 930) v4l2_std_id std, u32 delsys)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 931)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 932) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 933) int rc, i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 934) u32 if_khz, filt_cal_lo;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 935) u8 data[5], val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 936) u8 filt_gain, img_r, filt_q, hp_cor, ext_enable, loop_through;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 937) u8 lt_att, flt_ext_widest, polyfil_cur;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 938) bool need_calibration;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 939)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 940) tuner_dbg("selecting the delivery system\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 941)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 942) if (delsys == SYS_ISDBT) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 943) if_khz = 4063;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 944) filt_cal_lo = 59000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 945) filt_gain = 0x10; /* +3db, 6mhz on */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 946) img_r = 0x00; /* image negative */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 947) filt_q = 0x10; /* r10[4]:low q(1'b1) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 948) hp_cor = 0x6a; /* 1.7m disable, +2cap, 1.25mhz */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 949) ext_enable = 0x40; /* r30[6], ext enable; r30[5]:0 ext at lna max */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 950) loop_through = 0x00; /* r5[7], lt on */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 951) lt_att = 0x00; /* r31[7], lt att enable */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 952) flt_ext_widest = 0x80; /* r15[7]: flt_ext_wide on */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 953) polyfil_cur = 0x60; /* r25[6:5]:min */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 954) } else if (delsys == SYS_DVBC_ANNEX_A) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 955) if_khz = 5070;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 956) filt_cal_lo = 73500;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 957) filt_gain = 0x10; /* +3db, 6mhz on */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 958) img_r = 0x00; /* image negative */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 959) filt_q = 0x10; /* r10[4]:low q(1'b1) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 960) hp_cor = 0x0b; /* 1.7m disable, +0cap, 1.0mhz */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 961) ext_enable = 0x40; /* r30[6]=1 ext enable; r30[5]:1 ext at lna max-1 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 962) loop_through = 0x00; /* r5[7], lt on */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 963) lt_att = 0x00; /* r31[7], lt att enable */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 964) flt_ext_widest = 0x00; /* r15[7]: flt_ext_wide off */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 965) polyfil_cur = 0x60; /* r25[6:5]:min */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 966) } else if (delsys == SYS_DVBC_ANNEX_C) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 967) if_khz = 4063;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 968) filt_cal_lo = 55000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 969) filt_gain = 0x10; /* +3db, 6mhz on */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 970) img_r = 0x00; /* image negative */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 971) filt_q = 0x10; /* r10[4]:low q(1'b1) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 972) hp_cor = 0x6a; /* 1.7m disable, +0cap, 1.0mhz */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 973) ext_enable = 0x40; /* r30[6]=1 ext enable; r30[5]:1 ext at lna max-1 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 974) loop_through = 0x00; /* r5[7], lt on */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 975) lt_att = 0x00; /* r31[7], lt att enable */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 976) flt_ext_widest = 0x80; /* r15[7]: flt_ext_wide on */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 977) polyfil_cur = 0x60; /* r25[6:5]:min */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 978) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 979) if (bw <= 6) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 980) if_khz = 3570;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 981) filt_cal_lo = 56000; /* 52000->56000 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 982) filt_gain = 0x10; /* +3db, 6mhz on */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 983) img_r = 0x00; /* image negative */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 984) filt_q = 0x10; /* r10[4]:low q(1'b1) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 985) hp_cor = 0x6b; /* 1.7m disable, +2cap, 1.0mhz */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 986) ext_enable = 0x60; /* r30[6]=1 ext enable; r30[5]:1 ext at lna max-1 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 987) loop_through = 0x00; /* r5[7], lt on */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 988) lt_att = 0x00; /* r31[7], lt att enable */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 989) flt_ext_widest = 0x00; /* r15[7]: flt_ext_wide off */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 990) polyfil_cur = 0x60; /* r25[6:5]:min */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 991) } else if (bw == 7) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 992) #if 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 993) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 994) * There are two 7 MHz tables defined on the original
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 995) * driver, but just the second one seems to be visible
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 996) * by rtl2832. Keep this one here commented, as it
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 997) * might be needed in the future
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 998) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 999)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1000) if_khz = 4070;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1001) filt_cal_lo = 60000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1002) filt_gain = 0x10; /* +3db, 6mhz on */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1003) img_r = 0x00; /* image negative */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1004) filt_q = 0x10; /* r10[4]:low q(1'b1) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1005) hp_cor = 0x2b; /* 1.7m disable, +1cap, 1.0mhz */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1006) ext_enable = 0x60; /* r30[6]=1 ext enable; r30[5]:1 ext at lna max-1 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1007) loop_through = 0x00; /* r5[7], lt on */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1008) lt_att = 0x00; /* r31[7], lt att enable */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1009) flt_ext_widest = 0x00; /* r15[7]: flt_ext_wide off */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1010) polyfil_cur = 0x60; /* r25[6:5]:min */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1011) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1012) /* 7 MHz, second table */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1013) if_khz = 4570;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1014) filt_cal_lo = 63000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1015) filt_gain = 0x10; /* +3db, 6mhz on */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1016) img_r = 0x00; /* image negative */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1017) filt_q = 0x10; /* r10[4]:low q(1'b1) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1018) hp_cor = 0x2a; /* 1.7m disable, +1cap, 1.25mhz */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1019) ext_enable = 0x60; /* r30[6]=1 ext enable; r30[5]:1 ext at lna max-1 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1020) loop_through = 0x00; /* r5[7], lt on */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1021) lt_att = 0x00; /* r31[7], lt att enable */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1022) flt_ext_widest = 0x00; /* r15[7]: flt_ext_wide off */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1023) polyfil_cur = 0x60; /* r25[6:5]:min */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1024) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1025) if_khz = 4570;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1026) filt_cal_lo = 68500;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1027) filt_gain = 0x10; /* +3db, 6mhz on */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1028) img_r = 0x00; /* image negative */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1029) filt_q = 0x10; /* r10[4]:low q(1'b1) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1030) hp_cor = 0x0b; /* 1.7m disable, +0cap, 1.0mhz */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1031) ext_enable = 0x60; /* r30[6]=1 ext enable; r30[5]:1 ext at lna max-1 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1032) loop_through = 0x00; /* r5[7], lt on */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1033) lt_att = 0x00; /* r31[7], lt att enable */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1034) flt_ext_widest = 0x00; /* r15[7]: flt_ext_wide off */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1035) polyfil_cur = 0x60; /* r25[6:5]:min */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1036) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1037) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1038)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1039) /* Initialize the shadow registers */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1040) memcpy(priv->regs, r820t_init_array, sizeof(r820t_init_array));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1041)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1042) /* Init Flag & Xtal_check Result */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1043) if (priv->imr_done)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1044) val = 1 | priv->xtal_cap_sel << 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1045) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1046) val = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1047) rc = r820t_write_reg_mask(priv, 0x0c, val, 0x0f);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1048) if (rc < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1049) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1050)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1051) /* version */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1052) rc = r820t_write_reg_mask(priv, 0x13, VER_NUM, 0x3f);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1053) if (rc < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1054) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1055)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1056) /* for LT Gain test */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1057) if (type != V4L2_TUNER_ANALOG_TV) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1058) rc = r820t_write_reg_mask(priv, 0x1d, 0x00, 0x38);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1059) if (rc < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1060) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1061) usleep_range(1000, 2000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1062) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1063) priv->int_freq = if_khz * 1000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1064)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1065) /* Check if standard changed. If so, filter calibration is needed */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1066) if (type != priv->type)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1067) need_calibration = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1068) else if ((type == V4L2_TUNER_ANALOG_TV) && (std != priv->std))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1069) need_calibration = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1070) else if ((type == V4L2_TUNER_DIGITAL_TV) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1071) ((delsys != priv->delsys) || bw != priv->bw))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1072) need_calibration = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1073) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1074) need_calibration = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1075)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1076) if (need_calibration) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1077) tuner_dbg("calibrating the tuner\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1078) for (i = 0; i < 2; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1079) /* Set filt_cap */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1080) rc = r820t_write_reg_mask(priv, 0x0b, hp_cor, 0x60);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1081) if (rc < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1082) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1083)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1084) /* set cali clk =on */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1085) rc = r820t_write_reg_mask(priv, 0x0f, 0x04, 0x04);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1086) if (rc < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1087) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1088)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1089) /* X'tal cap 0pF for PLL */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1090) rc = r820t_write_reg_mask(priv, 0x10, 0x00, 0x03);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1091) if (rc < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1092) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1093)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1094) rc = r820t_set_pll(priv, type, filt_cal_lo * 1000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1095) if (rc < 0 || !priv->has_lock)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1096) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1097)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1098) /* Start Trigger */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1099) rc = r820t_write_reg_mask(priv, 0x0b, 0x10, 0x10);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1100) if (rc < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1101) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1102)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1103) usleep_range(1000, 2000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1104)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1105) /* Stop Trigger */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1106) rc = r820t_write_reg_mask(priv, 0x0b, 0x00, 0x10);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1107) if (rc < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1108) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1109)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1110) /* set cali clk =off */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1111) rc = r820t_write_reg_mask(priv, 0x0f, 0x00, 0x04);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1112) if (rc < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1113) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1114)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1115) /* Check if calibration worked */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1116) rc = r820t_read(priv, 0x00, data, sizeof(data));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1117) if (rc < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1118) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1119)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1120) priv->fil_cal_code = data[4] & 0x0f;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1121) if (priv->fil_cal_code && priv->fil_cal_code != 0x0f)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1122) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1123) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1124) /* narrowest */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1125) if (priv->fil_cal_code == 0x0f)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1126) priv->fil_cal_code = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1127) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1128)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1129) rc = r820t_write_reg_mask(priv, 0x0a,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1130) filt_q | priv->fil_cal_code, 0x1f);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1131) if (rc < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1132) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1133)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1134) /* Set BW, Filter_gain, & HP corner */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1135) rc = r820t_write_reg_mask(priv, 0x0b, hp_cor, 0xef);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1136) if (rc < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1137) return rc;
^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) /* Set Img_R */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1141) rc = r820t_write_reg_mask(priv, 0x07, img_r, 0x80);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1142) if (rc < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1143) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1144)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1145) /* Set filt_3dB, V6MHz */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1146) rc = r820t_write_reg_mask(priv, 0x06, filt_gain, 0x30);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1147) if (rc < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1148) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1149)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1150) /* channel filter extension */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1151) rc = r820t_write_reg_mask(priv, 0x1e, ext_enable, 0x60);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1152) if (rc < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1153) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1154)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1155) /* Loop through */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1156) rc = r820t_write_reg_mask(priv, 0x05, loop_through, 0x80);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1157) if (rc < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1158) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1159)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1160) /* Loop through attenuation */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1161) rc = r820t_write_reg_mask(priv, 0x1f, lt_att, 0x80);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1162) if (rc < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1163) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1164)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1165) /* filter extension widest */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1166) rc = r820t_write_reg_mask(priv, 0x0f, flt_ext_widest, 0x80);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1167) if (rc < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1168) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1169)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1170) /* RF poly filter current */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1171) rc = r820t_write_reg_mask(priv, 0x19, polyfil_cur, 0x60);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1172) if (rc < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1173) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1174)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1175) /* Store current standard. If it changes, re-calibrate the tuner */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1176) priv->delsys = delsys;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1177) priv->type = type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1178) priv->std = std;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1179) priv->bw = bw;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1180)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1181) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1182) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1183)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1184) static int r820t_read_gain(struct r820t_priv *priv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1185) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1186) u8 data[4];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1187) int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1188)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1189) rc = r820t_read(priv, 0x00, data, sizeof(data));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1190) if (rc < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1191) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1192)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1193) return ((data[3] & 0x08) << 1) + ((data[3] & 0xf0) >> 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1194) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1195)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1196) #if 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1197) /* FIXME: This routine requires more testing */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1198)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1199) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1200) * measured with a Racal 6103E GSM test set at 928 MHz with -60 dBm
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1201) * input power, for raw results see:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1202) * http://steve-m.de/projects/rtl-sdr/gain_measurement/r820t/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1203) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1204)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1205) static const int r820t_lna_gain_steps[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1206) 0, 9, 13, 40, 38, 13, 31, 22, 26, 31, 26, 14, 19, 5, 35, 13
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1207) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1208)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1209) static const int r820t_mixer_gain_steps[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1210) 0, 5, 10, 10, 19, 9, 10, 25, 17, 10, 8, 16, 13, 6, 3, -8
^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) static int r820t_set_gain_mode(struct r820t_priv *priv,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1214) bool set_manual_gain,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1215) int gain)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1216) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1217) int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1218)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1219) if (set_manual_gain) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1220) int i, total_gain = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1221) uint8_t mix_index = 0, lna_index = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1222) u8 data[4];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1223)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1224) /* LNA auto off */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1225) rc = r820t_write_reg_mask(priv, 0x05, 0x10, 0x10);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1226) if (rc < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1227) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1228)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1229) /* Mixer auto off */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1230) rc = r820t_write_reg_mask(priv, 0x07, 0, 0x10);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1231) if (rc < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1232) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1233)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1234) rc = r820t_read(priv, 0x00, data, sizeof(data));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1235) if (rc < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1236) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1237)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1238) /* set fixed VGA gain for now (16.3 dB) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1239) rc = r820t_write_reg_mask(priv, 0x0c, 0x08, 0x9f);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1240) if (rc < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1241) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1242)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1243) for (i = 0; i < 15; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1244) if (total_gain >= gain)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1245) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1246)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1247) total_gain += r820t_lna_gain_steps[++lna_index];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1248)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1249) if (total_gain >= gain)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1250) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1251)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1252) total_gain += r820t_mixer_gain_steps[++mix_index];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1253) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1254)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1255) /* set LNA gain */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1256) rc = r820t_write_reg_mask(priv, 0x05, lna_index, 0x0f);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1257) if (rc < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1258) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1259)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1260) /* set Mixer gain */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1261) rc = r820t_write_reg_mask(priv, 0x07, mix_index, 0x0f);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1262) if (rc < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1263) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1264) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1265) /* LNA */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1266) rc = r820t_write_reg_mask(priv, 0x05, 0, 0x10);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1267) if (rc < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1268) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1269)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1270) /* Mixer */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1271) rc = r820t_write_reg_mask(priv, 0x07, 0x10, 0x10);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1272) if (rc < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1273) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1274)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1275) /* set fixed VGA gain for now (26.5 dB) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1276) rc = r820t_write_reg_mask(priv, 0x0c, 0x0b, 0x9f);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1277) if (rc < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1278) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1279) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1280)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1281) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1282) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1283) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1284)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1285) static int generic_set_freq(struct dvb_frontend *fe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1286) u32 freq /* in HZ */,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1287) unsigned bw,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1288) enum v4l2_tuner_type type,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1289) v4l2_std_id std, u32 delsys)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1290) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1291) struct r820t_priv *priv = fe->tuner_priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1292) int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1293) u32 lo_freq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1294)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1295) tuner_dbg("should set frequency to %d kHz, bw %d MHz\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1296) freq / 1000, bw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1297)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1298) rc = r820t_set_tv_standard(priv, bw, type, std, delsys);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1299) if (rc < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1300) goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1301)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1302) if ((type == V4L2_TUNER_ANALOG_TV) && (std == V4L2_STD_SECAM_LC))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1303) lo_freq = freq - priv->int_freq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1304) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1305) lo_freq = freq + priv->int_freq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1306)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1307) rc = r820t_set_mux(priv, lo_freq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1308) if (rc < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1309) goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1310)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1311) rc = r820t_set_pll(priv, type, lo_freq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1312) if (rc < 0 || !priv->has_lock)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1313) goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1314)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1315) rc = r820t_sysfreq_sel(priv, freq, type, std, delsys);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1316) if (rc < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1317) goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1318)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1319) tuner_dbg("%s: PLL locked on frequency %d Hz, gain=%d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1320) __func__, freq, r820t_read_gain(priv));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1321)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1322) err:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1323)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1324) if (rc < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1325) tuner_dbg("%s: failed=%d\n", __func__, rc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1326) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1327) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1328)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1329) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1330) * r820t standby logic
^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) static int r820t_standby(struct r820t_priv *priv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1334) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1335) int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1336)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1337) /* If device was not initialized yet, don't need to standby */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1338) if (!priv->init_done)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1339) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1340)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1341) rc = r820t_write_reg(priv, 0x06, 0xb1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1342) if (rc < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1343) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1344) rc = r820t_write_reg(priv, 0x05, 0x03);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1345) if (rc < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1346) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1347) rc = r820t_write_reg(priv, 0x07, 0x3a);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1348) if (rc < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1349) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1350) rc = r820t_write_reg(priv, 0x08, 0x40);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1351) if (rc < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1352) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1353) rc = r820t_write_reg(priv, 0x09, 0xc0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1354) if (rc < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1355) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1356) rc = r820t_write_reg(priv, 0x0a, 0x36);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1357) if (rc < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1358) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1359) rc = r820t_write_reg(priv, 0x0c, 0x35);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1360) if (rc < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1361) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1362) rc = r820t_write_reg(priv, 0x0f, 0x68);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1363) if (rc < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1364) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1365) rc = r820t_write_reg(priv, 0x11, 0x03);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1366) if (rc < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1367) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1368) rc = r820t_write_reg(priv, 0x17, 0xf4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1369) if (rc < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1370) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1371) rc = r820t_write_reg(priv, 0x19, 0x0c);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1372)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1373) /* Force initial calibration */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1374) priv->type = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1375)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1376) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1377) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1378)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1379) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1380) * r820t device init logic
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1381) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1382)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1383) static int r820t_xtal_check(struct r820t_priv *priv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1384) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1385) int rc, i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1386) u8 data[3], val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1387)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1388) /* Initialize the shadow registers */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1389) memcpy(priv->regs, r820t_init_array, sizeof(r820t_init_array));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1390)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1391) /* cap 30pF & Drive Low */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1392) rc = r820t_write_reg_mask(priv, 0x10, 0x0b, 0x0b);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1393) if (rc < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1394) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1395)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1396) /* set pll autotune = 128kHz */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1397) rc = r820t_write_reg_mask(priv, 0x1a, 0x00, 0x0c);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1398) if (rc < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1399) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1400)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1401) /* set manual initial reg = 111111; */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1402) rc = r820t_write_reg_mask(priv, 0x13, 0x7f, 0x7f);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1403) if (rc < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1404) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1405)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1406) /* set auto */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1407) rc = r820t_write_reg_mask(priv, 0x13, 0x00, 0x40);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1408) if (rc < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1409) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1410)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1411) /* Try several xtal capacitor alternatives */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1412) for (i = 0; i < ARRAY_SIZE(r820t_xtal_capacitor); i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1413) rc = r820t_write_reg_mask(priv, 0x10,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1414) r820t_xtal_capacitor[i][0], 0x1b);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1415) if (rc < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1416) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1417)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1418) usleep_range(5000, 6000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1419)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1420) rc = r820t_read(priv, 0x00, data, sizeof(data));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1421) if (rc < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1422) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1423) if (!(data[2] & 0x40))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1424) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1425)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1426) val = data[2] & 0x3f;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1427)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1428) if (priv->cfg->xtal == 16000000 && (val > 29 || val < 23))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1429) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1430)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1431) if (val != 0x3f)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1432) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1433) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1434)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1435) if (i == ARRAY_SIZE(r820t_xtal_capacitor))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1436) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1437)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1438) return r820t_xtal_capacitor[i][1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1439) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1440)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1441) static int r820t_imr_prepare(struct r820t_priv *priv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1442) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1443) int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1444)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1445) /* Initialize the shadow registers */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1446) memcpy(priv->regs, r820t_init_array, sizeof(r820t_init_array));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1447)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1448) /* lna off (air-in off) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1449) rc = r820t_write_reg_mask(priv, 0x05, 0x20, 0x20);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1450) if (rc < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1451) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1452)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1453) /* mixer gain mode = manual */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1454) rc = r820t_write_reg_mask(priv, 0x07, 0, 0x10);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1455) if (rc < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1456) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1457)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1458) /* filter corner = lowest */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1459) rc = r820t_write_reg_mask(priv, 0x0a, 0x0f, 0x0f);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1460) if (rc < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1461) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1462)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1463) /* filter bw=+2cap, hp=5M */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1464) rc = r820t_write_reg_mask(priv, 0x0b, 0x60, 0x6f);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1465) if (rc < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1466) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1467)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1468) /* adc=on, vga code mode, gain = 26.5dB */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1469) rc = r820t_write_reg_mask(priv, 0x0c, 0x0b, 0x9f);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1470) if (rc < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1471) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1472)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1473) /* ring clk = on */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1474) rc = r820t_write_reg_mask(priv, 0x0f, 0, 0x08);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1475) if (rc < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1476) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1477)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1478) /* ring power = on */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1479) rc = r820t_write_reg_mask(priv, 0x18, 0x10, 0x10);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1480) if (rc < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1481) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1482)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1483) /* from ring = ring pll in */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1484) rc = r820t_write_reg_mask(priv, 0x1c, 0x02, 0x02);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1485) if (rc < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1486) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1487)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1488) /* sw_pdect = det3 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1489) rc = r820t_write_reg_mask(priv, 0x1e, 0x80, 0x80);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1490) if (rc < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1491) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1492)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1493) /* Set filt_3dB */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1494) rc = r820t_write_reg_mask(priv, 0x06, 0x20, 0x20);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1495)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1496) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1497) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1498)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1499) static int r820t_multi_read(struct r820t_priv *priv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1500) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1501) int rc, i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1502) u16 sum = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1503) u8 data[2], min = 255, max = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1504)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1505) usleep_range(5000, 6000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1506)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1507) for (i = 0; i < 6; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1508) rc = r820t_read(priv, 0x00, data, sizeof(data));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1509) if (rc < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1510) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1511)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1512) sum += data[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1513)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1514) if (data[1] < min)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1515) min = data[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1516)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1517) if (data[1] > max)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1518) max = data[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1519) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1520) rc = sum - max - min;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1521)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1522) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1523) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1524)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1525) static int r820t_imr_cross(struct r820t_priv *priv,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1526) struct r820t_sect_type iq_point[3],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1527) u8 *x_direct)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1528) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1529) struct r820t_sect_type cross[5]; /* (0,0)(0,Q-1)(0,I-1)(Q-1,0)(I-1,0) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1530) struct r820t_sect_type tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1531) int i, rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1532) u8 reg08, reg09;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1533)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1534) reg08 = r820t_read_cache_reg(priv, 8) & 0xc0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1535) reg09 = r820t_read_cache_reg(priv, 9) & 0xc0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1536)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1537) tmp.gain_x = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1538) tmp.phase_y = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1539) tmp.value = 255;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1540)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1541) for (i = 0; i < 5; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1542) switch (i) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1543) case 0:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1544) cross[i].gain_x = reg08;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1545) cross[i].phase_y = reg09;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1546) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1547) case 1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1548) cross[i].gain_x = reg08; /* 0 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1549) cross[i].phase_y = reg09 + 1; /* Q-1 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1550) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1551) case 2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1552) cross[i].gain_x = reg08; /* 0 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1553) cross[i].phase_y = (reg09 | 0x20) + 1; /* I-1 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1554) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1555) case 3:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1556) cross[i].gain_x = reg08 + 1; /* Q-1 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1557) cross[i].phase_y = reg09;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1558) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1559) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1560) cross[i].gain_x = (reg08 | 0x20) + 1; /* I-1 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1561) cross[i].phase_y = reg09;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1562) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1563)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1564) rc = r820t_write_reg(priv, 0x08, cross[i].gain_x);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1565) if (rc < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1566) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1567)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1568) rc = r820t_write_reg(priv, 0x09, cross[i].phase_y);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1569) if (rc < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1570) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1571)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1572) rc = r820t_multi_read(priv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1573) if (rc < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1574) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1575)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1576) cross[i].value = rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1577)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1578) if (cross[i].value < tmp.value)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1579) tmp = cross[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1580) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1581)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1582) if ((tmp.phase_y & 0x1f) == 1) { /* y-direction */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1583) *x_direct = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1584)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1585) iq_point[0] = cross[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1586) iq_point[1] = cross[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1587) iq_point[2] = cross[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1588) } else { /* (0,0) or x-direction */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1589) *x_direct = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1590)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1591) iq_point[0] = cross[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1592) iq_point[1] = cross[3];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1593) iq_point[2] = cross[4];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1594) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1595) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1596) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1597)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1598) static void r820t_compre_cor(struct r820t_sect_type iq[3])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1599) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1600) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1601)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1602) for (i = 3; i > 0; i--) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1603) if (iq[0].value > iq[i - 1].value)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1604) swap(iq[0], iq[i - 1]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1605) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1606) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1607)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1608) static int r820t_compre_step(struct r820t_priv *priv,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1609) struct r820t_sect_type iq[3], u8 reg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1610) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1611) int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1612) struct r820t_sect_type tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1613)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1614) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1615) * Purpose: if (Gain<9 or Phase<9), Gain+1 or Phase+1 and compare
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1616) * with min value:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1617) * new < min => update to min and continue
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1618) * new > min => Exit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1619) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1620)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1621) /* min value already saved in iq[0] */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1622) tmp.phase_y = iq[0].phase_y;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1623) tmp.gain_x = iq[0].gain_x;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1624)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1625) while (((tmp.gain_x & 0x1f) < IMR_TRIAL) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1626) ((tmp.phase_y & 0x1f) < IMR_TRIAL)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1627) if (reg == 0x08)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1628) tmp.gain_x++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1629) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1630) tmp.phase_y++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1631)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1632) rc = r820t_write_reg(priv, 0x08, tmp.gain_x);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1633) if (rc < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1634) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1635)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1636) rc = r820t_write_reg(priv, 0x09, tmp.phase_y);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1637) if (rc < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1638) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1639)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1640) rc = r820t_multi_read(priv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1641) if (rc < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1642) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1643) tmp.value = rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1644)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1645) if (tmp.value <= iq[0].value) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1646) iq[0].gain_x = tmp.gain_x;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1647) iq[0].phase_y = tmp.phase_y;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1648) iq[0].value = tmp.value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1649) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1650) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1651) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1652)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1653) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1654)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1655) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1656) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1657)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1658) static int r820t_iq_tree(struct r820t_priv *priv,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1659) struct r820t_sect_type iq[3],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1660) u8 fix_val, u8 var_val, u8 fix_reg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1661) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1662) int rc, i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1663) u8 tmp, var_reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1664)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1665) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1666) * record IMC results by input gain/phase location then adjust
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1667) * gain or phase positive 1 step and negative 1 step,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1668) * both record results
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1669) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1670)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1671) if (fix_reg == 0x08)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1672) var_reg = 0x09;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1673) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1674) var_reg = 0x08;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1675)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1676) for (i = 0; i < 3; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1677) rc = r820t_write_reg(priv, fix_reg, fix_val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1678) if (rc < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1679) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1680)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1681) rc = r820t_write_reg(priv, var_reg, var_val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1682) if (rc < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1683) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1684)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1685) rc = r820t_multi_read(priv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1686) if (rc < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1687) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1688) iq[i].value = rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1689)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1690) if (fix_reg == 0x08) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1691) iq[i].gain_x = fix_val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1692) iq[i].phase_y = var_val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1693) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1694) iq[i].phase_y = fix_val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1695) iq[i].gain_x = var_val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1696) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1697)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1698) if (i == 0) { /* try right-side point */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1699) var_val++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1700) } else if (i == 1) { /* try left-side point */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1701) /* if absolute location is 1, change I/Q direction */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1702) if ((var_val & 0x1f) < 0x02) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1703) tmp = 2 - (var_val & 0x1f);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1704)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1705) /* b[5]:I/Q selection. 0:Q-path, 1:I-path */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1706) if (var_val & 0x20) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1707) var_val &= 0xc0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1708) var_val |= tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1709) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1710) var_val |= 0x20 | tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1711) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1712) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1713) var_val -= 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1714) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1715) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1716) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1717)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1718) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1719) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1720)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1721) static int r820t_section(struct r820t_priv *priv,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1722) struct r820t_sect_type *iq_point)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1723) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1724) int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1725) struct r820t_sect_type compare_iq[3], compare_bet[3];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1726)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1727) /* Try X-1 column and save min result to compare_bet[0] */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1728) if (!(iq_point->gain_x & 0x1f))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1729) compare_iq[0].gain_x = ((iq_point->gain_x) & 0xdf) + 1; /* Q-path, Gain=1 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1730) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1731) compare_iq[0].gain_x = iq_point->gain_x - 1; /* left point */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1732) compare_iq[0].phase_y = iq_point->phase_y;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1733)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1734) /* y-direction */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1735) rc = r820t_iq_tree(priv, compare_iq, compare_iq[0].gain_x,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1736) compare_iq[0].phase_y, 0x08);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1737) if (rc < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1738) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1739)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1740) r820t_compre_cor(compare_iq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1741)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1742) compare_bet[0] = compare_iq[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1743)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1744) /* Try X column and save min result to compare_bet[1] */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1745) compare_iq[0].gain_x = iq_point->gain_x;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1746) compare_iq[0].phase_y = iq_point->phase_y;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1747)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1748) rc = r820t_iq_tree(priv, compare_iq, compare_iq[0].gain_x,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1749) compare_iq[0].phase_y, 0x08);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1750) if (rc < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1751) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1752)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1753) r820t_compre_cor(compare_iq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1754)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1755) compare_bet[1] = compare_iq[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1756)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1757) /* Try X+1 column and save min result to compare_bet[2] */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1758) if ((iq_point->gain_x & 0x1f) == 0x00)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1759) compare_iq[0].gain_x = ((iq_point->gain_x) | 0x20) + 1; /* I-path, Gain=1 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1760) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1761) compare_iq[0].gain_x = iq_point->gain_x + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1762) compare_iq[0].phase_y = iq_point->phase_y;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1763)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1764) rc = r820t_iq_tree(priv, compare_iq, compare_iq[0].gain_x,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1765) compare_iq[0].phase_y, 0x08);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1766) if (rc < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1767) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1768)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1769) r820t_compre_cor(compare_iq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1770)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1771) compare_bet[2] = compare_iq[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1772)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1773) r820t_compre_cor(compare_bet);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1774)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1775) *iq_point = compare_bet[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1776)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1777) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1778) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1779)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1780) static int r820t_vga_adjust(struct r820t_priv *priv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1781) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1782) int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1783) u8 vga_count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1784)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1785) /* increase vga power to let image significant */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1786) for (vga_count = 12; vga_count < 16; vga_count++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1787) rc = r820t_write_reg_mask(priv, 0x0c, vga_count, 0x0f);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1788) if (rc < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1789) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1790)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1791) usleep_range(10000, 11000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1792)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1793) rc = r820t_multi_read(priv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1794) if (rc < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1795) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1796)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1797) if (rc > 40 * 4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1798) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1799) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1800)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1801) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1802) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1803)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1804) static int r820t_iq(struct r820t_priv *priv, struct r820t_sect_type *iq_pont)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1805) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1806) struct r820t_sect_type compare_iq[3];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1807) int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1808) u8 x_direction = 0; /* 1:x, 0:y */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1809) u8 dir_reg, other_reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1810)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1811) r820t_vga_adjust(priv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1812)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1813) rc = r820t_imr_cross(priv, compare_iq, &x_direction);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1814) if (rc < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1815) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1816)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1817) if (x_direction == 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1818) dir_reg = 0x08;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1819) other_reg = 0x09;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1820) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1821) dir_reg = 0x09;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1822) other_reg = 0x08;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1823) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1824)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1825) /* compare and find min of 3 points. determine i/q direction */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1826) r820t_compre_cor(compare_iq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1827)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1828) /* increase step to find min value of this direction */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1829) rc = r820t_compre_step(priv, compare_iq, dir_reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1830) if (rc < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1831) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1832)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1833) /* the other direction */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1834) rc = r820t_iq_tree(priv, compare_iq, compare_iq[0].gain_x,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1835) compare_iq[0].phase_y, dir_reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1836) if (rc < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1837) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1838)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1839) /* compare and find min of 3 points. determine i/q direction */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1840) r820t_compre_cor(compare_iq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1841)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1842) /* increase step to find min value on this direction */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1843) rc = r820t_compre_step(priv, compare_iq, other_reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1844) if (rc < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1845) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1846)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1847) /* check 3 points again */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1848) rc = r820t_iq_tree(priv, compare_iq, compare_iq[0].gain_x,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1849) compare_iq[0].phase_y, other_reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1850) if (rc < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1851) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1852)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1853) r820t_compre_cor(compare_iq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1854)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1855) /* section-9 check */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1856) rc = r820t_section(priv, compare_iq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1857)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1858) *iq_pont = compare_iq[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1859)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1860) /* reset gain/phase control setting */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1861) rc = r820t_write_reg_mask(priv, 0x08, 0, 0x3f);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1862) if (rc < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1863) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1864)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1865) rc = r820t_write_reg_mask(priv, 0x09, 0, 0x3f);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1866)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1867) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1868) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1869)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1870) static int r820t_f_imr(struct r820t_priv *priv, struct r820t_sect_type *iq_pont)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1871) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1872) int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1873)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1874) r820t_vga_adjust(priv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1875)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1876) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1877) * search surrounding points from previous point
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1878) * try (x-1), (x), (x+1) columns, and find min IMR result point
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1879) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1880) rc = r820t_section(priv, iq_pont);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1881) if (rc < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1882) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1883)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1884) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1885) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1886)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1887) static int r820t_imr(struct r820t_priv *priv, unsigned imr_mem, bool im_flag)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1888) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1889) struct r820t_sect_type imr_point;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1890) int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1891) u32 ring_vco, ring_freq, ring_ref;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1892) u8 n_ring, n;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1893) int reg18, reg19, reg1f;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1894)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1895) if (priv->cfg->xtal > 24000000)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1896) ring_ref = priv->cfg->xtal / 2000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1897) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1898) ring_ref = priv->cfg->xtal / 1000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1899)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1900) n_ring = 15;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1901) for (n = 0; n < 16; n++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1902) if ((16 + n) * 8 * ring_ref >= 3100000) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1903) n_ring = n;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1904) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1905) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1906) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1907)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1908) reg18 = r820t_read_cache_reg(priv, 0x18);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1909) reg19 = r820t_read_cache_reg(priv, 0x19);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1910) reg1f = r820t_read_cache_reg(priv, 0x1f);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1911)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1912) reg18 &= 0xf0; /* set ring[3:0] */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1913) reg18 |= n_ring;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1914)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1915) ring_vco = (16 + n_ring) * 8 * ring_ref;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1916)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1917) reg18 &= 0xdf; /* clear ring_se23 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1918) reg19 &= 0xfc; /* clear ring_seldiv */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1919) reg1f &= 0xfc; /* clear ring_att */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1920)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1921) switch (imr_mem) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1922) case 0:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1923) ring_freq = ring_vco / 48;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1924) reg18 |= 0x20; /* ring_se23 = 1 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1925) reg19 |= 0x03; /* ring_seldiv = 3 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1926) reg1f |= 0x02; /* ring_att 10 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1927) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1928) case 1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1929) ring_freq = ring_vco / 16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1930) reg18 |= 0x00; /* ring_se23 = 0 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1931) reg19 |= 0x02; /* ring_seldiv = 2 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1932) reg1f |= 0x00; /* pw_ring 00 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1933) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1934) case 2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1935) ring_freq = ring_vco / 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1936) reg18 |= 0x00; /* ring_se23 = 0 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1937) reg19 |= 0x01; /* ring_seldiv = 1 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1938) reg1f |= 0x03; /* pw_ring 11 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1939) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1940) case 3:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1941) ring_freq = ring_vco / 6;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1942) reg18 |= 0x20; /* ring_se23 = 1 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1943) reg19 |= 0x00; /* ring_seldiv = 0 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1944) reg1f |= 0x03; /* pw_ring 11 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1945) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1946) case 4:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1947) ring_freq = ring_vco / 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1948) reg18 |= 0x00; /* ring_se23 = 0 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1949) reg19 |= 0x00; /* ring_seldiv = 0 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1950) reg1f |= 0x01; /* pw_ring 01 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1951) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1952) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1953) ring_freq = ring_vco / 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1954) reg18 |= 0x00; /* ring_se23 = 0 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1955) reg19 |= 0x00; /* ring_seldiv = 0 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1956) reg1f |= 0x01; /* pw_ring 01 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1957) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1958) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1959)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1960)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1961) /* write pw_ring, n_ring, ringdiv2 registers */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1962)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1963) /* n_ring, ring_se23 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1964) rc = r820t_write_reg(priv, 0x18, reg18);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1965) if (rc < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1966) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1967)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1968) /* ring_sediv */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1969) rc = r820t_write_reg(priv, 0x19, reg19);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1970) if (rc < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1971) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1972)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1973) /* pw_ring */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1974) rc = r820t_write_reg(priv, 0x1f, reg1f);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1975) if (rc < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1976) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1977)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1978) /* mux input freq ~ rf_in freq */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1979) rc = r820t_set_mux(priv, (ring_freq - 5300) * 1000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1980) if (rc < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1981) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1982)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1983) rc = r820t_set_pll(priv, V4L2_TUNER_DIGITAL_TV,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1984) (ring_freq - 5300) * 1000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1985) if (!priv->has_lock)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1986) rc = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1987) if (rc < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1988) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1989)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1990) if (im_flag) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1991) rc = r820t_iq(priv, &imr_point);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1992) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1993) imr_point.gain_x = priv->imr_data[3].gain_x;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1994) imr_point.phase_y = priv->imr_data[3].phase_y;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1995) imr_point.value = priv->imr_data[3].value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1996)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1997) rc = r820t_f_imr(priv, &imr_point);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1998) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1999) if (rc < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2000) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2001)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2002) /* save IMR value */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2003) switch (imr_mem) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2004) case 0:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2005) priv->imr_data[0].gain_x = imr_point.gain_x;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2006) priv->imr_data[0].phase_y = imr_point.phase_y;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2007) priv->imr_data[0].value = imr_point.value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2008) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2009) case 1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2010) priv->imr_data[1].gain_x = imr_point.gain_x;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2011) priv->imr_data[1].phase_y = imr_point.phase_y;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2012) priv->imr_data[1].value = imr_point.value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2013) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2014) case 2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2015) priv->imr_data[2].gain_x = imr_point.gain_x;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2016) priv->imr_data[2].phase_y = imr_point.phase_y;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2017) priv->imr_data[2].value = imr_point.value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2018) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2019) case 3:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2020) priv->imr_data[3].gain_x = imr_point.gain_x;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2021) priv->imr_data[3].phase_y = imr_point.phase_y;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2022) priv->imr_data[3].value = imr_point.value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2023) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2024) case 4:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2025) priv->imr_data[4].gain_x = imr_point.gain_x;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2026) priv->imr_data[4].phase_y = imr_point.phase_y;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2027) priv->imr_data[4].value = imr_point.value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2028) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2029) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2030) priv->imr_data[4].gain_x = imr_point.gain_x;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2031) priv->imr_data[4].phase_y = imr_point.phase_y;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2032) priv->imr_data[4].value = imr_point.value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2033) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2034) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2035)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2036) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2037) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2038)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2039) static int r820t_imr_callibrate(struct r820t_priv *priv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2040) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2041) int rc, i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2042) int xtal_cap = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2043)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2044) if (priv->init_done)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2045) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2046)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2047) /* Detect Xtal capacitance */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2048) if ((priv->cfg->rafael_chip == CHIP_R820T) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2049) (priv->cfg->rafael_chip == CHIP_R828S) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2050) (priv->cfg->rafael_chip == CHIP_R820C)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2051) priv->xtal_cap_sel = XTAL_HIGH_CAP_0P;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2052) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2053) /* Initialize registers */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2054) rc = r820t_write(priv, 0x05,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2055) r820t_init_array, sizeof(r820t_init_array));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2056) if (rc < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2057) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2058) for (i = 0; i < 3; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2059) rc = r820t_xtal_check(priv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2060) if (rc < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2061) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2062) if (!i || rc > xtal_cap)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2063) xtal_cap = rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2064) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2065) priv->xtal_cap_sel = xtal_cap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2066) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2067)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2068) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2069) * Disables IMR calibration. That emulates the same behaviour
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2070) * as what is done by rtl-sdr userspace library. Useful for testing
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2071) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2072) if (no_imr_cal) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2073) priv->init_done = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2074)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2075) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2076) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2077)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2078) /* Initialize registers */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2079) rc = r820t_write(priv, 0x05,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2080) r820t_init_array, sizeof(r820t_init_array));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2081) if (rc < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2082) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2083)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2084) rc = r820t_imr_prepare(priv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2085) if (rc < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2086) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2087)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2088) rc = r820t_imr(priv, 3, true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2089) if (rc < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2090) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2091) rc = r820t_imr(priv, 1, false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2092) if (rc < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2093) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2094) rc = r820t_imr(priv, 0, false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2095) if (rc < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2096) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2097) rc = r820t_imr(priv, 2, false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2098) if (rc < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2099) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2100) rc = r820t_imr(priv, 4, false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2101) if (rc < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2102) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2103)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2104) priv->init_done = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2105) priv->imr_done = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2106)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2107) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2108) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2109)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2110) #if 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2111) /* Not used, for now */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2112) static int r820t_gpio(struct r820t_priv *priv, bool enable)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2113) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2114) return r820t_write_reg_mask(priv, 0x0f, enable ? 1 : 0, 0x01);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2115) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2116) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2117)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2118) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2119) * r820t frontend operations and tuner attach code
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2120) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2121) * All driver locks and i2c control are only in this part of the code
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2122) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2123)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2124) static int r820t_init(struct dvb_frontend *fe)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2125) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2126) struct r820t_priv *priv = fe->tuner_priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2127) int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2128)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2129) tuner_dbg("%s:\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2130)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2131) mutex_lock(&priv->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2132) if (fe->ops.i2c_gate_ctrl)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2133) fe->ops.i2c_gate_ctrl(fe, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2134)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2135) rc = r820t_imr_callibrate(priv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2136) if (rc < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2137) goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2138)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2139) /* Initialize registers */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2140) rc = r820t_write(priv, 0x05,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2141) r820t_init_array, sizeof(r820t_init_array));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2142)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2143) err:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2144) if (fe->ops.i2c_gate_ctrl)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2145) fe->ops.i2c_gate_ctrl(fe, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2146) mutex_unlock(&priv->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2147)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2148) if (rc < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2149) tuner_dbg("%s: failed=%d\n", __func__, rc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2150) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2151) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2152)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2153) static int r820t_sleep(struct dvb_frontend *fe)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2154) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2155) struct r820t_priv *priv = fe->tuner_priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2156) int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2157)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2158) tuner_dbg("%s:\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2159)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2160) mutex_lock(&priv->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2161) if (fe->ops.i2c_gate_ctrl)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2162) fe->ops.i2c_gate_ctrl(fe, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2163)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2164) rc = r820t_standby(priv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2165)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2166) if (fe->ops.i2c_gate_ctrl)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2167) fe->ops.i2c_gate_ctrl(fe, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2168) mutex_unlock(&priv->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2169)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2170) tuner_dbg("%s: failed=%d\n", __func__, rc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2171) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2172) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2173)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2174) static int r820t_set_analog_freq(struct dvb_frontend *fe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2175) struct analog_parameters *p)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2176) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2177) struct r820t_priv *priv = fe->tuner_priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2178) unsigned bw;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2179) int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2180)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2181) tuner_dbg("%s called\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2182)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2183) /* if std is not defined, choose one */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2184) if (!p->std)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2185) p->std = V4L2_STD_MN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2186)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2187) if ((p->std == V4L2_STD_PAL_M) || (p->std == V4L2_STD_NTSC))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2188) bw = 6;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2189) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2190) bw = 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2191)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2192) mutex_lock(&priv->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2193) if (fe->ops.i2c_gate_ctrl)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2194) fe->ops.i2c_gate_ctrl(fe, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2195)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2196) rc = generic_set_freq(fe, 62500l * p->frequency, bw,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2197) V4L2_TUNER_ANALOG_TV, p->std, SYS_UNDEFINED);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2198)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2199) if (fe->ops.i2c_gate_ctrl)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2200) fe->ops.i2c_gate_ctrl(fe, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2201) mutex_unlock(&priv->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2202)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2203) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2204) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2205)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2206) static int r820t_set_params(struct dvb_frontend *fe)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2207) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2208) struct r820t_priv *priv = fe->tuner_priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2209) struct dtv_frontend_properties *c = &fe->dtv_property_cache;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2210) int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2211) unsigned bw;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2212)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2213) tuner_dbg("%s: delivery_system=%d frequency=%d bandwidth_hz=%d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2214) __func__, c->delivery_system, c->frequency, c->bandwidth_hz);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2215)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2216) mutex_lock(&priv->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2217) if (fe->ops.i2c_gate_ctrl)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2218) fe->ops.i2c_gate_ctrl(fe, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2219)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2220) bw = (c->bandwidth_hz + 500000) / 1000000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2221) if (!bw)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2222) bw = 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2223)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2224) rc = generic_set_freq(fe, c->frequency, bw,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2225) V4L2_TUNER_DIGITAL_TV, 0, c->delivery_system);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2226)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2227) if (fe->ops.i2c_gate_ctrl)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2228) fe->ops.i2c_gate_ctrl(fe, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2229) mutex_unlock(&priv->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2230)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2231) if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2232) tuner_dbg("%s: failed=%d\n", __func__, rc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2233) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2234) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2235)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2236) static int r820t_signal(struct dvb_frontend *fe, u16 *strength)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2237) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2238) struct r820t_priv *priv = fe->tuner_priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2239) int rc = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2240)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2241) mutex_lock(&priv->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2242) if (fe->ops.i2c_gate_ctrl)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2243) fe->ops.i2c_gate_ctrl(fe, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2244)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2245) if (priv->has_lock) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2246) rc = r820t_read_gain(priv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2247) if (rc < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2248) goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2249)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2250) /* A higher gain at LNA means a lower signal strength */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2251) *strength = (45 - rc) << 4 | 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2252) if (*strength == 0xff)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2253) *strength = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2254) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2255) *strength = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2256) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2257)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2258) err:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2259) if (fe->ops.i2c_gate_ctrl)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2260) fe->ops.i2c_gate_ctrl(fe, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2261) mutex_unlock(&priv->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2262)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2263) tuner_dbg("%s: %s, gain=%d strength=%d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2264) __func__,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2265) priv->has_lock ? "PLL locked" : "no signal",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2266) rc, *strength);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2267)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2268) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2269) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2270)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2271) static int r820t_get_if_frequency(struct dvb_frontend *fe, u32 *frequency)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2272) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2273) struct r820t_priv *priv = fe->tuner_priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2274)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2275) tuner_dbg("%s:\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2276)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2277) *frequency = priv->int_freq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2278)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2279) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2280) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2281)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2282) static void r820t_release(struct dvb_frontend *fe)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2283) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2284) struct r820t_priv *priv = fe->tuner_priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2285)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2286) tuner_dbg("%s:\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2287)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2288) mutex_lock(&r820t_list_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2289)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2290) if (priv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2291) hybrid_tuner_release_state(priv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2292)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2293) mutex_unlock(&r820t_list_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2294)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2295) fe->tuner_priv = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2296) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2297)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2298) static const struct dvb_tuner_ops r820t_tuner_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2299) .info = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2300) .name = "Rafael Micro R820T",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2301) .frequency_min_hz = 42 * MHz,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2302) .frequency_max_hz = 1002 * MHz,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2303) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2304) .init = r820t_init,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2305) .release = r820t_release,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2306) .sleep = r820t_sleep,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2307) .set_params = r820t_set_params,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2308) .set_analog_params = r820t_set_analog_freq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2309) .get_if_frequency = r820t_get_if_frequency,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2310) .get_rf_strength = r820t_signal,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2311) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2312)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2313) struct dvb_frontend *r820t_attach(struct dvb_frontend *fe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2314) struct i2c_adapter *i2c,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2315) const struct r820t_config *cfg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2316) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2317) struct r820t_priv *priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2318) int rc = -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2319) u8 data[5];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2320) int instance;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2321)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2322) mutex_lock(&r820t_list_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2323)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2324) instance = hybrid_tuner_request_state(struct r820t_priv, priv,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2325) hybrid_tuner_instance_list,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2326) i2c, cfg->i2c_addr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2327) "r820t");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2328) switch (instance) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2329) case 0:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2330) /* memory allocation failure */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2331) goto err_no_gate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2332) case 1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2333) /* new tuner instance */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2334) priv->cfg = cfg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2335)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2336) mutex_init(&priv->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2337)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2338) fe->tuner_priv = priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2339) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2340) case 2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2341) /* existing tuner instance */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2342) fe->tuner_priv = priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2343) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2344) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2345)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2346) if (fe->ops.i2c_gate_ctrl)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2347) fe->ops.i2c_gate_ctrl(fe, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2348)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2349) /* check if the tuner is there */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2350) rc = r820t_read(priv, 0x00, data, sizeof(data));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2351) if (rc < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2352) goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2353)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2354) rc = r820t_sleep(fe);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2355) if (rc < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2356) goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2357)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2358) tuner_info("Rafael Micro r820t successfully identified\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2359)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2360) if (fe->ops.i2c_gate_ctrl)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2361) fe->ops.i2c_gate_ctrl(fe, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2362)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2363) mutex_unlock(&r820t_list_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2364)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2365) memcpy(&fe->ops.tuner_ops, &r820t_tuner_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2366) sizeof(struct dvb_tuner_ops));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2367)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2368) return fe;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2369) err:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2370) if (fe->ops.i2c_gate_ctrl)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2371) fe->ops.i2c_gate_ctrl(fe, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2372)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2373) err_no_gate:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2374) mutex_unlock(&r820t_list_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2375)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2376) pr_info("%s: failed=%d\n", __func__, rc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2377) r820t_release(fe);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2378) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2379) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2380) EXPORT_SYMBOL_GPL(r820t_attach);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2381)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2382) MODULE_DESCRIPTION("Rafael Micro r820t silicon tuner driver");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2383) MODULE_AUTHOR("Mauro Carvalho Chehab");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2384) MODULE_LICENSE("GPL v2");