^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-or-later
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * Support for Legend Silicon GB20600 (a.k.a DMB-TH) demodulator
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) * LGS8913, LGS8GL5, LGS8G75
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * experimental support LGS8G42, LGS8G52
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * Copyright (C) 2007-2009 David T.L. Wong <davidtlwong@gmail.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * Copyright (C) 2008 Sirius International (Hong Kong) Limited
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) * Timothy Lee <timothy.lee@siriushk.com> (for initial work on LGS8GL5)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <asm/div64.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <linux/firmware.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <media/dvb_frontend.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include "lgs8gxx.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include "lgs8gxx_priv.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #define dprintk(args...) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) do { \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) if (debug) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) printk(KERN_DEBUG "lgs8gxx: " args); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) } while (0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) static int debug;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) static int fake_signal_str = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) #define LGS8GXX_FIRMWARE "lgs8g75.fw"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) module_param(debug, int, 0644);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off).");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) module_param(fake_signal_str, int, 0644);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) MODULE_PARM_DESC(fake_signal_str, "fake signal strength for LGS8913."
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) "Signal strength calculation is slow.(default:on).");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) /* LGS8GXX internal helper functions */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) static int lgs8gxx_write_reg(struct lgs8gxx_state *priv, u8 reg, u8 data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) u8 buf[] = { reg, data };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) struct i2c_msg msg = { .flags = 0, .buf = buf, .len = 2 };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) msg.addr = priv->config->demod_address;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) if (priv->config->prod != LGS8GXX_PROD_LGS8G75 && reg >= 0xC0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) msg.addr += 0x02;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) if (debug >= 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) dprintk("%s: reg=0x%02X, data=0x%02X\n", __func__, reg, data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) ret = i2c_transfer(priv->i2c, &msg, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) if (ret != 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) dprintk("%s: error reg=0x%x, data=0x%x, ret=%i\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) __func__, reg, data, ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) return (ret != 1) ? -1 : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) static int lgs8gxx_read_reg(struct lgs8gxx_state *priv, u8 reg, u8 *p_data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) u8 dev_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) u8 b0[] = { reg };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) u8 b1[] = { 0 };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) struct i2c_msg msg[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) { .flags = 0, .buf = b0, .len = 1 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) { .flags = I2C_M_RD, .buf = b1, .len = 1 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) dev_addr = priv->config->demod_address;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) if (priv->config->prod != LGS8GXX_PROD_LGS8G75 && reg >= 0xC0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) dev_addr += 0x02;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) msg[1].addr = msg[0].addr = dev_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) ret = i2c_transfer(priv->i2c, msg, 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) if (ret != 2) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) dprintk("%s: error reg=0x%x, ret=%i\n", __func__, reg, ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) *p_data = b1[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) if (debug >= 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) dprintk("%s: reg=0x%02X, data=0x%02X\n", __func__, reg, b1[0]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) static int lgs8gxx_soft_reset(struct lgs8gxx_state *priv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) lgs8gxx_write_reg(priv, 0x02, 0x00);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) msleep(1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) lgs8gxx_write_reg(priv, 0x02, 0x01);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) msleep(100);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) static int wait_reg_mask(struct lgs8gxx_state *priv, u8 reg, u8 mask,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) u8 val, u8 delay, u8 tries)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) u8 t;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) for (i = 0; i < tries; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) lgs8gxx_read_reg(priv, reg, &t);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) if ((t & mask) == val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) msleep(delay);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) static int lgs8gxx_set_ad_mode(struct lgs8gxx_state *priv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) const struct lgs8gxx_config *config = priv->config;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) u8 if_conf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) if_conf = 0x10; /* AGC output on, RF_AGC output off; */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) if_conf |=
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) ((config->ext_adc) ? 0x80 : 0x00) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) ((config->if_neg_center) ? 0x04 : 0x00) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) ((config->if_freq == 0) ? 0x08 : 0x00) | /* Baseband */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) ((config->adc_signed) ? 0x02 : 0x00) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) ((config->if_neg_edge) ? 0x01 : 0x00);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) if (config->ext_adc &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) (config->prod == LGS8GXX_PROD_LGS8G52)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) lgs8gxx_write_reg(priv, 0xBA, 0x40);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) lgs8gxx_write_reg(priv, 0x07, if_conf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) static int lgs8gxx_set_if_freq(struct lgs8gxx_state *priv, u32 freq /*in kHz*/)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) u64 val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) u32 v32;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) u32 if_clk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) if_clk = priv->config->if_clk_freq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) val = freq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) if (freq != 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) val <<= 32;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) if (if_clk != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) do_div(val, if_clk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) v32 = val & 0xFFFFFFFF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) dprintk("Set IF Freq to %dkHz\n", freq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) v32 = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) dprintk("Set IF Freq to baseband\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) dprintk("AFC_INIT_FREQ = 0x%08X\n", v32);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) if (priv->config->prod == LGS8GXX_PROD_LGS8G75) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) lgs8gxx_write_reg(priv, 0x08, 0xFF & (v32));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) lgs8gxx_write_reg(priv, 0x09, 0xFF & (v32 >> 8));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) lgs8gxx_write_reg(priv, 0x0A, 0xFF & (v32 >> 16));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) lgs8gxx_write_reg(priv, 0x0B, 0xFF & (v32 >> 24));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) lgs8gxx_write_reg(priv, 0x09, 0xFF & (v32));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) lgs8gxx_write_reg(priv, 0x0A, 0xFF & (v32 >> 8));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) lgs8gxx_write_reg(priv, 0x0B, 0xFF & (v32 >> 16));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) lgs8gxx_write_reg(priv, 0x0C, 0xFF & (v32 >> 24));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) static int lgs8gxx_get_afc_phase(struct lgs8gxx_state *priv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) u64 val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) u32 v32 = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) u8 reg_addr, t;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) if (priv->config->prod == LGS8GXX_PROD_LGS8G75)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) reg_addr = 0x23;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) reg_addr = 0x48;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) for (i = 0; i < 4; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) lgs8gxx_read_reg(priv, reg_addr, &t);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) v32 <<= 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) v32 |= t;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) reg_addr--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) val = v32;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) val *= priv->config->if_clk_freq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) val >>= 32;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) dprintk("AFC = %u kHz\n", (u32)val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) static int lgs8gxx_set_mode_auto(struct lgs8gxx_state *priv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) u8 t;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) u8 prod = priv->config->prod;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) if (prod == LGS8GXX_PROD_LGS8913)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) lgs8gxx_write_reg(priv, 0xC6, 0x01);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) if (prod == LGS8GXX_PROD_LGS8G75) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) lgs8gxx_read_reg(priv, 0x0C, &t);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) t &= (~0x04);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) lgs8gxx_write_reg(priv, 0x0C, t | 0x80);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) lgs8gxx_write_reg(priv, 0x39, 0x00);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) lgs8gxx_write_reg(priv, 0x3D, 0x04);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) } else if (prod == LGS8GXX_PROD_LGS8913 ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) prod == LGS8GXX_PROD_LGS8GL5 ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) prod == LGS8GXX_PROD_LGS8G42 ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) prod == LGS8GXX_PROD_LGS8G52 ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) prod == LGS8GXX_PROD_LGS8G54) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) lgs8gxx_read_reg(priv, 0x7E, &t);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) lgs8gxx_write_reg(priv, 0x7E, t | 0x01);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) /* clear FEC self reset */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) lgs8gxx_read_reg(priv, 0xC5, &t);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) lgs8gxx_write_reg(priv, 0xC5, t & 0xE0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) if (prod == LGS8GXX_PROD_LGS8913) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) /* FEC auto detect */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) lgs8gxx_write_reg(priv, 0xC1, 0x03);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) lgs8gxx_read_reg(priv, 0x7C, &t);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) t = (t & 0x8C) | 0x03;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) lgs8gxx_write_reg(priv, 0x7C, t);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) /* BER test mode */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) lgs8gxx_read_reg(priv, 0xC3, &t);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) t = (t & 0xEF) | 0x10;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) lgs8gxx_write_reg(priv, 0xC3, t);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) if (priv->config->prod == LGS8GXX_PROD_LGS8G52)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) lgs8gxx_write_reg(priv, 0xD9, 0x40);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) static int lgs8gxx_set_mode_manual(struct lgs8gxx_state *priv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) u8 t;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) if (priv->config->prod == LGS8GXX_PROD_LGS8G75) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) u8 t2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) lgs8gxx_read_reg(priv, 0x0C, &t);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) t &= (~0x80);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) lgs8gxx_write_reg(priv, 0x0C, t);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) lgs8gxx_read_reg(priv, 0x0C, &t);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) lgs8gxx_read_reg(priv, 0x19, &t2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) if (((t&0x03) == 0x01) && (t2&0x01)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) lgs8gxx_write_reg(priv, 0x6E, 0x05);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) lgs8gxx_write_reg(priv, 0x39, 0x02);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) lgs8gxx_write_reg(priv, 0x39, 0x03);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) lgs8gxx_write_reg(priv, 0x3D, 0x05);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) lgs8gxx_write_reg(priv, 0x3E, 0x28);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) lgs8gxx_write_reg(priv, 0x53, 0x80);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) lgs8gxx_write_reg(priv, 0x6E, 0x3F);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) lgs8gxx_write_reg(priv, 0x39, 0x00);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) lgs8gxx_write_reg(priv, 0x3D, 0x04);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) lgs8gxx_soft_reset(priv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) /* turn off auto-detect; manual settings */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) lgs8gxx_write_reg(priv, 0x7E, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) if (priv->config->prod == LGS8GXX_PROD_LGS8913)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) lgs8gxx_write_reg(priv, 0xC1, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) lgs8gxx_read_reg(priv, 0xC5, &t);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) t = (t & 0xE0) | 0x06;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) lgs8gxx_write_reg(priv, 0xC5, t);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) lgs8gxx_soft_reset(priv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) static int lgs8gxx_is_locked(struct lgs8gxx_state *priv, u8 *locked)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) u8 t;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) if (priv->config->prod == LGS8GXX_PROD_LGS8G75)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) ret = lgs8gxx_read_reg(priv, 0x13, &t);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) ret = lgs8gxx_read_reg(priv, 0x4B, &t);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) if (ret != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) if (priv->config->prod == LGS8GXX_PROD_LGS8G75)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) *locked = ((t & 0x80) == 0x80) ? 1 : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) *locked = ((t & 0xC0) == 0xC0) ? 1 : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) /* Wait for Code Acquisition Lock */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) static int lgs8gxx_wait_ca_lock(struct lgs8gxx_state *priv, u8 *locked)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) u8 reg, mask, val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) if (priv->config->prod == LGS8GXX_PROD_LGS8G75) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) reg = 0x13;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) mask = 0x80;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) val = 0x80;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) reg = 0x4B;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) mask = 0xC0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) val = 0xC0;
^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) ret = wait_reg_mask(priv, reg, mask, val, 50, 40);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) *locked = (ret == 0) ? 1 : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) static int lgs8gxx_is_autodetect_finished(struct lgs8gxx_state *priv,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) u8 *finished)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) u8 reg, mask, val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) if (priv->config->prod == LGS8GXX_PROD_LGS8G75) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) reg = 0x1f;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) mask = 0xC0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) val = 0x80;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) reg = 0xA4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) mask = 0x03;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) val = 0x01;
^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) ret = wait_reg_mask(priv, reg, mask, val, 10, 20);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) *finished = (ret == 0) ? 1 : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) static int lgs8gxx_autolock_gi(struct lgs8gxx_state *priv, u8 gi, u8 cpn,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) u8 *locked)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) int err = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) u8 ad_fini = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) u8 t1, t2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) if (gi == GI_945)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) dprintk("try GI 945\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) else if (gi == GI_595)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) dprintk("try GI 595\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) else if (gi == GI_420)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) dprintk("try GI 420\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) if (priv->config->prod == LGS8GXX_PROD_LGS8G75) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) lgs8gxx_read_reg(priv, 0x0C, &t1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) lgs8gxx_read_reg(priv, 0x18, &t2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) t1 &= ~(GI_MASK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) t1 |= gi;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) t2 &= 0xFE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) t2 |= cpn ? 0x01 : 0x00;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) lgs8gxx_write_reg(priv, 0x0C, t1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) lgs8gxx_write_reg(priv, 0x18, t2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) lgs8gxx_write_reg(priv, 0x04, gi);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) lgs8gxx_soft_reset(priv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) err = lgs8gxx_wait_ca_lock(priv, locked);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) if (err || !(*locked))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) err = lgs8gxx_is_autodetect_finished(priv, &ad_fini);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) if (err != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) if (ad_fini) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) dprintk("auto detect finished\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) *locked = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) static int lgs8gxx_auto_detect(struct lgs8gxx_state *priv,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) u8 *detected_param, u8 *gi)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) int i, j;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) int err = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) u8 locked = 0, tmp_gi;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) dprintk("%s\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) lgs8gxx_set_mode_auto(priv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) if (priv->config->prod == LGS8GXX_PROD_LGS8G75) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) lgs8gxx_write_reg(priv, 0x67, 0xAA);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) lgs8gxx_write_reg(priv, 0x6E, 0x3F);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) /* Guard Interval */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) lgs8gxx_write_reg(priv, 0x03, 00);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) for (i = 0; i < 2; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) for (j = 0; j < 2; j++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) tmp_gi = GI_945;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) err = lgs8gxx_autolock_gi(priv, GI_945, j, &locked);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) if (locked)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) goto locked;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) for (j = 0; j < 2; j++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) tmp_gi = GI_420;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) err = lgs8gxx_autolock_gi(priv, GI_420, j, &locked);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) if (locked)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) goto locked;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) tmp_gi = GI_595;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) err = lgs8gxx_autolock_gi(priv, GI_595, 1, &locked);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) if (locked)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) goto locked;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) locked:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) if ((err == 0) && (locked == 1)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) u8 t;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) if (priv->config->prod != LGS8GXX_PROD_LGS8G75) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) lgs8gxx_read_reg(priv, 0xA2, &t);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) *detected_param = t;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) lgs8gxx_read_reg(priv, 0x1F, &t);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) *detected_param = t & 0x3F;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) if (tmp_gi == GI_945)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) dprintk("GI 945 locked\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) else if (tmp_gi == GI_595)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) dprintk("GI 595 locked\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) else if (tmp_gi == GI_420)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) dprintk("GI 420 locked\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) *gi = tmp_gi;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) if (!locked)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) err = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) static void lgs8gxx_auto_lock(struct lgs8gxx_state *priv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) s8 err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) u8 gi = 0x2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) u8 detected_param = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) err = lgs8gxx_auto_detect(priv, &detected_param, &gi);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) if (err != 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) dprintk("lgs8gxx_auto_detect failed\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) dprintk("detected param = 0x%02X\n", detected_param);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) /* Apply detected parameters */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) if (priv->config->prod == LGS8GXX_PROD_LGS8913) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) u8 inter_leave_len = detected_param & TIM_MASK ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) /* Fix 8913 time interleaver detection bug */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) inter_leave_len = (inter_leave_len == TIM_MIDDLE) ? 0x60 : 0x40;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) detected_param &= CF_MASK | SC_MASK | LGS_FEC_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) detected_param |= inter_leave_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) if (priv->config->prod == LGS8GXX_PROD_LGS8G75) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) u8 t;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) lgs8gxx_read_reg(priv, 0x19, &t);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) t &= 0x81;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) t |= detected_param << 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) lgs8gxx_write_reg(priv, 0x19, t);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) lgs8gxx_write_reg(priv, 0x7D, detected_param);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) if (priv->config->prod == LGS8GXX_PROD_LGS8913)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) lgs8gxx_write_reg(priv, 0xC0, detected_param);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) /* lgs8gxx_soft_reset(priv); */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) /* Enter manual mode */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) lgs8gxx_set_mode_manual(priv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) switch (gi) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) case GI_945:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) priv->curr_gi = 945; break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) case GI_595:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) priv->curr_gi = 595; break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) case GI_420:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) priv->curr_gi = 420; break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) priv->curr_gi = 945; break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) static int lgs8gxx_set_mpeg_mode(struct lgs8gxx_state *priv,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) u8 serial, u8 clk_pol, u8 clk_gated)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) u8 t, reg_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) reg_addr = (priv->config->prod == LGS8GXX_PROD_LGS8G75) ? 0x30 : 0xC2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) ret = lgs8gxx_read_reg(priv, reg_addr, &t);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) if (ret != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) t &= 0xF8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) t |= serial ? TS_SERIAL : TS_PARALLEL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) t |= clk_pol ? TS_CLK_INVERTED : TS_CLK_NORMAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) t |= clk_gated ? TS_CLK_GATED : TS_CLK_FREERUN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) ret = lgs8gxx_write_reg(priv, reg_addr, t);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) if (ret != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) /* A/D input peak-to-peak voltage range */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) static int lgs8g75_set_adc_vpp(struct lgs8gxx_state *priv,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) u8 sel)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) u8 r26 = 0x73, r27 = 0x90;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) if (priv->config->prod != LGS8GXX_PROD_LGS8G75)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) r26 |= (sel & 0x01) << 7;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) r27 |= (sel & 0x02) >> 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) lgs8gxx_write_reg(priv, 0x26, r26);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) lgs8gxx_write_reg(priv, 0x27, r27);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) /* LGS8913 demod frontend functions */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) static int lgs8913_init(struct lgs8gxx_state *priv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) u8 t;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) /* LGS8913 specific */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) lgs8gxx_write_reg(priv, 0xc1, 0x3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) lgs8gxx_read_reg(priv, 0x7c, &t);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) lgs8gxx_write_reg(priv, 0x7c, (t&0x8c) | 0x3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) /* LGS8913 specific */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) lgs8gxx_read_reg(priv, 0xc3, &t);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) lgs8gxx_write_reg(priv, 0xc3, t&0x10);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) static int lgs8g75_init_data(struct lgs8gxx_state *priv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) const struct firmware *fw;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) rc = request_firmware(&fw, LGS8GXX_FIRMWARE, &priv->i2c->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) lgs8gxx_write_reg(priv, 0xC6, 0x40);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) lgs8gxx_write_reg(priv, 0x3D, 0x04);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) lgs8gxx_write_reg(priv, 0x39, 0x00);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) lgs8gxx_write_reg(priv, 0x3A, 0x00);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) lgs8gxx_write_reg(priv, 0x38, 0x00);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) lgs8gxx_write_reg(priv, 0x3B, 0x00);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) lgs8gxx_write_reg(priv, 0x38, 0x00);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) for (i = 0; i < fw->size; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) lgs8gxx_write_reg(priv, 0x38, 0x00);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) lgs8gxx_write_reg(priv, 0x3A, (u8)(i&0xff));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) lgs8gxx_write_reg(priv, 0x3B, (u8)(i>>8));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) lgs8gxx_write_reg(priv, 0x3C, fw->data[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) lgs8gxx_write_reg(priv, 0x38, 0x00);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) release_firmware(fw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) static int lgs8gxx_init(struct dvb_frontend *fe)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) struct lgs8gxx_state *priv =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) (struct lgs8gxx_state *)fe->demodulator_priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) const struct lgs8gxx_config *config = priv->config;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) u8 data = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) s8 err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) dprintk("%s\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) lgs8gxx_read_reg(priv, 0, &data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) dprintk("reg 0 = 0x%02X\n", data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) if (config->prod == LGS8GXX_PROD_LGS8G75)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) lgs8g75_set_adc_vpp(priv, config->adc_vpp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) /* Setup MPEG output format */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) err = lgs8gxx_set_mpeg_mode(priv, config->serial_ts,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) config->ts_clk_pol,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) config->ts_clk_gated);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) if (err != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) if (config->prod == LGS8GXX_PROD_LGS8913)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) lgs8913_init(priv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) lgs8gxx_set_if_freq(priv, priv->config->if_freq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) lgs8gxx_set_ad_mode(priv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) static void lgs8gxx_release(struct dvb_frontend *fe)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) struct lgs8gxx_state *state = fe->demodulator_priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) dprintk("%s\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) kfree(state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) static int lgs8gxx_write(struct dvb_frontend *fe, const u8 buf[], int len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) struct lgs8gxx_state *priv = fe->demodulator_priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) if (len != 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) return lgs8gxx_write_reg(priv, buf[0], buf[1]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) static int lgs8gxx_set_fe(struct dvb_frontend *fe)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) struct dtv_frontend_properties *fe_params = &fe->dtv_property_cache;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) struct lgs8gxx_state *priv = fe->demodulator_priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) dprintk("%s\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) /* set frequency */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) if (fe->ops.tuner_ops.set_params) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) fe->ops.tuner_ops.set_params(fe);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) if (fe->ops.i2c_gate_ctrl)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) fe->ops.i2c_gate_ctrl(fe, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) /* start auto lock */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) lgs8gxx_auto_lock(priv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) msleep(10);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) /* TODO: get real readings from device */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) /* bandwidth */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) fe_params->bandwidth_hz = 8000000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) fe_params->code_rate_HP = FEC_AUTO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) fe_params->code_rate_LP = FEC_AUTO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) fe_params->modulation = QAM_AUTO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) /* transmission mode */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) fe_params->transmission_mode = TRANSMISSION_MODE_AUTO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) /* guard interval */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) fe_params->guard_interval = GUARD_INTERVAL_AUTO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) /* hierarchy */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) fe_params->hierarchy = HIERARCHY_NONE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) static
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) int lgs8gxx_get_tune_settings(struct dvb_frontend *fe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) struct dvb_frontend_tune_settings *fesettings)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) /* FIXME: copy from tda1004x.c */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) fesettings->min_delay_ms = 800;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) fesettings->step_size = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) fesettings->max_drift = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711) static int lgs8gxx_read_status(struct dvb_frontend *fe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) enum fe_status *fe_status)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714) struct lgs8gxx_state *priv = fe->demodulator_priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) s8 ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) u8 t, locked = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) dprintk("%s\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719) *fe_status = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) lgs8gxx_get_afc_phase(priv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) lgs8gxx_is_locked(priv, &locked);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723) if (priv->config->prod == LGS8GXX_PROD_LGS8G75) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) if (locked)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) *fe_status |= FE_HAS_SIGNAL | FE_HAS_CARRIER |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726) FE_HAS_VITERBI | FE_HAS_SYNC | FE_HAS_LOCK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730) ret = lgs8gxx_read_reg(priv, 0x4B, &t);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) if (ret != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) dprintk("Reg 0x4B: 0x%02X\n", t);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736) *fe_status = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) if (priv->config->prod == LGS8GXX_PROD_LGS8913) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738) if ((t & 0x40) == 0x40)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739) *fe_status |= FE_HAS_SIGNAL | FE_HAS_CARRIER;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740) if ((t & 0x80) == 0x80)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741) *fe_status |= FE_HAS_VITERBI | FE_HAS_SYNC |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742) FE_HAS_LOCK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744) if ((t & 0x80) == 0x80)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) *fe_status |= FE_HAS_SIGNAL | FE_HAS_CARRIER |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746) FE_HAS_VITERBI | FE_HAS_SYNC | FE_HAS_LOCK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) /* success */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) dprintk("%s: fe_status=0x%x\n", __func__, *fe_status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754) static int lgs8gxx_read_signal_agc(struct lgs8gxx_state *priv, u16 *signal)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756) u16 v;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757) u8 agc_lvl[2], cat;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759) dprintk("%s()\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760) lgs8gxx_read_reg(priv, 0x3F, &agc_lvl[0]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761) lgs8gxx_read_reg(priv, 0x3E, &agc_lvl[1]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763) v = agc_lvl[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764) v <<= 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765) v |= agc_lvl[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767) dprintk("agc_lvl: 0x%04X\n", v);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769) if (v < 0x100)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770) cat = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771) else if (v < 0x190)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772) cat = 5;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773) else if (v < 0x2A8)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774) cat = 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775) else if (v < 0x381)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776) cat = 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777) else if (v < 0x400)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778) cat = 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779) else if (v == 0x400)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780) cat = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782) cat = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784) *signal = cat * 65535 / 5;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789) static int lgs8913_read_signal_strength(struct lgs8gxx_state *priv, u16 *signal)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791) u8 t; s8 ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792) s16 max_strength = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793) u8 str;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794) u16 i, gi = priv->curr_gi;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796) dprintk("%s\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798) ret = lgs8gxx_read_reg(priv, 0x4B, &t);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799) if (ret != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802) if (fake_signal_str) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803) if ((t & 0xC0) == 0xC0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804) dprintk("Fake signal strength\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805) *signal = 0x7FFF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807) *signal = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811) dprintk("gi = %d\n", gi);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812) for (i = 0; i < gi; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814) if ((i & 0xFF) == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815) lgs8gxx_write_reg(priv, 0x84, 0x03 & (i >> 8));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816) lgs8gxx_write_reg(priv, 0x83, i & 0xFF);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818) lgs8gxx_read_reg(priv, 0x94, &str);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819) if (max_strength < str)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820) max_strength = str;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823) *signal = max_strength;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824) dprintk("%s: signal=0x%02X\n", __func__, *signal);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826) lgs8gxx_read_reg(priv, 0x95, &t);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827) dprintk("%s: AVG Noise=0x%02X\n", __func__, t);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832) static int lgs8g75_read_signal_strength(struct lgs8gxx_state *priv, u16 *signal)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834) u8 t;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835) s16 v = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837) dprintk("%s\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839) lgs8gxx_read_reg(priv, 0xB1, &t);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840) v |= t;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841) v <<= 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842) lgs8gxx_read_reg(priv, 0xB0, &t);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843) v |= t;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845) *signal = v;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846) dprintk("%s: signal=0x%02X\n", __func__, *signal);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 851) static int lgs8gxx_read_signal_strength(struct dvb_frontend *fe, u16 *signal)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 853) struct lgs8gxx_state *priv = fe->demodulator_priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 855) if (priv->config->prod == LGS8GXX_PROD_LGS8913)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 856) return lgs8913_read_signal_strength(priv, signal);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 857) else if (priv->config->prod == LGS8GXX_PROD_LGS8G75)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 858) return lgs8g75_read_signal_strength(priv, signal);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 859) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 860) return lgs8gxx_read_signal_agc(priv, signal);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 861) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 862)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 863) static int lgs8gxx_read_snr(struct dvb_frontend *fe, u16 *snr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 864) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 865) struct lgs8gxx_state *priv = fe->demodulator_priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 866) u8 t;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 867) *snr = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 868)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 869) if (priv->config->prod == LGS8GXX_PROD_LGS8G75)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 870) lgs8gxx_read_reg(priv, 0x34, &t);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 871) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 872) lgs8gxx_read_reg(priv, 0x95, &t);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 873) dprintk("AVG Noise=0x%02X\n", t);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 874) *snr = 256 - t;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 875) *snr <<= 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 876) dprintk("snr=0x%x\n", *snr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 877)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 878) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 879) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 880)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 881) static int lgs8gxx_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 882) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 883) *ucblocks = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 884) dprintk("%s: ucblocks=0x%x\n", __func__, *ucblocks);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 885) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 886) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 887)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 888) static void packet_counter_start(struct lgs8gxx_state *priv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 889) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 890) u8 orig, t;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 891)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 892) if (priv->config->prod == LGS8GXX_PROD_LGS8G75) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 893) lgs8gxx_read_reg(priv, 0x30, &orig);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 894) orig &= 0xE7;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 895) t = orig | 0x10;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 896) lgs8gxx_write_reg(priv, 0x30, t);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 897) t = orig | 0x18;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 898) lgs8gxx_write_reg(priv, 0x30, t);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 899) t = orig | 0x10;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 900) lgs8gxx_write_reg(priv, 0x30, t);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 901) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 902) lgs8gxx_write_reg(priv, 0xC6, 0x01);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 903) lgs8gxx_write_reg(priv, 0xC6, 0x41);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 904) lgs8gxx_write_reg(priv, 0xC6, 0x01);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 905) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 906) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 907)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 908) static void packet_counter_stop(struct lgs8gxx_state *priv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 909) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 910) u8 t;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 911)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 912) if (priv->config->prod == LGS8GXX_PROD_LGS8G75) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 913) lgs8gxx_read_reg(priv, 0x30, &t);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 914) t &= 0xE7;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 915) lgs8gxx_write_reg(priv, 0x30, t);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 916) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 917) lgs8gxx_write_reg(priv, 0xC6, 0x81);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 918) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 919) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 920)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 921) static int lgs8gxx_read_ber(struct dvb_frontend *fe, u32 *ber)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 922) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 923) struct lgs8gxx_state *priv = fe->demodulator_priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 924) u8 reg_err, reg_total, t;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 925) u32 total_cnt = 0, err_cnt = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 926) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 927)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 928) dprintk("%s\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 929)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 930) packet_counter_start(priv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 931) msleep(200);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 932) packet_counter_stop(priv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 933)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 934) if (priv->config->prod == LGS8GXX_PROD_LGS8G75) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 935) reg_total = 0x28; reg_err = 0x2C;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 936) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 937) reg_total = 0xD0; reg_err = 0xD4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 938) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 939)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 940) for (i = 0; i < 4; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 941) total_cnt <<= 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 942) lgs8gxx_read_reg(priv, reg_total+3-i, &t);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 943) total_cnt |= t;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 944) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 945) for (i = 0; i < 4; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 946) err_cnt <<= 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 947) lgs8gxx_read_reg(priv, reg_err+3-i, &t);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 948) err_cnt |= t;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 949) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 950) dprintk("error=%d total=%d\n", err_cnt, total_cnt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 951)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 952) if (total_cnt == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 953) *ber = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 954) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 955) *ber = err_cnt * 100 / total_cnt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 956)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 957) dprintk("%s: ber=0x%x\n", __func__, *ber);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 958) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 959) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 960)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 961) static int lgs8gxx_i2c_gate_ctrl(struct dvb_frontend *fe, int enable)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 962) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 963) struct lgs8gxx_state *priv = fe->demodulator_priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 964)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 965) if (priv->config->tuner_address == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 966) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 967) if (enable) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 968) u8 v = 0x80 | priv->config->tuner_address;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 969) return lgs8gxx_write_reg(priv, 0x01, v);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 970) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 971) return lgs8gxx_write_reg(priv, 0x01, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 972) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 973)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 974) static const struct dvb_frontend_ops lgs8gxx_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 975) .delsys = { SYS_DTMB },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 976) .info = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 977) .name = "Legend Silicon LGS8913/LGS8GXX DMB-TH",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 978) .frequency_min_hz = 474 * MHz,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 979) .frequency_max_hz = 858 * MHz,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 980) .frequency_stepsize_hz = 10 * kHz,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 981) .caps =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 982) FE_CAN_FEC_AUTO |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 983) FE_CAN_QAM_AUTO |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 984) FE_CAN_TRANSMISSION_MODE_AUTO |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 985) FE_CAN_GUARD_INTERVAL_AUTO
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 986) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 987)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 988) .release = lgs8gxx_release,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 989)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 990) .init = lgs8gxx_init,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 991) .write = lgs8gxx_write,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 992) .i2c_gate_ctrl = lgs8gxx_i2c_gate_ctrl,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 993)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 994) .set_frontend = lgs8gxx_set_fe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 995) .get_tune_settings = lgs8gxx_get_tune_settings,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 996)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 997) .read_status = lgs8gxx_read_status,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 998) .read_ber = lgs8gxx_read_ber,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 999) .read_signal_strength = lgs8gxx_read_signal_strength,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1000) .read_snr = lgs8gxx_read_snr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1001) .read_ucblocks = lgs8gxx_read_ucblocks,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1002) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1003)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1004) struct dvb_frontend *lgs8gxx_attach(const struct lgs8gxx_config *config,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1005) struct i2c_adapter *i2c)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1006) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1007) struct lgs8gxx_state *priv = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1008) u8 data = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1009)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1010) dprintk("%s()\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1011)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1012) if (config == NULL || i2c == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1013) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1014)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1015) priv = kzalloc(sizeof(struct lgs8gxx_state), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1016) if (priv == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1017) goto error_out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1018)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1019) priv->config = config;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1020) priv->i2c = i2c;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1021)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1022) /* check if the demod is there */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1023) if (lgs8gxx_read_reg(priv, 0, &data) != 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1024) dprintk("%s lgs8gxx not found at i2c addr 0x%02X\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1025) __func__, priv->config->demod_address);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1026) goto error_out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1027) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1028)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1029) lgs8gxx_read_reg(priv, 1, &data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1030)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1031) memcpy(&priv->frontend.ops, &lgs8gxx_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1032) sizeof(struct dvb_frontend_ops));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1033) priv->frontend.demodulator_priv = priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1034)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1035) if (config->prod == LGS8GXX_PROD_LGS8G75)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1036) lgs8g75_init_data(priv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1037)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1038) return &priv->frontend;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1039)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1040) error_out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1041) dprintk("%s() error_out\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1042) kfree(priv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1043) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1044)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1045) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1046) EXPORT_SYMBOL(lgs8gxx_attach);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1047)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1048) MODULE_DESCRIPTION("Legend Silicon LGS8913/LGS8GXX DMB-TH demodulator driver");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1049) MODULE_AUTHOR("David T. L. Wong <davidtlwong@gmail.com>");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1050) MODULE_LICENSE("GPL");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1051) MODULE_FIRMWARE(LGS8GXX_FIRMWARE);