^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) * Driver for Silicon Labs Si2161 DVB-T and Si2165 DVB-C/-T Demodulator
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Copyright (C) 2013-2017 Matthias Schwarzott <zzam@gentoo.org>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * References:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * http://www.silabs.com/Support%20Documents/TechnicalDocs/Si2165-short.pdf
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <linux/delay.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <linux/errno.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <linux/init.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <linux/string.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include <linux/firmware.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include <linux/regmap.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #include <media/dvb_frontend.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #include <media/dvb_math.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #include "si2165_priv.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #include "si2165.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) * Hauppauge WinTV-HVR-930C-HD B130 / PCTV QuatroStick 521e 1113xx
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) * uses 16 MHz xtal
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) * Hauppauge WinTV-HVR-930C-HD B131 / PCTV QuatroStick 522e 1114xx
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) * uses 24 MHz clock provided by tuner
^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) struct si2165_state {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) struct i2c_client *client;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) struct regmap *regmap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) struct dvb_frontend fe;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) struct si2165_config config;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) u8 chip_revcode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) u8 chip_type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) /* calculated by xtal and div settings */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) u32 fvco_hz;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) u32 sys_clk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) u32 adc_clk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) /* DVBv3 stats */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) u64 ber_prev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) bool has_dvbc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) bool has_dvbt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) bool firmware_loaded;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) static int si2165_write(struct si2165_state *state, const u16 reg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) const u8 *src, const int count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) dev_dbg(&state->client->dev, "i2c write: reg: 0x%04x, data: %*ph\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) reg, count, src);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) ret = regmap_bulk_write(state->regmap, reg, src, count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) dev_err(&state->client->dev, "%s: ret == %d\n", __func__, ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) static int si2165_read(struct si2165_state *state,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) const u16 reg, u8 *val, const int count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) int ret = regmap_bulk_read(state->regmap, reg, val, count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) dev_err(&state->client->dev, "%s: error (addr %02x reg %04x error (ret == %i)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) __func__, state->config.i2c_addr, reg, ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) dev_dbg(&state->client->dev, "i2c read: reg: 0x%04x, data: %*ph\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) reg, count, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) static int si2165_readreg8(struct si2165_state *state,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) const u16 reg, u8 *val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) unsigned int val_tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) int ret = regmap_read(state->regmap, reg, &val_tmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) *val = (u8)val_tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) dev_dbg(&state->client->dev, "reg read: R(0x%04x)=0x%02x\n", reg, *val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) static int si2165_readreg16(struct si2165_state *state,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) const u16 reg, u16 *val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) u8 buf[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) int ret = si2165_read(state, reg, buf, 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) *val = buf[0] | buf[1] << 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) dev_dbg(&state->client->dev, "reg read: R(0x%04x)=0x%04x\n", reg, *val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) return ret;
^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 int si2165_readreg24(struct si2165_state *state,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) const u16 reg, u32 *val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) u8 buf[3];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) int ret = si2165_read(state, reg, buf, 3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) *val = buf[0] | buf[1] << 8 | buf[2] << 16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) dev_dbg(&state->client->dev, "reg read: R(0x%04x)=0x%06x\n", reg, *val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) static int si2165_writereg8(struct si2165_state *state, const u16 reg, u8 val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) return regmap_write(state->regmap, reg, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) static int si2165_writereg16(struct si2165_state *state, const u16 reg, u16 val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) u8 buf[2] = { val & 0xff, (val >> 8) & 0xff };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) return si2165_write(state, reg, buf, 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) static int si2165_writereg24(struct si2165_state *state, const u16 reg, u32 val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) u8 buf[3] = { val & 0xff, (val >> 8) & 0xff, (val >> 16) & 0xff };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) return si2165_write(state, reg, buf, 3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) static int si2165_writereg32(struct si2165_state *state, const u16 reg, u32 val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) u8 buf[4] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) val & 0xff,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) (val >> 8) & 0xff,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) (val >> 16) & 0xff,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) (val >> 24) & 0xff
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) return si2165_write(state, reg, buf, 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) static int si2165_writereg_mask8(struct si2165_state *state, const u16 reg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) u8 val, u8 mask)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) if (mask != 0xff) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) u8 tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) int ret = si2165_readreg8(state, reg, &tmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) val &= mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) tmp &= ~mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) val |= tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) return si2165_writereg8(state, reg, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) #define REG16(reg, val) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) { (reg), (val) & 0xff }, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) { (reg) + 1, (val) >> 8 & 0xff }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) struct si2165_reg_value_pair {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) u16 reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) u8 val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) static int si2165_write_reg_list(struct si2165_state *state,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) const struct si2165_reg_value_pair *regs,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) int count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) for (i = 0; i < count; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) ret = si2165_writereg8(state, regs[i].reg, regs[i].val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) static int si2165_get_tune_settings(struct dvb_frontend *fe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) struct dvb_frontend_tune_settings *s)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) s->min_delay_ms = 1000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) static int si2165_init_pll(struct si2165_state *state)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) u32 ref_freq_hz = state->config.ref_freq_hz;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) u8 divr = 1; /* 1..7 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) u8 divp = 1; /* only 1 or 4 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) u8 divn = 56; /* 1..63 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) u8 divm = 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) u8 divl = 12;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) u8 buf[4];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) * hardcoded values can be deleted if calculation is verified
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) * or it yields the same values as the windows driver
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) switch (ref_freq_hz) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) case 16000000u:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) divn = 56;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) case 24000000u:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) divr = 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) divp = 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) divn = 19;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) /* ref_freq / divr must be between 4 and 16 MHz */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) if (ref_freq_hz > 16000000u)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) divr = 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) * now select divn and divp such that
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) * fvco is in 1624..1824 MHz
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) if (1624000000u * divr > ref_freq_hz * 2u * 63u)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) divp = 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) /* is this already correct regarding rounding? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) divn = 1624000000u * divr / (ref_freq_hz * 2u * divp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) /* adc_clk and sys_clk depend on xtal and pll settings */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) state->fvco_hz = ref_freq_hz / divr
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) * 2u * divn * divp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) state->adc_clk = state->fvco_hz / (divm * 4u);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) state->sys_clk = state->fvco_hz / (divl * 2u);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) /* write all 4 pll registers 0x00a0..0x00a3 at once */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) buf[0] = divl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) buf[1] = divm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) buf[2] = (divn & 0x3f) | ((divp == 1) ? 0x40 : 0x00) | 0x80;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) buf[3] = divr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) return si2165_write(state, REG_PLL_DIVL, buf, 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) static int si2165_adjust_pll_divl(struct si2165_state *state, u8 divl)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) state->sys_clk = state->fvco_hz / (divl * 2u);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) return si2165_writereg8(state, REG_PLL_DIVL, divl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) static u32 si2165_get_fe_clk(struct si2165_state *state)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) /* assume Oversampling mode Ovr4 is used */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) return state->adc_clk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) static int si2165_wait_init_done(struct si2165_state *state)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) u8 val = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) for (i = 0; i < 3; ++i) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) ret = si2165_readreg8(state, REG_INIT_DONE, &val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) if (val == 0x01)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) usleep_range(1000, 50000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) dev_err(&state->client->dev, "init_done was not set\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) static int si2165_upload_firmware_block(struct si2165_state *state,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) const u8 *data, u32 len, u32 *poffset,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) u32 block_count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) u8 buf_ctrl[4] = { 0x00, 0x00, 0x00, 0xc0 };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) u8 wordcount;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) u32 cur_block = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) u32 offset = poffset ? *poffset : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) if (len < 4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) if (len % 4 != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) dev_dbg(&state->client->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) "fw load: %s: called with len=0x%x offset=0x%x blockcount=0x%x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) __func__, len, offset, block_count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) while (offset + 12 <= len && cur_block < block_count) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) dev_dbg(&state->client->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) "fw load: %s: in while len=0x%x offset=0x%x cur_block=0x%x blockcount=0x%x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) __func__, len, offset, cur_block, block_count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) wordcount = data[offset];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) if (wordcount < 1 || data[offset + 1] ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) data[offset + 2] || data[offset + 3]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) dev_warn(&state->client->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) "bad fw data[0..3] = %*ph\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) 4, data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) if (offset + 8 + wordcount * 4 > len) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) dev_warn(&state->client->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) "len is too small for block len=%d, wordcount=%d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) len, wordcount);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) buf_ctrl[0] = wordcount - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) ret = si2165_write(state, REG_DCOM_CONTROL_BYTE, buf_ctrl, 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) ret = si2165_write(state, REG_DCOM_ADDR, data + offset + 4, 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) offset += 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) while (wordcount > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) ret = si2165_write(state, REG_DCOM_DATA,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) data + offset, 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) wordcount--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) offset += 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) cur_block++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) dev_dbg(&state->client->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) "fw load: %s: after while len=0x%x offset=0x%x cur_block=0x%x blockcount=0x%x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) __func__, len, offset, cur_block, block_count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) if (poffset)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) *poffset = offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) dev_dbg(&state->client->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) "fw load: %s: returned offset=0x%x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) __func__, offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) error:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) static int si2165_upload_firmware(struct si2165_state *state)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) /* int ret; */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) u8 val[3];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) u16 val16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) const struct firmware *fw = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) u8 *fw_file;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) const u8 *data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) u32 len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) u32 offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) u8 patch_version;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) u8 block_count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) u16 crc_expected;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) switch (state->chip_revcode) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) case 0x03: /* revision D */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) fw_file = SI2165_FIRMWARE_REV_D;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) dev_info(&state->client->dev, "no firmware file for revision=%d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) state->chip_revcode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) /* request the firmware, this will block and timeout */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) ret = request_firmware(&fw, fw_file, &state->client->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) dev_warn(&state->client->dev, "firmware file '%s' not found\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) fw_file);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) data = fw->data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) len = fw->size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) dev_info(&state->client->dev, "downloading firmware from file '%s' size=%d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) fw_file, len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) if (len % 4 != 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) dev_warn(&state->client->dev, "firmware size is not multiple of 4\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) ret = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) /* check header (8 bytes) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) if (len < 8) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) dev_warn(&state->client->dev, "firmware header is missing\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) ret = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) if (data[0] != 1 || data[1] != 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) dev_warn(&state->client->dev, "firmware file version is wrong\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) ret = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) goto error;
^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) patch_version = data[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) block_count = data[4];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) crc_expected = data[7] << 8 | data[6];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) /* start uploading fw */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) /* boot/wdog status */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) ret = si2165_writereg8(state, REG_WDOG_AND_BOOT, 0x00);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) /* reset */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) ret = si2165_writereg8(state, REG_RST_ALL, 0x00);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) /* boot/wdog status */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) ret = si2165_readreg8(state, REG_WDOG_AND_BOOT, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) /* enable reset on error */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) ret = si2165_readreg8(state, REG_EN_RST_ERROR, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) ret = si2165_readreg8(state, REG_EN_RST_ERROR, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) ret = si2165_writereg8(state, REG_EN_RST_ERROR, 0x02);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) /* start right after the header */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) offset = 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) dev_info(&state->client->dev, "%s: extracted patch_version=0x%02x, block_count=0x%02x, crc_expected=0x%04x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) __func__, patch_version, block_count, crc_expected);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) ret = si2165_upload_firmware_block(state, data, len, &offset, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) ret = si2165_writereg8(state, REG_PATCH_VERSION, patch_version);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) /* reset crc */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) ret = si2165_writereg8(state, REG_RST_CRC, 0x01);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) ret = si2165_upload_firmware_block(state, data, len,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) &offset, block_count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) dev_err(&state->client->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) "firmware could not be uploaded\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) /* read crc */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) ret = si2165_readreg16(state, REG_CRC, &val16);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) if (val16 != crc_expected) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) dev_err(&state->client->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) "firmware crc mismatch %04x != %04x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) val16, crc_expected);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) ret = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) ret = si2165_upload_firmware_block(state, data, len, &offset, 5);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) if (len != offset) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) dev_err(&state->client->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) "firmware len mismatch %04x != %04x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) len, offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) ret = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) /* reset watchdog error register */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) ret = si2165_writereg_mask8(state, REG_WDOG_AND_BOOT, 0x02, 0x02);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) /* enable reset on error */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) ret = si2165_writereg_mask8(state, REG_EN_RST_ERROR, 0x01, 0x01);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) dev_info(&state->client->dev, "fw load finished\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) state->firmware_loaded = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) error:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) if (fw) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) release_firmware(fw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) fw = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) static int si2165_init(struct dvb_frontend *fe)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) struct si2165_state *state = fe->demodulator_priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) struct dtv_frontend_properties *c = &fe->dtv_property_cache;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) u8 val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) u8 patch_version = 0x00;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) dev_dbg(&state->client->dev, "%s: called\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) /* powerup */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) ret = si2165_writereg8(state, REG_CHIP_MODE, state->config.chip_mode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) /* dsp_clock_enable */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) ret = si2165_writereg8(state, REG_DSP_CLOCK, 0x01);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) /* verify chip_mode */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) ret = si2165_readreg8(state, REG_CHIP_MODE, &val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) if (val != state->config.chip_mode) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) dev_err(&state->client->dev, "could not set chip_mode\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) /* agc */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) ret = si2165_writereg8(state, REG_AGC_IF_TRI, 0x00);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) ret = si2165_writereg8(state, REG_AGC_IF_SLR, 0x01);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) ret = si2165_writereg8(state, REG_AGC2_OUTPUT, 0x00);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) ret = si2165_writereg8(state, REG_AGC2_CLKDIV, 0x07);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) /* rssi pad */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) ret = si2165_writereg8(state, REG_RSSI_PAD_CTRL, 0x00);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) ret = si2165_writereg8(state, REG_RSSI_ENABLE, 0x00);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) ret = si2165_init_pll(state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) /* enable chip_init */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) ret = si2165_writereg8(state, REG_CHIP_INIT, 0x01);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) /* set start_init */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) ret = si2165_writereg8(state, REG_START_INIT, 0x01);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) ret = si2165_wait_init_done(state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) /* disable chip_init */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) ret = si2165_writereg8(state, REG_CHIP_INIT, 0x00);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) /* ber_pkt - default 65535 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) ret = si2165_writereg16(state, REG_BER_PKT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) STATISTICS_PERIOD_PKT_COUNT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) ret = si2165_readreg8(state, REG_PATCH_VERSION, &patch_version);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) ret = si2165_writereg8(state, REG_AUTO_RESET, 0x00);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) /* dsp_addr_jump */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) ret = si2165_writereg32(state, REG_ADDR_JUMP, 0xf4000000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) /* boot/wdog status */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) ret = si2165_readreg8(state, REG_WDOG_AND_BOOT, &val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) if (patch_version == 0x00) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) ret = si2165_upload_firmware(state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) /* ts output config */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) ret = si2165_writereg8(state, REG_TS_DATA_MODE, 0x20);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) ret = si2165_writereg16(state, REG_TS_TRI, 0x00fe);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) ret = si2165_writereg24(state, REG_TS_SLR, 0x555555);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) ret = si2165_writereg8(state, REG_TS_CLK_MODE, 0x01);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) ret = si2165_writereg8(state, REG_TS_PARALLEL_MODE, 0x00);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) c = &state->fe.dtv_property_cache;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) c->cnr.len = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) c->cnr.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) c->post_bit_error.len = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) c->post_bit_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) c->post_bit_count.len = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) c->post_bit_count.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) error:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) static int si2165_sleep(struct dvb_frontend *fe)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) struct si2165_state *state = fe->demodulator_priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) /* dsp clock disable */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) ret = si2165_writereg8(state, REG_DSP_CLOCK, 0x00);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) /* chip mode */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) ret = si2165_writereg8(state, REG_CHIP_MODE, SI2165_MODE_OFF);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) static int si2165_read_status(struct dvb_frontend *fe, enum fe_status *status)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) u8 u8tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) u32 u32tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) struct si2165_state *state = fe->demodulator_priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) struct dtv_frontend_properties *c = &fe->dtv_property_cache;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) u32 delsys = c->delivery_system;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) *status = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) switch (delsys) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) case SYS_DVBT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) /* check fast signal type */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) ret = si2165_readreg8(state, REG_CHECK_SIGNAL, &u8tmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) switch (u8tmp & 0x3) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) case 0: /* searching */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) case 1: /* nothing */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) case 2: /* digital signal */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) *status |= FE_HAS_SIGNAL | FE_HAS_CARRIER;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) case SYS_DVBC_ANNEX_A:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) /* check packet sync lock */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) ret = si2165_readreg8(state, REG_PS_LOCK, &u8tmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) if (u8tmp & 0x01) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) *status |= FE_HAS_SIGNAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) *status |= FE_HAS_CARRIER;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) *status |= FE_HAS_VITERBI;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) *status |= FE_HAS_SYNC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) /* check fec_lock */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) ret = si2165_readreg8(state, REG_FEC_LOCK, &u8tmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) if (u8tmp & 0x01) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) *status |= FE_HAS_SIGNAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714) *status |= FE_HAS_CARRIER;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) *status |= FE_HAS_VITERBI;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) *status |= FE_HAS_SYNC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) *status |= FE_HAS_LOCK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) /* CNR */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) if (delsys == SYS_DVBC_ANNEX_A && *status & FE_HAS_VITERBI) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) ret = si2165_readreg24(state, REG_C_N, &u32tmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726) * svalue =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727) * 1000 * c_n/dB =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) * 1000 * 10 * log10(2^24 / regval) =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729) * 1000 * 10 * (log10(2^24) - log10(regval)) =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730) * 1000 * 10 * (intlog10(2^24) - intlog10(regval)) / 2^24
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732) * intlog10(x) = log10(x) * 2^24
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733) * intlog10(2^24) = log10(2^24) * 2^24 = 121210686
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735) u32tmp = (1000 * 10 * (121210686 - (u64)intlog10(u32tmp)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736) >> 24;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) c->cnr.stat[0].scale = FE_SCALE_DECIBEL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738) c->cnr.stat[0].svalue = u32tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740) c->cnr.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742) /* BER */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) if (*status & FE_HAS_VITERBI) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744) if (c->post_bit_error.stat[0].scale == FE_SCALE_NOT_AVAILABLE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) /* start new sampling period to get rid of old data*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746) ret = si2165_writereg8(state, REG_BER_RST, 0x01);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) /* set scale to enter read code on next call */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) c->post_bit_error.stat[0].scale = FE_SCALE_COUNTER;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752) c->post_bit_count.stat[0].scale = FE_SCALE_COUNTER;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753) c->post_bit_error.stat[0].uvalue = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754) c->post_bit_count.stat[0].uvalue = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757) * reset DVBv3 value to deliver a good result
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758) * for the first call
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760) state->ber_prev = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763) ret = si2165_readreg8(state, REG_BER_AVAIL, &u8tmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767) if (u8tmp & 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768) u32 biterrcnt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770) ret = si2165_readreg24(state, REG_BER_BIT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771) &biterrcnt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775) c->post_bit_error.stat[0].uvalue +=
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776) biterrcnt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777) c->post_bit_count.stat[0].uvalue +=
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778) STATISTICS_PERIOD_BIT_COUNT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780) /* start new sampling period */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781) ret = si2165_writereg8(state,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782) REG_BER_RST, 0x01);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786) dev_dbg(&state->client->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787) "post_bit_error=%u post_bit_count=%u\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788) biterrcnt, STATISTICS_PERIOD_BIT_COUNT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792) c->post_bit_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793) c->post_bit_count.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
^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) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799) static int si2165_read_snr(struct dvb_frontend *fe, u16 *snr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801) struct dtv_frontend_properties *c = &fe->dtv_property_cache;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803) if (c->cnr.stat[0].scale == FE_SCALE_DECIBEL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804) *snr = div_s64(c->cnr.stat[0].svalue, 100);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806) *snr = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810) static int si2165_read_ber(struct dvb_frontend *fe, u32 *ber)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812) struct si2165_state *state = fe->demodulator_priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813) struct dtv_frontend_properties *c = &fe->dtv_property_cache;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815) if (c->post_bit_error.stat[0].scale != FE_SCALE_COUNTER) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816) *ber = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820) *ber = c->post_bit_error.stat[0].uvalue - state->ber_prev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821) state->ber_prev = c->post_bit_error.stat[0].uvalue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826) static int si2165_set_oversamp(struct si2165_state *state, u32 dvb_rate)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828) u64 oversamp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829) u32 reg_value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831) if (!dvb_rate)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834) oversamp = si2165_get_fe_clk(state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835) oversamp <<= 23;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836) do_div(oversamp, dvb_rate);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837) reg_value = oversamp & 0x3fffffff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839) dev_dbg(&state->client->dev, "Write oversamp=%#x\n", reg_value);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840) return si2165_writereg32(state, REG_OVERSAMP, reg_value);
^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) static int si2165_set_if_freq_shift(struct si2165_state *state)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845) struct dvb_frontend *fe = &state->fe;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846) u64 if_freq_shift;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847) s32 reg_value = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848) u32 fe_clk = si2165_get_fe_clk(state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849) u32 IF = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 851) if (!fe->ops.tuner_ops.get_if_frequency) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852) dev_err(&state->client->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 853) "Error: get_if_frequency() not defined at tuner. Can't work without it!\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 855) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 856)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 857) if (!fe_clk)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 858) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 859)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 860) fe->ops.tuner_ops.get_if_frequency(fe, &IF);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 861) if_freq_shift = IF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 862) if_freq_shift <<= 29;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 863)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 864) do_div(if_freq_shift, fe_clk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 865) reg_value = (s32)if_freq_shift;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 866)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 867) if (state->config.inversion)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 868) reg_value = -reg_value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 869)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 870) reg_value = reg_value & 0x1fffffff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 871)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 872) /* if_freq_shift, usbdump contained 0x023ee08f; */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 873) return si2165_writereg32(state, REG_IF_FREQ_SHIFT, reg_value);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 874) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 875)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 876) static const struct si2165_reg_value_pair dvbt_regs[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 877) /* standard = DVB-T */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 878) { REG_DVB_STANDARD, 0x01 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 879) /* impulsive_noise_remover */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 880) { REG_IMPULSIVE_NOISE_REM, 0x01 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 881) { REG_AUTO_RESET, 0x00 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 882) /* agc2 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 883) { REG_AGC2_MIN, 0x41 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 884) { REG_AGC2_KACQ, 0x0e },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 885) { REG_AGC2_KLOC, 0x10 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 886) /* agc */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 887) { REG_AGC_UNFREEZE_THR, 0x03 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 888) { REG_AGC_CRESTF_DBX8, 0x78 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 889) /* agc */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 890) { REG_AAF_CRESTF_DBX8, 0x78 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 891) { REG_ACI_CRESTF_DBX8, 0x68 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 892) /* freq_sync_range */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 893) REG16(REG_FREQ_SYNC_RANGE, 0x0064),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 894) /* gp_reg0 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 895) { REG_GP_REG0_MSB, 0x00 }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 896) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 897)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 898) static int si2165_set_frontend_dvbt(struct dvb_frontend *fe)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 899) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 900) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 901) struct dtv_frontend_properties *p = &fe->dtv_property_cache;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 902) struct si2165_state *state = fe->demodulator_priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 903) u32 dvb_rate = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 904) u16 bw10k;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 905) u32 bw_hz = p->bandwidth_hz;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 906)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 907) dev_dbg(&state->client->dev, "%s: called\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 908)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 909) if (!state->has_dvbt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 910) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 911)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 912) /* no bandwidth auto-detection */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 913) if (bw_hz == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 914) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 915)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 916) dvb_rate = bw_hz * 8 / 7;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 917) bw10k = bw_hz / 10000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 918)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 919) ret = si2165_adjust_pll_divl(state, 12);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 920) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 921) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 922)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 923) /* bandwidth in 10KHz steps */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 924) ret = si2165_writereg16(state, REG_T_BANDWIDTH, bw10k);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 925) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 926) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 927) ret = si2165_set_oversamp(state, dvb_rate);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 928) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 929) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 930)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 931) ret = si2165_write_reg_list(state, dvbt_regs, ARRAY_SIZE(dvbt_regs));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 932) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 933) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 934)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 935) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 936) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 937)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 938) static const struct si2165_reg_value_pair dvbc_regs[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 939) /* standard = DVB-C */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 940) { REG_DVB_STANDARD, 0x05 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 941)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 942) /* agc2 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 943) { REG_AGC2_MIN, 0x50 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 944) { REG_AGC2_KACQ, 0x0e },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 945) { REG_AGC2_KLOC, 0x10 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 946) /* agc */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 947) { REG_AGC_UNFREEZE_THR, 0x03 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 948) { REG_AGC_CRESTF_DBX8, 0x68 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 949) /* agc */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 950) { REG_AAF_CRESTF_DBX8, 0x68 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 951) { REG_ACI_CRESTF_DBX8, 0x50 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 952)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 953) { REG_EQ_AUTO_CONTROL, 0x0d },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 954)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 955) { REG_KP_LOCK, 0x05 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 956) { REG_CENTRAL_TAP, 0x09 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 957) REG16(REG_UNKNOWN_350, 0x3e80),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 958)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 959) { REG_AUTO_RESET, 0x01 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 960) REG16(REG_UNKNOWN_24C, 0x0000),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 961) REG16(REG_UNKNOWN_27C, 0x0000),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 962) { REG_SWEEP_STEP, 0x03 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 963) { REG_AGC_IF_TRI, 0x00 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 964) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 965)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 966) static int si2165_set_frontend_dvbc(struct dvb_frontend *fe)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 967) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 968) struct si2165_state *state = fe->demodulator_priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 969) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 970) struct dtv_frontend_properties *p = &fe->dtv_property_cache;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 971) const u32 dvb_rate = p->symbol_rate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 972) u8 u8tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 973)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 974) if (!state->has_dvbc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 975) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 976)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 977) if (dvb_rate == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 978) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 979)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 980) ret = si2165_adjust_pll_divl(state, 14);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 981) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 982) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 983)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 984) /* Oversampling */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 985) ret = si2165_set_oversamp(state, dvb_rate);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 986) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 987) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 988)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 989) switch (p->modulation) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 990) case QPSK:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 991) u8tmp = 0x3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 992) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 993) case QAM_16:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 994) u8tmp = 0x7;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 995) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 996) case QAM_32:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 997) u8tmp = 0x8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 998) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 999) case QAM_64:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1000) u8tmp = 0x9;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1001) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1002) case QAM_128:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1003) u8tmp = 0xa;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1004) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1005) case QAM_256:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1006) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1007) u8tmp = 0xb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1008) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1009) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1010) ret = si2165_writereg8(state, REG_REQ_CONSTELLATION, u8tmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1011) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1012) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1013)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1014) ret = si2165_writereg32(state, REG_LOCK_TIMEOUT, 0x007a1200);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1015) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1016) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1017)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1018) ret = si2165_write_reg_list(state, dvbc_regs, ARRAY_SIZE(dvbc_regs));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1019) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1020) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1021)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1022) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1023) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1024)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1025) static const struct si2165_reg_value_pair adc_rewrite[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1026) { REG_ADC_RI1, 0x46 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1027) { REG_ADC_RI3, 0x00 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1028) { REG_ADC_RI5, 0x0a },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1029) { REG_ADC_RI6, 0xff },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1030) { REG_ADC_RI8, 0x70 }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1031) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1032)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1033) static int si2165_set_frontend(struct dvb_frontend *fe)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1034) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1035) struct si2165_state *state = fe->demodulator_priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1036) struct dtv_frontend_properties *p = &fe->dtv_property_cache;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1037) u32 delsys = p->delivery_system;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1038) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1039) u8 val[3];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1040)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1041) /* initial setting of if freq shift */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1042) ret = si2165_set_if_freq_shift(state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1043) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1044) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1045)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1046) switch (delsys) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1047) case SYS_DVBT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1048) ret = si2165_set_frontend_dvbt(fe);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1049) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1050) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1051) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1052) case SYS_DVBC_ANNEX_A:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1053) ret = si2165_set_frontend_dvbc(fe);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1054) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1055) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1056) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1057) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1058) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1059) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1060)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1061) /* dsp_addr_jump */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1062) ret = si2165_writereg32(state, REG_ADDR_JUMP, 0xf4000000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1063) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1064) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1065)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1066) if (fe->ops.tuner_ops.set_params)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1067) fe->ops.tuner_ops.set_params(fe);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1068)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1069) /* recalc if_freq_shift if IF might has changed */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1070) ret = si2165_set_if_freq_shift(state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1071) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1072) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1073)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1074) /* boot/wdog status */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1075) ret = si2165_readreg8(state, REG_WDOG_AND_BOOT, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1076) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1077) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1078) ret = si2165_writereg8(state, REG_WDOG_AND_BOOT, 0x00);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1079) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1080) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1081)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1082) /* reset all */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1083) ret = si2165_writereg8(state, REG_RST_ALL, 0x00);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1084) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1085) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1086) /* gp_reg0 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1087) ret = si2165_writereg32(state, REG_GP_REG0_LSB, 0x00000000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1088) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1089) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1090)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1091) /* write adc values after each reset*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1092) ret = si2165_write_reg_list(state, adc_rewrite,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1093) ARRAY_SIZE(adc_rewrite));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1094) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1095) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1096)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1097) /* start_synchro */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1098) ret = si2165_writereg8(state, REG_START_SYNCHRO, 0x01);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1099) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1100) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1101) /* boot/wdog status */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1102) ret = si2165_readreg8(state, REG_WDOG_AND_BOOT, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1103) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1104) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1105)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1106) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1107) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1108)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1109) static const struct dvb_frontend_ops si2165_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1110) .info = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1111) .name = "Silicon Labs ",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1112) /* For DVB-C */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1113) .symbol_rate_min = 1000000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1114) .symbol_rate_max = 7200000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1115) /* For DVB-T */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1116) .frequency_stepsize_hz = 166667,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1117) .caps = FE_CAN_FEC_1_2 |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1118) FE_CAN_FEC_2_3 |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1119) FE_CAN_FEC_3_4 |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1120) FE_CAN_FEC_5_6 |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1121) FE_CAN_FEC_7_8 |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1122) FE_CAN_FEC_AUTO |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1123) FE_CAN_QPSK |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1124) FE_CAN_QAM_16 |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1125) FE_CAN_QAM_32 |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1126) FE_CAN_QAM_64 |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1127) FE_CAN_QAM_128 |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1128) FE_CAN_QAM_256 |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1129) FE_CAN_GUARD_INTERVAL_AUTO |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1130) FE_CAN_HIERARCHY_AUTO |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1131) FE_CAN_MUTE_TS |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1132) FE_CAN_TRANSMISSION_MODE_AUTO |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1133) FE_CAN_RECOVER
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1134) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1135)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1136) .get_tune_settings = si2165_get_tune_settings,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1137)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1138) .init = si2165_init,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1139) .sleep = si2165_sleep,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1140)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1141) .set_frontend = si2165_set_frontend,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1142) .read_status = si2165_read_status,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1143) .read_snr = si2165_read_snr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1144) .read_ber = si2165_read_ber,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1145) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1146)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1147) static int si2165_probe(struct i2c_client *client,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1148) const struct i2c_device_id *id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1149) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1150) struct si2165_state *state = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1151) struct si2165_platform_data *pdata = client->dev.platform_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1152) int n;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1153) int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1154) u8 val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1155) char rev_char;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1156) const char *chip_name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1157) static const struct regmap_config regmap_config = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1158) .reg_bits = 16,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1159) .val_bits = 8,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1160) .max_register = 0x08ff,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1161) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1162)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1163) /* allocate memory for the internal state */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1164) state = kzalloc(sizeof(*state), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1165) if (!state) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1166) ret = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1167) goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1168) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1169)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1170) /* create regmap */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1171) state->regmap = devm_regmap_init_i2c(client, ®map_config);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1172) if (IS_ERR(state->regmap)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1173) ret = PTR_ERR(state->regmap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1174) goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1175) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1176)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1177) /* setup the state */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1178) state->client = client;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1179) state->config.i2c_addr = client->addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1180) state->config.chip_mode = pdata->chip_mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1181) state->config.ref_freq_hz = pdata->ref_freq_hz;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1182) state->config.inversion = pdata->inversion;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1183)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1184) if (state->config.ref_freq_hz < 4000000 ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1185) state->config.ref_freq_hz > 27000000) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1186) dev_err(&state->client->dev, "ref_freq of %d Hz not supported by this driver\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1187) state->config.ref_freq_hz);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1188) ret = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1189) goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1190) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1191)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1192) /* create dvb_frontend */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1193) memcpy(&state->fe.ops, &si2165_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1194) sizeof(struct dvb_frontend_ops));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1195) state->fe.ops.release = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1196) state->fe.demodulator_priv = state;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1197) i2c_set_clientdata(client, state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1198)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1199) /* powerup */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1200) ret = si2165_writereg8(state, REG_CHIP_MODE, state->config.chip_mode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1201) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1202) goto nodev_error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1203)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1204) ret = si2165_readreg8(state, REG_CHIP_MODE, &val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1205) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1206) goto nodev_error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1207) if (val != state->config.chip_mode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1208) goto nodev_error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1209)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1210) ret = si2165_readreg8(state, REG_CHIP_REVCODE, &state->chip_revcode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1211) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1212) goto nodev_error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1213)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1214) ret = si2165_readreg8(state, REV_CHIP_TYPE, &state->chip_type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1215) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1216) goto nodev_error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1217)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1218) /* powerdown */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1219) ret = si2165_writereg8(state, REG_CHIP_MODE, SI2165_MODE_OFF);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1220) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1221) goto nodev_error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1222)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1223) if (state->chip_revcode < 26)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1224) rev_char = 'A' + state->chip_revcode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1225) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1226) rev_char = '?';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1227)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1228) switch (state->chip_type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1229) case 0x06:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1230) chip_name = "Si2161";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1231) state->has_dvbt = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1232) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1233) case 0x07:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1234) chip_name = "Si2165";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1235) state->has_dvbt = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1236) state->has_dvbc = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1237) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1238) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1239) dev_err(&state->client->dev, "Unsupported Silicon Labs chip (type %d, rev %d)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1240) state->chip_type, state->chip_revcode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1241) goto nodev_error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1242) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1243)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1244) dev_info(&state->client->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1245) "Detected Silicon Labs %s-%c (type %d, rev %d)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1246) chip_name, rev_char, state->chip_type,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1247) state->chip_revcode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1248)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1249) strlcat(state->fe.ops.info.name, chip_name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1250) sizeof(state->fe.ops.info.name));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1251)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1252) n = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1253) if (state->has_dvbt) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1254) state->fe.ops.delsys[n++] = SYS_DVBT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1255) strlcat(state->fe.ops.info.name, " DVB-T",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1256) sizeof(state->fe.ops.info.name));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1257) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1258) if (state->has_dvbc) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1259) state->fe.ops.delsys[n++] = SYS_DVBC_ANNEX_A;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1260) strlcat(state->fe.ops.info.name, " DVB-C",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1261) sizeof(state->fe.ops.info.name));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1262) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1263)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1264) /* return fe pointer */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1265) *pdata->fe = &state->fe;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1266)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1267) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1268)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1269) nodev_error:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1270) ret = -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1271) error:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1272) kfree(state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1273) dev_dbg(&client->dev, "failed=%d\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1274) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1275) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1276)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1277) static int si2165_remove(struct i2c_client *client)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1278) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1279) struct si2165_state *state = i2c_get_clientdata(client);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1280)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1281) dev_dbg(&client->dev, "\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1282)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1283) kfree(state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1284) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1285) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1286)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1287) static const struct i2c_device_id si2165_id_table[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1288) {"si2165", 0},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1289) {}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1290) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1291) MODULE_DEVICE_TABLE(i2c, si2165_id_table);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1292)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1293) static struct i2c_driver si2165_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1294) .driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1295) .name = "si2165",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1296) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1297) .probe = si2165_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1298) .remove = si2165_remove,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1299) .id_table = si2165_id_table,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1300) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1301)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1302) module_i2c_driver(si2165_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1303)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1304) MODULE_DESCRIPTION("Silicon Labs Si2165 DVB-C/-T Demodulator driver");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1305) MODULE_AUTHOR("Matthias Schwarzott <zzam@gentoo.org>");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1306) MODULE_LICENSE("GPL");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1307) MODULE_FIRMWARE(SI2165_FIRMWARE_REV_D);