^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 NXT2002 and NXT2004 - VSB/QAM
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Copyright (C) 2005 Kirk Lapray <kirk.lapray@gmail.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * Copyright (C) 2006-2014 Michael Krufky <mkrufky@linuxtv.org>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * based on nxt2002 by Taylor Jacob <rtjacob@earthlink.net>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * and nxt2004 by Jean-Francois Thibert <jeanfrancois@sagetv.com>
^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) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) * NOTES ABOUT THIS DRIVER
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) * This Linux driver supports:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) * B2C2/BBTI Technisat Air2PC - ATSC (NXT2002)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) * AverTVHD MCE A180 (NXT2004)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) * ATI HDTV Wonder (NXT2004)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) * This driver needs external firmware. Please use the command
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) * "<kerneldir>/scripts/get_dvb_firmware nxt2002" or
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) * "<kerneldir>/scripts/get_dvb_firmware nxt2004" to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) * download/extract the appropriate firmware, and then copy it to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) * /usr/lib/hotplug/firmware/ or /lib/firmware/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) * (depending on configuration of firmware hotplug).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) /* Max transfer size done by I2C transfer functions */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) #define MAX_XFER_SIZE 256
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) #define NXT2002_DEFAULT_FIRMWARE "dvb-fe-nxt2002.fw"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) #define NXT2004_DEFAULT_FIRMWARE "dvb-fe-nxt2004.fw"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) #define CRC_CCIT_MASK 0x1021
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) #include <linux/init.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) #include <linux/string.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) #include <media/dvb_frontend.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) #include "nxt200x.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) struct nxt200x_state {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) struct i2c_adapter* i2c;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) const struct nxt200x_config* config;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) struct dvb_frontend frontend;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) /* demodulator private data */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) nxt_chip_type demod_chip;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) u8 initialised:1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) static int debug;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) #define dprintk(args...) do { if (debug) pr_debug(args); } while (0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) static int i2c_writebytes (struct nxt200x_state* state, u8 addr, u8 *buf, u8 len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) struct i2c_msg msg = { .addr = addr, .flags = 0, .buf = buf, .len = len };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) if ((err = i2c_transfer (state->i2c, &msg, 1)) != 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) pr_warn("%s: i2c write error (addr 0x%02x, err == %i)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) __func__, addr, err);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) return -EREMOTEIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) static int i2c_readbytes(struct nxt200x_state *state, u8 addr, u8 *buf, u8 len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) struct i2c_msg msg = { .addr = addr, .flags = I2C_M_RD, .buf = buf, .len = len };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) if ((err = i2c_transfer (state->i2c, &msg, 1)) != 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) pr_warn("%s: i2c read error (addr 0x%02x, err == %i)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) __func__, addr, err);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) return -EREMOTEIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) static int nxt200x_writebytes (struct nxt200x_state* state, u8 reg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) const u8 *buf, u8 len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) u8 buf2[MAX_XFER_SIZE];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) struct i2c_msg msg = { .addr = state->config->demod_address, .flags = 0, .buf = buf2, .len = len + 1 };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) if (1 + len > sizeof(buf2)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) pr_warn("%s: i2c wr reg=%04x: len=%d is too big!\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) __func__, reg, len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) buf2[0] = reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) memcpy(&buf2[1], buf, len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) if ((err = i2c_transfer (state->i2c, &msg, 1)) != 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) pr_warn("%s: i2c write error (addr 0x%02x, err == %i)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) __func__, state->config->demod_address, err);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) return -EREMOTEIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) static int nxt200x_readbytes(struct nxt200x_state *state, u8 reg, u8 *buf, u8 len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) u8 reg2 [] = { reg };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) struct i2c_msg msg [] = { { .addr = state->config->demod_address, .flags = 0, .buf = reg2, .len = 1 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) { .addr = state->config->demod_address, .flags = I2C_M_RD, .buf = buf, .len = len } };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) if ((err = i2c_transfer (state->i2c, msg, 2)) != 2) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) pr_warn("%s: i2c read error (addr 0x%02x, err == %i)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) __func__, state->config->demod_address, err);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) return -EREMOTEIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) static u16 nxt200x_crc(u16 crc, u8 c)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) u8 i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) u16 input = (u16) c & 0xFF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) input<<=8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) for(i=0; i<8; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) if((crc^input) & 0x8000)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) crc=(crc<<1)^CRC_CCIT_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) crc<<=1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) input<<=1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) return crc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) static int nxt200x_writereg_multibyte (struct nxt200x_state* state, u8 reg, u8* data, u8 len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) u8 attr, len2, buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) dprintk("%s\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) /* set multi register register */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) nxt200x_writebytes(state, 0x35, ®, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) /* send the actual data */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) nxt200x_writebytes(state, 0x36, data, len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) switch (state->demod_chip) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) case NXT2002:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) len2 = len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) buf = 0x02;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) case NXT2004:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) /* probably not right, but gives correct values */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) attr = 0x02;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) if (reg & 0x80) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) attr = attr << 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) if (reg & 0x04)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) attr = attr >> 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) /* set write bit */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) len2 = ((attr << 4) | 0x10) | len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) buf = 0x80;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) /* set multi register length */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) nxt200x_writebytes(state, 0x34, &len2, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) /* toggle the multireg write bit */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) nxt200x_writebytes(state, 0x21, &buf, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) nxt200x_readbytes(state, 0x21, &buf, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) switch (state->demod_chip) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) case NXT2002:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) if ((buf & 0x02) == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) case NXT2004:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) if (buf == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) pr_warn("Error writing multireg register 0x%02X\n", reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197)
^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 nxt200x_readreg_multibyte (struct nxt200x_state* state, u8 reg, u8* data, u8 len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) u8 buf, len2, attr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) dprintk("%s\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) /* set multi register register */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) nxt200x_writebytes(state, 0x35, ®, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) switch (state->demod_chip) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) case NXT2002:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) /* set multi register length */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) len2 = len & 0x80;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) nxt200x_writebytes(state, 0x34, &len2, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) /* read the actual data */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) nxt200x_readbytes(state, reg, data, len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) case NXT2004:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) /* probably not right, but gives correct values */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) attr = 0x02;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) if (reg & 0x80) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) attr = attr << 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) if (reg & 0x04)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) attr = attr >> 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) /* set multi register length */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) len2 = (attr << 4) | len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) nxt200x_writebytes(state, 0x34, &len2, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) /* toggle the multireg bit*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) buf = 0x80;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) nxt200x_writebytes(state, 0x21, &buf, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) /* read the actual data */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) for(i = 0; i < len; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) nxt200x_readbytes(state, 0x36 + i, &data[i], 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) static void nxt200x_microcontroller_stop (struct nxt200x_state* state)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) u8 buf, stopval, counter = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) dprintk("%s\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) /* set correct stop value */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) switch (state->demod_chip) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) case NXT2002:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) stopval = 0x40;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) case NXT2004:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) stopval = 0x10;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) stopval = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) break;
^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) buf = 0x80;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) nxt200x_writebytes(state, 0x22, &buf, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) while (counter < 20) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) nxt200x_readbytes(state, 0x31, &buf, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) if (buf & stopval)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) msleep(10);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) counter++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) pr_warn("Timeout waiting for nxt200x to stop. This is ok after firmware upload.\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) static void nxt200x_microcontroller_start (struct nxt200x_state* state)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) u8 buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) dprintk("%s\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) buf = 0x00;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) nxt200x_writebytes(state, 0x22, &buf, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) static void nxt2004_microcontroller_init (struct nxt200x_state* state)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) u8 buf[9];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) u8 counter = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) dprintk("%s\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) buf[0] = 0x00;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) nxt200x_writebytes(state, 0x2b, buf, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) buf[0] = 0x70;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) nxt200x_writebytes(state, 0x34, buf, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) buf[0] = 0x04;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) nxt200x_writebytes(state, 0x35, buf, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) buf[0] = 0x01; buf[1] = 0x23; buf[2] = 0x45; buf[3] = 0x67; buf[4] = 0x89;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) buf[5] = 0xAB; buf[6] = 0xCD; buf[7] = 0xEF; buf[8] = 0xC0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) nxt200x_writebytes(state, 0x36, buf, 9);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) buf[0] = 0x80;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) nxt200x_writebytes(state, 0x21, buf, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) while (counter < 20) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) nxt200x_readbytes(state, 0x21, buf, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) if (buf[0] == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) msleep(10);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) counter++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) pr_warn("Timeout waiting for nxt2004 to init.\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) static int nxt200x_writetuner (struct nxt200x_state* state, u8* data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) u8 buf, count = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) dprintk("%s\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) dprintk("Tuner Bytes: %*ph\n", 4, data + 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) /* if NXT2004, write directly to tuner. if NXT2002, write through NXT chip.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) * direct write is required for Philips TUV1236D and ALPS TDHU2 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) switch (state->demod_chip) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) case NXT2004:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) if (i2c_writebytes(state, data[0], data+1, 4))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) pr_warn("error writing to tuner\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) /* wait until we have a lock */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) while (count < 20) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) i2c_readbytes(state, data[0], &buf, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) if (buf & 0x40)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) msleep(100);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) count++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) pr_warn("timeout waiting for tuner lock\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) case NXT2002:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) /* set the i2c transfer speed to the tuner */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) buf = 0x03;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) nxt200x_writebytes(state, 0x20, &buf, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) /* setup to transfer 4 bytes via i2c */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) buf = 0x04;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) nxt200x_writebytes(state, 0x34, &buf, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) /* write actual tuner bytes */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) nxt200x_writebytes(state, 0x36, data+1, 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) /* set tuner i2c address */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) buf = data[0] << 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) nxt200x_writebytes(state, 0x35, &buf, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) /* write UC Opmode to begin transfer */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) buf = 0x80;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) nxt200x_writebytes(state, 0x21, &buf, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) while (count < 20) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) nxt200x_readbytes(state, 0x21, &buf, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) if ((buf & 0x80)== 0x00)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) msleep(100);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) count++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) pr_warn("timeout error writing to tuner\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) static void nxt200x_agc_reset(struct nxt200x_state* state)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) u8 buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) dprintk("%s\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) switch (state->demod_chip) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) case NXT2002:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) buf = 0x08;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) nxt200x_writebytes(state, 0x08, &buf, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) buf = 0x00;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) nxt200x_writebytes(state, 0x08, &buf, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) case NXT2004:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) nxt200x_readreg_multibyte(state, 0x08, &buf, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) buf = 0x08;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) nxt200x_writereg_multibyte(state, 0x08, &buf, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) buf = 0x00;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) nxt200x_writereg_multibyte(state, 0x08, &buf, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) return;
^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) static int nxt2002_load_firmware (struct dvb_frontend* fe, const struct firmware *fw)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) struct nxt200x_state* state = fe->demodulator_priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) u8 buf[3], written = 0, chunkpos = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) u16 rambase, position, crc = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) dprintk("%s\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) dprintk("Firmware is %zu bytes\n", fw->size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) /* Get the RAM base for this nxt2002 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) nxt200x_readbytes(state, 0x10, buf, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) if (buf[0] & 0x10)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) rambase = 0x1000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) rambase = 0x0000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) dprintk("rambase on this nxt2002 is %04X\n", rambase);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) /* Hold the micro in reset while loading firmware */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) buf[0] = 0x80;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) nxt200x_writebytes(state, 0x2B, buf, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) for (position = 0; position < fw->size; position++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) if (written == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) crc = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) chunkpos = 0x28;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) buf[0] = ((rambase + position) >> 8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) buf[1] = (rambase + position) & 0xFF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) buf[2] = 0x81;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) /* write starting address */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) nxt200x_writebytes(state, 0x29, buf, 3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) written++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) chunkpos++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) if ((written % 4) == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) nxt200x_writebytes(state, chunkpos, &fw->data[position-3], 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) crc = nxt200x_crc(crc, fw->data[position]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) if ((written == 255) || (position+1 == fw->size)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) /* write remaining bytes of firmware */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) nxt200x_writebytes(state, chunkpos+4-(written %4),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) &fw->data[position-(written %4) + 1],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) written %4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) buf[0] = crc << 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) buf[1] = crc & 0xFF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) /* write crc */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) nxt200x_writebytes(state, 0x2C, buf, 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) /* do a read to stop things */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) nxt200x_readbytes(state, 0x2A, buf, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) /* set transfer mode to complete */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) buf[0] = 0x80;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) nxt200x_writebytes(state, 0x2B, buf, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) written = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) static int nxt2004_load_firmware (struct dvb_frontend* fe, const struct firmware *fw)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) struct nxt200x_state* state = fe->demodulator_priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) u8 buf[3];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) u16 rambase, position, crc=0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) dprintk("%s\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) dprintk("Firmware is %zu bytes\n", fw->size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) /* set rambase */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) rambase = 0x1000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) /* hold the micro in reset while loading firmware */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) buf[0] = 0x80;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) nxt200x_writebytes(state, 0x2B, buf,1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) /* calculate firmware CRC */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) for (position = 0; position < fw->size; position++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) crc = nxt200x_crc(crc, fw->data[position]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) buf[0] = rambase >> 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) buf[1] = rambase & 0xFF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) buf[2] = 0x81;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) /* write starting address */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) nxt200x_writebytes(state,0x29,buf,3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) for (position = 0; position < fw->size;) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) nxt200x_writebytes(state, 0x2C, &fw->data[position],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) fw->size-position > 255 ? 255 : fw->size-position);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) position += (fw->size-position > 255 ? 255 : fw->size-position);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) buf[0] = crc >> 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) buf[1] = crc & 0xFF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) dprintk("firmware crc is 0x%02X 0x%02X\n", buf[0], buf[1]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) /* write crc */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) nxt200x_writebytes(state, 0x2C, buf,2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) /* do a read to stop things */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) nxt200x_readbytes(state, 0x2C, buf, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) /* set transfer mode to complete */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) buf[0] = 0x80;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) nxt200x_writebytes(state, 0x2B, buf,1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) static int nxt200x_setup_frontend_parameters(struct dvb_frontend *fe)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) struct dtv_frontend_properties *p = &fe->dtv_property_cache;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) struct nxt200x_state* state = fe->demodulator_priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) u8 buf[5];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) /* stop the micro first */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) nxt200x_microcontroller_stop(state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) if (state->demod_chip == NXT2004) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) /* make sure demod is set to digital */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) buf[0] = 0x04;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) nxt200x_writebytes(state, 0x14, buf, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) buf[0] = 0x00;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) nxt200x_writebytes(state, 0x17, buf, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) /* set additional params */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) switch (p->modulation) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) case QAM_64:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) case QAM_256:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) /* Set punctured clock for QAM */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) /* This is just a guess since I am unable to test it */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) if (state->config->set_ts_params)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) state->config->set_ts_params(fe, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) case VSB_8:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) /* Set non-punctured clock for VSB */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) if (state->config->set_ts_params)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) state->config->set_ts_params(fe, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) if (fe->ops.tuner_ops.calc_regs) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) /* get tuning information */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) fe->ops.tuner_ops.calc_regs(fe, buf, 5);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) /* write frequency information */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) nxt200x_writetuner(state, buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) /* reset the agc now that tuning has been completed */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) nxt200x_agc_reset(state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) /* set target power level */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) switch (p->modulation) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) case QAM_64:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) case QAM_256:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) buf[0] = 0x74;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) case VSB_8:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) buf[0] = 0x70;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) nxt200x_writebytes(state, 0x42, buf, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) /* configure sdm */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) switch (state->demod_chip) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) case NXT2002:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) buf[0] = 0x87;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) case NXT2004:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) buf[0] = 0x07;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) nxt200x_writebytes(state, 0x57, buf, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) /* write sdm1 input */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) buf[0] = 0x10;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) buf[1] = 0x00;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) switch (state->demod_chip) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) case NXT2002:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) nxt200x_writereg_multibyte(state, 0x58, buf, 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) case NXT2004:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) nxt200x_writebytes(state, 0x58, buf, 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) /* write sdmx input */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) switch (p->modulation) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) case QAM_64:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) buf[0] = 0x68;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) case QAM_256:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) buf[0] = 0x64;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) case VSB_8:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) buf[0] = 0x60;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) buf[1] = 0x00;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) switch (state->demod_chip) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) case NXT2002:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) nxt200x_writereg_multibyte(state, 0x5C, buf, 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) case NXT2004:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) nxt200x_writebytes(state, 0x5C, buf, 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) /* write adc power lpf fc */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) buf[0] = 0x05;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) nxt200x_writebytes(state, 0x43, buf, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) if (state->demod_chip == NXT2004) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) /* write ??? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) buf[0] = 0x00;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) buf[1] = 0x00;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) nxt200x_writebytes(state, 0x46, buf, 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) /* write accumulator2 input */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) buf[0] = 0x80;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) buf[1] = 0x00;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) switch (state->demod_chip) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) case NXT2002:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) nxt200x_writereg_multibyte(state, 0x4B, buf, 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) case NXT2004:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) nxt200x_writebytes(state, 0x4B, buf, 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) /* write kg1 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) buf[0] = 0x00;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) nxt200x_writebytes(state, 0x4D, buf, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) /* write sdm12 lpf fc */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) buf[0] = 0x44;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) nxt200x_writebytes(state, 0x55, buf, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) /* write agc control reg */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) buf[0] = 0x04;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) nxt200x_writebytes(state, 0x41, buf, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) if (state->demod_chip == NXT2004) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) nxt200x_readreg_multibyte(state, 0x80, buf, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) buf[0] = 0x24;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) nxt200x_writereg_multibyte(state, 0x80, buf, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) /* soft reset? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) nxt200x_readreg_multibyte(state, 0x08, buf, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) buf[0] = 0x10;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) nxt200x_writereg_multibyte(state, 0x08, buf, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) nxt200x_readreg_multibyte(state, 0x08, buf, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) buf[0] = 0x00;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) nxt200x_writereg_multibyte(state, 0x08, buf, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) nxt200x_readreg_multibyte(state, 0x80, buf, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) buf[0] = 0x04;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) nxt200x_writereg_multibyte(state, 0x80, buf, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) buf[0] = 0x00;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) nxt200x_writereg_multibyte(state, 0x81, buf, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) buf[0] = 0x80; buf[1] = 0x00; buf[2] = 0x00;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) nxt200x_writereg_multibyte(state, 0x82, buf, 3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) nxt200x_readreg_multibyte(state, 0x88, buf, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) buf[0] = 0x11;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) nxt200x_writereg_multibyte(state, 0x88, buf, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) nxt200x_readreg_multibyte(state, 0x80, buf, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) buf[0] = 0x44;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) nxt200x_writereg_multibyte(state, 0x80, buf, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) /* write agc ucgp0 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711) switch (p->modulation) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) case QAM_64:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) buf[0] = 0x02;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) case QAM_256:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) buf[0] = 0x03;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) case VSB_8:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719) buf[0] = 0x00;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) nxt200x_writebytes(state, 0x30, buf, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727) /* write agc control reg */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) buf[0] = 0x00;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729) nxt200x_writebytes(state, 0x41, buf, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) /* write accumulator2 input */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732) buf[0] = 0x80;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733) buf[1] = 0x00;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) switch (state->demod_chip) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735) case NXT2002:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736) nxt200x_writereg_multibyte(state, 0x49, buf, 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) nxt200x_writereg_multibyte(state, 0x4B, buf, 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739) case NXT2004:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740) nxt200x_writebytes(state, 0x49, buf, 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741) nxt200x_writebytes(state, 0x4B, buf, 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748) /* write agc control reg */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) buf[0] = 0x04;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) nxt200x_writebytes(state, 0x41, buf, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752) nxt200x_microcontroller_start(state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754) if (state->demod_chip == NXT2004) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755) nxt2004_microcontroller_init(state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757) /* ???? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758) buf[0] = 0xF0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759) buf[1] = 0x00;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760) nxt200x_writebytes(state, 0x5C, buf, 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763) /* adjacent channel detection should be done here, but I don't
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764) have any stations with this need so I cannot test it */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769) static int nxt200x_read_status(struct dvb_frontend *fe, enum fe_status *status)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771) struct nxt200x_state* state = fe->demodulator_priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772) u8 lock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773) nxt200x_readbytes(state, 0x31, &lock, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775) *status = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776) if (lock & 0x20) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777) *status |= FE_HAS_SIGNAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778) *status |= FE_HAS_CARRIER;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779) *status |= FE_HAS_VITERBI;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780) *status |= FE_HAS_SYNC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781) *status |= FE_HAS_LOCK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786) static int nxt200x_read_ber(struct dvb_frontend* fe, u32* ber)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788) struct nxt200x_state* state = fe->demodulator_priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789) u8 b[3];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791) nxt200x_readreg_multibyte(state, 0xE6, b, 3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793) *ber = ((b[0] << 8) + b[1]) * 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798) static int nxt200x_read_signal_strength(struct dvb_frontend* fe, u16* strength)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800) struct nxt200x_state* state = fe->demodulator_priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801) u8 b[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802) u16 temp = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804) /* setup to read cluster variance */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805) b[0] = 0x00;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806) nxt200x_writebytes(state, 0xA1, b, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808) /* get multreg val */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809) nxt200x_readreg_multibyte(state, 0xA6, b, 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811) temp = (b[0] << 8) | b[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812) *strength = ((0x7FFF - temp) & 0x0FFF) * 16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817) static int nxt200x_read_snr(struct dvb_frontend* fe, u16* snr)
^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) struct nxt200x_state* state = fe->demodulator_priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821) u8 b[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822) u16 temp = 0, temp2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823) u32 snrdb = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825) /* setup to read cluster variance */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826) b[0] = 0x00;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827) nxt200x_writebytes(state, 0xA1, b, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829) /* get multreg val from 0xA6 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830) nxt200x_readreg_multibyte(state, 0xA6, b, 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832) temp = (b[0] << 8) | b[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833) temp2 = 0x7FFF - temp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835) /* snr will be in db */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836) if (temp2 > 0x7F00)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837) snrdb = 1000*24 + ( 1000*(30-24) * ( temp2 - 0x7F00 ) / ( 0x7FFF - 0x7F00 ) );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838) else if (temp2 > 0x7EC0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839) snrdb = 1000*18 + ( 1000*(24-18) * ( temp2 - 0x7EC0 ) / ( 0x7F00 - 0x7EC0 ) );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840) else if (temp2 > 0x7C00)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841) snrdb = 1000*12 + ( 1000*(18-12) * ( temp2 - 0x7C00 ) / ( 0x7EC0 - 0x7C00 ) );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843) snrdb = 1000*0 + ( 1000*(12-0) * ( temp2 - 0 ) / ( 0x7C00 - 0 ) );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845) /* the value reported back from the frontend will be FFFF=32db 0000=0db */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846) *snr = snrdb * (0xFFFF/32000);
^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 nxt200x_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 853) struct nxt200x_state* state = fe->demodulator_priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854) u8 b[3];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 855)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 856) nxt200x_readreg_multibyte(state, 0xE6, b, 3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 857) *ucblocks = b[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 858)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 859) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 860) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 861)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 862) static int nxt200x_sleep(struct dvb_frontend* fe)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 863) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 864) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 865) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 866)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 867) static int nxt2002_init(struct dvb_frontend* fe)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 868) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 869) struct nxt200x_state* state = fe->demodulator_priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 870) const struct firmware *fw;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 871) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 872) u8 buf[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 873)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 874) /* request the firmware, this will block until someone uploads it */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 875) pr_debug("%s: Waiting for firmware upload (%s)...\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 876) __func__, NXT2002_DEFAULT_FIRMWARE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 877) ret = request_firmware(&fw, NXT2002_DEFAULT_FIRMWARE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 878) state->i2c->dev.parent);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 879) pr_debug("%s: Waiting for firmware upload(2)...\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 880) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 881) pr_err("%s: No firmware uploaded (timeout or file not found?)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 882) __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 883) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 884) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 885)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 886) ret = nxt2002_load_firmware(fe, fw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 887) release_firmware(fw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 888) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 889) pr_err("%s: Writing firmware to device failed\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 890) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 891) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 892) pr_info("%s: Firmware upload complete\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 893)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 894) /* Put the micro into reset */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 895) nxt200x_microcontroller_stop(state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 896)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 897) /* ensure transfer is complete */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 898) buf[0]=0x00;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 899) nxt200x_writebytes(state, 0x2B, buf, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 900)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 901) /* Put the micro into reset for real this time */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 902) nxt200x_microcontroller_stop(state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 903)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 904) /* soft reset everything (agc,frontend,eq,fec)*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 905) buf[0] = 0x0F;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 906) nxt200x_writebytes(state, 0x08, buf, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 907) buf[0] = 0x00;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 908) nxt200x_writebytes(state, 0x08, buf, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 909)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 910) /* write agc sdm configure */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 911) buf[0] = 0xF1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 912) nxt200x_writebytes(state, 0x57, buf, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 913)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 914) /* write mod output format */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 915) buf[0] = 0x20;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 916) nxt200x_writebytes(state, 0x09, buf, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 917)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 918) /* write fec mpeg mode */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 919) buf[0] = 0x7E;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 920) buf[1] = 0x00;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 921) nxt200x_writebytes(state, 0xE9, buf, 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 922)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 923) /* write mux selection */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 924) buf[0] = 0x00;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 925) nxt200x_writebytes(state, 0xCC, buf, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 926)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 927) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 928) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 929)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 930) static int nxt2004_init(struct dvb_frontend* fe)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 931) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 932) struct nxt200x_state* state = fe->demodulator_priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 933) const struct firmware *fw;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 934) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 935) u8 buf[3];
^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) buf[0]=0x00;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 939) nxt200x_writebytes(state, 0x1E, buf, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 940)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 941) /* request the firmware, this will block until someone uploads it */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 942) pr_debug("%s: Waiting for firmware upload (%s)...\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 943) __func__, NXT2004_DEFAULT_FIRMWARE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 944) ret = request_firmware(&fw, NXT2004_DEFAULT_FIRMWARE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 945) state->i2c->dev.parent);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 946) pr_debug("%s: Waiting for firmware upload(2)...\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 947) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 948) pr_err("%s: No firmware uploaded (timeout or file not found?)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 949) __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 950) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 951) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 952)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 953) ret = nxt2004_load_firmware(fe, fw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 954) release_firmware(fw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 955) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 956) pr_err("%s: Writing firmware to device failed\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 957) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 958) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 959) pr_info("%s: Firmware upload complete\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 960)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 961) /* ensure transfer is complete */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 962) buf[0] = 0x01;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 963) nxt200x_writebytes(state, 0x19, buf, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 964)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 965) nxt2004_microcontroller_init(state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 966) nxt200x_microcontroller_stop(state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 967) nxt200x_microcontroller_stop(state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 968) nxt2004_microcontroller_init(state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 969) nxt200x_microcontroller_stop(state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 970)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 971) /* soft reset everything (agc,frontend,eq,fec)*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 972) buf[0] = 0xFF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 973) nxt200x_writereg_multibyte(state, 0x08, buf, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 974) buf[0] = 0x00;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 975) nxt200x_writereg_multibyte(state, 0x08, buf, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 976)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 977) /* write agc sdm configure */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 978) buf[0] = 0xD7;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 979) nxt200x_writebytes(state, 0x57, buf, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 980)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 981) /* ???*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 982) buf[0] = 0x07;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 983) buf[1] = 0xfe;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 984) nxt200x_writebytes(state, 0x35, buf, 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 985) buf[0] = 0x12;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 986) nxt200x_writebytes(state, 0x34, buf, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 987) buf[0] = 0x80;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 988) nxt200x_writebytes(state, 0x21, buf, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 989)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 990) /* ???*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 991) buf[0] = 0x21;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 992) nxt200x_writebytes(state, 0x0A, buf, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 993)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 994) /* ???*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 995) buf[0] = 0x01;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 996) nxt200x_writereg_multibyte(state, 0x80, buf, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 997)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 998) /* write fec mpeg mode */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 999) buf[0] = 0x7E;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1000) buf[1] = 0x00;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1001) nxt200x_writebytes(state, 0xE9, buf, 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1002)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1003) /* write mux selection */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1004) buf[0] = 0x00;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1005) nxt200x_writebytes(state, 0xCC, buf, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1006)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1007) /* ???*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1008) nxt200x_readreg_multibyte(state, 0x80, buf, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1009) buf[0] = 0x00;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1010) nxt200x_writereg_multibyte(state, 0x80, buf, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1011)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1012) /* soft reset? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1013) nxt200x_readreg_multibyte(state, 0x08, buf, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1014) buf[0] = 0x10;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1015) nxt200x_writereg_multibyte(state, 0x08, buf, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1016) nxt200x_readreg_multibyte(state, 0x08, buf, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1017) buf[0] = 0x00;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1018) nxt200x_writereg_multibyte(state, 0x08, buf, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1019)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1020) /* ???*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1021) nxt200x_readreg_multibyte(state, 0x80, buf, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1022) buf[0] = 0x01;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1023) nxt200x_writereg_multibyte(state, 0x80, buf, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1024) buf[0] = 0x70;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1025) nxt200x_writereg_multibyte(state, 0x81, buf, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1026) buf[0] = 0x31; buf[1] = 0x5E; buf[2] = 0x66;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1027) nxt200x_writereg_multibyte(state, 0x82, buf, 3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1028)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1029) nxt200x_readreg_multibyte(state, 0x88, buf, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1030) buf[0] = 0x11;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1031) nxt200x_writereg_multibyte(state, 0x88, buf, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1032) nxt200x_readreg_multibyte(state, 0x80, buf, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1033) buf[0] = 0x40;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1034) nxt200x_writereg_multibyte(state, 0x80, buf, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1035)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1036) nxt200x_readbytes(state, 0x10, buf, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1037) buf[0] = 0x10;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1038) nxt200x_writebytes(state, 0x10, buf, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1039) nxt200x_readbytes(state, 0x0A, buf, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1040) buf[0] = 0x21;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1041) nxt200x_writebytes(state, 0x0A, buf, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1042)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1043) nxt2004_microcontroller_init(state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1044)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1045) buf[0] = 0x21;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1046) nxt200x_writebytes(state, 0x0A, buf, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1047) buf[0] = 0x7E;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1048) nxt200x_writebytes(state, 0xE9, buf, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1049) buf[0] = 0x00;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1050) nxt200x_writebytes(state, 0xEA, buf, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1051)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1052) nxt200x_readreg_multibyte(state, 0x80, buf, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1053) buf[0] = 0x00;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1054) nxt200x_writereg_multibyte(state, 0x80, buf, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1055) nxt200x_readreg_multibyte(state, 0x80, buf, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1056) buf[0] = 0x00;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1057) nxt200x_writereg_multibyte(state, 0x80, buf, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1058)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1059) /* soft reset? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1060) nxt200x_readreg_multibyte(state, 0x08, buf, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1061) buf[0] = 0x10;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1062) nxt200x_writereg_multibyte(state, 0x08, buf, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1063) nxt200x_readreg_multibyte(state, 0x08, buf, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1064) buf[0] = 0x00;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1065) nxt200x_writereg_multibyte(state, 0x08, buf, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1066)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1067) nxt200x_readreg_multibyte(state, 0x80, buf, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1068) buf[0] = 0x04;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1069) nxt200x_writereg_multibyte(state, 0x80, buf, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1070) buf[0] = 0x00;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1071) nxt200x_writereg_multibyte(state, 0x81, buf, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1072) buf[0] = 0x80; buf[1] = 0x00; buf[2] = 0x00;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1073) nxt200x_writereg_multibyte(state, 0x82, buf, 3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1074)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1075) nxt200x_readreg_multibyte(state, 0x88, buf, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1076) buf[0] = 0x11;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1077) nxt200x_writereg_multibyte(state, 0x88, buf, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1078)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1079) nxt200x_readreg_multibyte(state, 0x80, buf, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1080) buf[0] = 0x44;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1081) nxt200x_writereg_multibyte(state, 0x80, buf, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1082)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1083) /* initialize tuner */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1084) nxt200x_readbytes(state, 0x10, buf, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1085) buf[0] = 0x12;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1086) nxt200x_writebytes(state, 0x10, buf, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1087) buf[0] = 0x04;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1088) nxt200x_writebytes(state, 0x13, buf, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1089) buf[0] = 0x00;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1090) nxt200x_writebytes(state, 0x16, buf, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1091) buf[0] = 0x04;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1092) nxt200x_writebytes(state, 0x14, buf, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1093) buf[0] = 0x00;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1094) nxt200x_writebytes(state, 0x14, buf, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1095) nxt200x_writebytes(state, 0x17, buf, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1096) nxt200x_writebytes(state, 0x14, buf, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1097) nxt200x_writebytes(state, 0x17, buf, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1098)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1099) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1100) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1101)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1102) static int nxt200x_init(struct dvb_frontend* fe)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1103) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1104) struct nxt200x_state* state = fe->demodulator_priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1105) int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1106)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1107) if (!state->initialised) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1108) switch (state->demod_chip) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1109) case NXT2002:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1110) ret = nxt2002_init(fe);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1111) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1112) case NXT2004:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1113) ret = nxt2004_init(fe);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1114) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1115) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1116) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1117) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1118) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1119) state->initialised = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1120) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1121) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1122) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1123)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1124) static int nxt200x_get_tune_settings(struct dvb_frontend* fe, struct dvb_frontend_tune_settings* fesettings)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1125) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1126) fesettings->min_delay_ms = 500;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1127) fesettings->step_size = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1128) fesettings->max_drift = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1129) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1130) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1131)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1132) static void nxt200x_release(struct dvb_frontend* fe)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1133) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1134) struct nxt200x_state* state = fe->demodulator_priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1135) kfree(state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1136) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1137)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1138) static const struct dvb_frontend_ops nxt200x_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1139)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1140) struct dvb_frontend* nxt200x_attach(const struct nxt200x_config* config,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1141) struct i2c_adapter* i2c)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1142) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1143) struct nxt200x_state* state = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1144) u8 buf [] = {0,0,0,0,0};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1145)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1146) /* allocate memory for the internal state */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1147) state = kzalloc(sizeof(struct nxt200x_state), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1148) if (state == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1149) goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1150)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1151) /* setup the state */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1152) state->config = config;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1153) state->i2c = i2c;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1154) state->initialised = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1155)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1156) /* read card id */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1157) nxt200x_readbytes(state, 0x00, buf, 5);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1158) dprintk("NXT info: %*ph\n", 5, buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1159)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1160) /* set demod chip */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1161) switch (buf[0]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1162) case 0x04:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1163) state->demod_chip = NXT2002;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1164) pr_info("NXT2002 Detected\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1165) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1166) case 0x05:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1167) state->demod_chip = NXT2004;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1168) pr_info("NXT2004 Detected\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1169) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1170) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1171) goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1172) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1173)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1174) /* make sure demod chip is supported */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1175) switch (state->demod_chip) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1176) case NXT2002:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1177) if (buf[0] != 0x04) goto error; /* device id */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1178) if (buf[1] != 0x02) goto error; /* fab id */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1179) if (buf[2] != 0x11) goto error; /* month */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1180) if (buf[3] != 0x20) goto error; /* year msb */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1181) if (buf[4] != 0x00) goto error; /* year lsb */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1182) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1183) case NXT2004:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1184) if (buf[0] != 0x05) goto error; /* device id */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1185) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1186) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1187) goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1188) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1189)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1190) /* create dvb_frontend */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1191) memcpy(&state->frontend.ops, &nxt200x_ops, sizeof(struct dvb_frontend_ops));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1192) state->frontend.demodulator_priv = state;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1193) return &state->frontend;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1194)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1195) error:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1196) kfree(state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1197) pr_err("Unknown/Unsupported NXT chip: %*ph\n", 5, buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1198) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1199) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1200)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1201) static const struct dvb_frontend_ops nxt200x_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1202) .delsys = { SYS_ATSC, SYS_DVBC_ANNEX_B },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1203) .info = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1204) .name = "Nextwave NXT200X VSB/QAM frontend",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1205) .frequency_min_hz = 54 * MHz,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1206) .frequency_max_hz = 860 * MHz,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1207) .frequency_stepsize_hz = 166666, /* stepsize is just a guess */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1208) .caps = FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1209) FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1210) FE_CAN_8VSB | FE_CAN_QAM_64 | FE_CAN_QAM_256
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1211) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1212)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1213) .release = nxt200x_release,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1214)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1215) .init = nxt200x_init,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1216) .sleep = nxt200x_sleep,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1217)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1218) .set_frontend = nxt200x_setup_frontend_parameters,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1219) .get_tune_settings = nxt200x_get_tune_settings,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1220)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1221) .read_status = nxt200x_read_status,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1222) .read_ber = nxt200x_read_ber,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1223) .read_signal_strength = nxt200x_read_signal_strength,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1224) .read_snr = nxt200x_read_snr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1225) .read_ucblocks = nxt200x_read_ucblocks,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1226) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1227)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1228) module_param(debug, int, 0644);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1229) MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off).");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1230)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1231) MODULE_DESCRIPTION("NXT200X (ATSC 8VSB & ITU-T J.83 AnnexB 64/256 QAM) Demodulator Driver");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1232) MODULE_AUTHOR("Kirk Lapray, Michael Krufky, Jean-Francois Thibert, and Taylor Jacob");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1233) MODULE_LICENSE("GPL");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1234)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1235) EXPORT_SYMBOL(nxt200x_attach);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1236)