^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) * Support for the Broadcom BCM3510 ATSC demodulator (1st generation Air2PC)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) * Copyright (C) 2001-5, B2C2 inc.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * GPL/Linux driver written by Patrick Boettcher <patrick.boettcher@posteo.de>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * This driver is "hard-coded" to be used with the 1st generation of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) * Technisat/B2C2's Air2PC ATSC PCI/USB cards/boxes. The pll-programming
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) * (Panasonic CT10S) is located here, which is actually wrong. Unless there is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) * another device with a BCM3510, this is no problem.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) * The driver works also with QAM64 DVB-C, but had an unreasonable high
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) * UNC. (Tested with the Air2PC ATSC 1st generation)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) * You'll need a firmware for this driver in order to get it running. It is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) * called "dvb-fe-bcm3510-01.fw".
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) * This program is free software; you can redistribute it and/or modify it
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) * under the terms of the GNU General Public License as published by the Free
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) * Software Foundation; either version 2 of the License, or (at your option)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) * any later version.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) * This program is distributed in the hope that it will be useful, but WITHOUT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) * more details.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) * You should have received a copy of the GNU General Public License along with
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) * this program; if not, write to the Free Software Foundation, Inc., 675 Mass
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) * Ave, Cambridge, MA 02139, USA.
^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) #include <linux/init.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) #include <linux/device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) #include <linux/firmware.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) #include <linux/jiffies.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) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) #include <linux/mutex.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) #include <media/dvb_frontend.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) #include "bcm3510.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) #include "bcm3510_priv.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) /* Max transfer size done by bcm3510_do_hab_cmd() function */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) #define MAX_XFER_SIZE 128
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) struct bcm3510_state {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) struct i2c_adapter* i2c;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) const struct bcm3510_config* config;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) struct dvb_frontend frontend;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) /* demodulator private data */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) struct mutex hab_mutex;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) u8 firmware_loaded:1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) unsigned long next_status_check;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) unsigned long status_check_interval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) struct bcm3510_hab_cmd_status1 status1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) struct bcm3510_hab_cmd_status2 status2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) static int debug;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) module_param(debug, int, 0644);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) MODULE_PARM_DESC(debug, "set debugging level (1=info,2=i2c (|-able)).");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) #define dprintk(level,x...) if (level & debug) printk(x)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) #define dbufout(b,l,m) {\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) int i; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) for (i = 0; i < l; i++) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) m("%02x ",b[i]); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) #define deb_info(args...) dprintk(0x01,args)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) #define deb_i2c(args...) dprintk(0x02,args)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) #define deb_hab(args...) dprintk(0x04,args)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) /* transfer functions */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) static int bcm3510_writebytes (struct bcm3510_state *state, u8 reg, u8 *buf, u8 len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) u8 b[256];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) struct i2c_msg msg = { .addr = state->config->demod_address, .flags = 0, .buf = b, .len = len + 1 };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) b[0] = reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) memcpy(&b[1],buf,len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) deb_i2c("i2c wr %02x: ",reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) dbufout(buf,len,deb_i2c);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) deb_i2c("\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) if ((err = i2c_transfer (state->i2c, &msg, 1)) != 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) deb_info("%s: i2c write error (addr %02x, reg %02x, err == %i)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) __func__, state->config->demod_address, reg, err);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) return -EREMOTEIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) static int bcm3510_readbytes (struct bcm3510_state *state, u8 reg, u8 *buf, u8 len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) struct i2c_msg msg[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) { .addr = state->config->demod_address, .flags = 0, .buf = ®, .len = 1 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) { .addr = state->config->demod_address, .flags = I2C_M_RD, .buf = buf, .len = len }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) memset(buf,0,len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) if ((err = i2c_transfer (state->i2c, msg, 2)) != 2) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) deb_info("%s: i2c read error (addr %02x, reg %02x, err == %i)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) __func__, state->config->demod_address, reg, err);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) return -EREMOTEIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) deb_i2c("i2c rd %02x: ",reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) dbufout(buf,len,deb_i2c);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) deb_i2c("\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) static int bcm3510_writeB(struct bcm3510_state *state, u8 reg, bcm3510_register_value v)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) return bcm3510_writebytes(state,reg,&v.raw,1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) static int bcm3510_readB(struct bcm3510_state *state, u8 reg, bcm3510_register_value *v)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) return bcm3510_readbytes(state,reg,&v->raw,1);
^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) /* Host Access Buffer transfers */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) static int bcm3510_hab_get_response(struct bcm3510_state *st, u8 *buf, int len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) bcm3510_register_value v;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) int ret,i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) v.HABADR_a6.HABADR = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) if ((ret = bcm3510_writeB(st,0xa6,v)) < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) for (i = 0; i < len; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) if ((ret = bcm3510_readB(st,0xa7,&v)) < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) buf[i] = v.HABDATA_a7;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) return 0;
^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 bcm3510_hab_send_request(struct bcm3510_state *st, u8 *buf, int len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) bcm3510_register_value v,hab;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) int ret,i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) unsigned long t;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) /* Check if any previous HAB request still needs to be serviced by the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) * Acquisition Processor before sending new request */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) if ((ret = bcm3510_readB(st,0xa8,&v)) < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) if (v.HABSTAT_a8.HABR) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) deb_info("HAB is running already - clearing it.\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) v.HABSTAT_a8.HABR = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) bcm3510_writeB(st,0xa8,v);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) // return -EBUSY;
^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) /* Send the start HAB Address (automatically incremented after write of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) * HABDATA) and write the HAB Data */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) hab.HABADR_a6.HABADR = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) if ((ret = bcm3510_writeB(st,0xa6,hab)) < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) for (i = 0; i < len; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) hab.HABDATA_a7 = buf[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) if ((ret = bcm3510_writeB(st,0xa7,hab)) < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) /* Set the HABR bit to indicate AP request in progress (LBHABR allows HABR to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) * be written) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) v.raw = 0; v.HABSTAT_a8.HABR = 1; v.HABSTAT_a8.LDHABR = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) if ((ret = bcm3510_writeB(st,0xa8,v)) < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) /* Polling method: Wait until the AP finishes processing the HAB request */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) t = jiffies + 1*HZ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) while (time_before(jiffies, t)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) deb_info("waiting for HAB to complete\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) msleep(10);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) if ((ret = bcm3510_readB(st,0xa8,&v)) < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) if (!v.HABSTAT_a8.HABR)
^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) deb_info("send_request execution timed out.\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) return -ETIMEDOUT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) static int bcm3510_do_hab_cmd(struct bcm3510_state *st, u8 cmd, u8 msgid, u8 *obuf, u8 olen, u8 *ibuf, u8 ilen)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) u8 ob[MAX_XFER_SIZE], ib[MAX_XFER_SIZE];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) if (ilen + 2 > sizeof(ib)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) deb_hab("do_hab_cmd: ilen=%d is too big!\n", ilen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) if (olen + 2 > sizeof(ob)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) deb_hab("do_hab_cmd: olen=%d is too big!\n", olen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) ob[0] = cmd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) ob[1] = msgid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) memcpy(&ob[2],obuf,olen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) deb_hab("hab snd: ");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) dbufout(ob,olen+2,deb_hab);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) deb_hab("\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) if (mutex_lock_interruptible(&st->hab_mutex) < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) return -EAGAIN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) if ((ret = bcm3510_hab_send_request(st, ob, olen+2)) < 0 ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) (ret = bcm3510_hab_get_response(st, ib, ilen+2)) < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) deb_hab("hab get: ");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) dbufout(ib,ilen+2,deb_hab);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) deb_hab("\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) memcpy(ibuf,&ib[2],ilen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) error:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) mutex_unlock(&st->hab_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) #if 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) /* not needed, we use a semaphore to prevent HAB races */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) static int bcm3510_is_ap_ready(struct bcm3510_state *st)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) bcm3510_register_value ap,hab;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) if ((ret = bcm3510_readB(st,0xa8,&hab)) < 0 ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) (ret = bcm3510_readB(st,0xa2,&ap) < 0))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) if (ap.APSTAT1_a2.RESET || ap.APSTAT1_a2.IDLE || ap.APSTAT1_a2.STOP || hab.HABSTAT_a8.HABR) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) deb_info("AP is busy\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) return -EBUSY;
^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) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) static int bcm3510_bert_reset(struct bcm3510_state *st)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) bcm3510_register_value b;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) if ((ret = bcm3510_readB(st,0xfa,&b)) < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) b.BERCTL_fa.RESYNC = 0; bcm3510_writeB(st,0xfa,b);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) b.BERCTL_fa.RESYNC = 1; bcm3510_writeB(st,0xfa,b);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) b.BERCTL_fa.RESYNC = 0; bcm3510_writeB(st,0xfa,b);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) b.BERCTL_fa.CNTCTL = 1; b.BERCTL_fa.BITCNT = 1; bcm3510_writeB(st,0xfa,b);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) /* clear residual bit counter TODO */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) return 0;
^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 int bcm3510_refresh_state(struct bcm3510_state *st)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) if (time_after(jiffies,st->next_status_check)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) bcm3510_do_hab_cmd(st, CMD_STATUS, MSGID_STATUS1, NULL,0, (u8 *)&st->status1, sizeof(st->status1));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) bcm3510_do_hab_cmd(st, CMD_STATUS, MSGID_STATUS2, NULL,0, (u8 *)&st->status2, sizeof(st->status2));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) st->next_status_check = jiffies + (st->status_check_interval*HZ)/1000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) static int bcm3510_read_status(struct dvb_frontend *fe, enum fe_status *status)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) struct bcm3510_state* st = fe->demodulator_priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) bcm3510_refresh_state(st);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) *status = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) if (st->status1.STATUS1.RECEIVER_LOCK)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) *status |= FE_HAS_LOCK | FE_HAS_SYNC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) if (st->status1.STATUS1.FEC_LOCK)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) *status |= FE_HAS_VITERBI;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) if (st->status1.STATUS1.OUT_PLL_LOCK)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) *status |= FE_HAS_SIGNAL | FE_HAS_CARRIER;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) if (*status & FE_HAS_LOCK)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) st->status_check_interval = 1500;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) else /* more frequently checks if no lock has been achieved yet */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) st->status_check_interval = 500;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) deb_info("real_status: %02x\n",*status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) return 0;
^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) static int bcm3510_read_ber(struct dvb_frontend* fe, u32* ber)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) struct bcm3510_state* st = fe->demodulator_priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) bcm3510_refresh_state(st);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) *ber = (st->status2.LDBER0 << 16) | (st->status2.LDBER1 << 8) | st->status2.LDBER2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) static int bcm3510_read_unc(struct dvb_frontend* fe, u32* unc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) struct bcm3510_state* st = fe->demodulator_priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) bcm3510_refresh_state(st);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) *unc = (st->status2.LDUERC0 << 8) | st->status2.LDUERC1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) static int bcm3510_read_signal_strength(struct dvb_frontend* fe, u16* strength)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) struct bcm3510_state* st = fe->demodulator_priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) s32 t;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) bcm3510_refresh_state(st);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) t = st->status2.SIGNAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) if (t > 190)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) t = 190;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) if (t < 90)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) t = 90;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) t -= 90;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) t = t * 0xff / 100;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) /* normalize if necessary */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) *strength = (t << 8) | t;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) static int bcm3510_read_snr(struct dvb_frontend* fe, u16* snr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) struct bcm3510_state* st = fe->demodulator_priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) bcm3510_refresh_state(st);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) *snr = st->status1.SNR_EST0*1000 + ((st->status1.SNR_EST1*1000) >> 8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) /* tuner frontend programming */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) static int bcm3510_tuner_cmd(struct bcm3510_state* st,u8 bc, u16 n, u8 a)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) struct bcm3510_hab_cmd_tune c;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) memset(&c,0,sizeof(struct bcm3510_hab_cmd_tune));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) /* I2C Mode disabled, set 16 control / Data pairs */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) c.length = 0x10;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) c.clock_width = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) /* CS1, CS0, DATA, CLK bits control the tuner RF_AGC_SEL pin is set to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) * logic high (as Configuration) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) c.misc = 0x10;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) /* Set duration of the initial state of TUNCTL = 3.34 micro Sec */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) c.TUNCTL_state = 0x40;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) /* PRESCALER DIVIDE RATIO | BC1_2_3_4; (band switch), 1stosc REFERENCE COUNTER REF_S12 and REF_S11 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) c.ctl_dat[0].ctrl.size = BITS_8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) c.ctl_dat[0].data = 0x80 | bc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) /* Control DATA pin, 1stosc REFERENCE COUNTER REF_S10 to REF_S3 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) c.ctl_dat[1].ctrl.size = BITS_8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) c.ctl_dat[1].data = 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) /* set CONTROL BIT 1 to 1, 1stosc REFERENCE COUNTER REF_S2 to REF_S1 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) c.ctl_dat[2].ctrl.size = BITS_3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) c.ctl_dat[2].data = 0x20;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) /* control CS0 pin, pulse byte ? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) c.ctl_dat[3].ctrl.size = BITS_3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) c.ctl_dat[3].ctrl.clk_off = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) c.ctl_dat[3].ctrl.cs0 = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) c.ctl_dat[3].data = 0x40;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) /* PGM_S18 to PGM_S11 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) c.ctl_dat[4].ctrl.size = BITS_8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) c.ctl_dat[4].data = n >> 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) /* PGM_S10 to PGM_S8, SWL_S7 to SWL_S3 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) c.ctl_dat[5].ctrl.size = BITS_8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) c.ctl_dat[5].data = ((n & 0x7) << 5) | (a >> 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) /* SWL_S2 and SWL_S1, set CONTROL BIT 2 to 0 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) c.ctl_dat[6].ctrl.size = BITS_3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) c.ctl_dat[6].data = (a << 6) & 0xdf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) /* control CS0 pin, pulse byte ? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) c.ctl_dat[7].ctrl.size = BITS_3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) c.ctl_dat[7].ctrl.clk_off = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) c.ctl_dat[7].ctrl.cs0 = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) c.ctl_dat[7].data = 0x40;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) /* PRESCALER DIVIDE RATIO, 2ndosc REFERENCE COUNTER REF_S12 and REF_S11 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) c.ctl_dat[8].ctrl.size = BITS_8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) c.ctl_dat[8].data = 0x80;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) /* 2ndosc REFERENCE COUNTER REF_S10 to REF_S3 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) c.ctl_dat[9].ctrl.size = BITS_8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) c.ctl_dat[9].data = 0x10;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) /* set CONTROL BIT 1 to 1, 2ndosc REFERENCE COUNTER REF_S2 to REF_S1 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) c.ctl_dat[10].ctrl.size = BITS_3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) c.ctl_dat[10].data = 0x20;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) /* pulse byte */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) c.ctl_dat[11].ctrl.size = BITS_3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) c.ctl_dat[11].ctrl.clk_off = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) c.ctl_dat[11].ctrl.cs1 = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) c.ctl_dat[11].data = 0x40;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) /* PGM_S18 to PGM_S11 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) c.ctl_dat[12].ctrl.size = BITS_8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) c.ctl_dat[12].data = 0x2a;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) /* PGM_S10 to PGM_S8 and SWL_S7 to SWL_S3 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) c.ctl_dat[13].ctrl.size = BITS_8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) c.ctl_dat[13].data = 0x8e;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) /* SWL_S2 and SWL_S1 and set CONTROL BIT 2 to 0 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) c.ctl_dat[14].ctrl.size = BITS_3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) c.ctl_dat[14].data = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) /* Pulse Byte */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) c.ctl_dat[15].ctrl.size = BITS_3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) c.ctl_dat[15].ctrl.clk_off = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) c.ctl_dat[15].ctrl.cs1 = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) c.ctl_dat[15].data = 0x40;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) return bcm3510_do_hab_cmd(st,CMD_TUNE, MSGID_TUNE,(u8 *) &c,sizeof(c), NULL, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) static int bcm3510_set_freq(struct bcm3510_state* st,u32 freq)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) u8 bc,a;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) u16 n;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) s32 YIntercept,Tfvco1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) freq /= 1000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) deb_info("%dkHz:",freq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) /* set Band Switch */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) if (freq <= 168000)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) bc = 0x1c;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) else if (freq <= 378000)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) bc = 0x2c;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) bc = 0x30;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) if (freq >= 470000) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) freq -= 470001;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) YIntercept = 18805;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) } else if (freq >= 90000) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) freq -= 90001;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) YIntercept = 15005;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) } else if (freq >= 76000){
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) freq -= 76001;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) YIntercept = 14865;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) freq -= 54001;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) YIntercept = 14645;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) Tfvco1 = (((freq/6000)*60 + YIntercept)*4)/10;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) n = Tfvco1 >> 6;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) a = Tfvco1 & 0x3f;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) deb_info(" BC1_2_3_4: %x, N: %x A: %x\n", bc, n, a);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) if (n >= 16 && n <= 2047)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) return bcm3510_tuner_cmd(st,bc,n,a);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) static int bcm3510_set_frontend(struct dvb_frontend *fe)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) struct dtv_frontend_properties *c = &fe->dtv_property_cache;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) struct bcm3510_state* st = fe->demodulator_priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) struct bcm3510_hab_cmd_ext_acquire cmd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) struct bcm3510_hab_cmd_bert_control bert;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) memset(&cmd,0,sizeof(cmd));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) switch (c->modulation) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) case QAM_256:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) cmd.ACQUIRE0.MODE = 0x1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) cmd.ACQUIRE1.SYM_RATE = 0x1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) cmd.ACQUIRE1.IF_FREQ = 0x1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) case QAM_64:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) cmd.ACQUIRE0.MODE = 0x2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) cmd.ACQUIRE1.SYM_RATE = 0x2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) cmd.ACQUIRE1.IF_FREQ = 0x1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) #if 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) case QAM_256:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) cmd.ACQUIRE0.MODE = 0x3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) case QAM_128:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) cmd.ACQUIRE0.MODE = 0x4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) case QAM_64:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) cmd.ACQUIRE0.MODE = 0x5;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) case QAM_32:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) cmd.ACQUIRE0.MODE = 0x6;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) case QAM_16:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) cmd.ACQUIRE0.MODE = 0x7;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) case VSB_8:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) cmd.ACQUIRE0.MODE = 0x8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) cmd.ACQUIRE1.SYM_RATE = 0x0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) cmd.ACQUIRE1.IF_FREQ = 0x0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) case VSB_16:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) cmd.ACQUIRE0.MODE = 0x9;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) cmd.ACQUIRE1.SYM_RATE = 0x0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) cmd.ACQUIRE1.IF_FREQ = 0x0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) cmd.ACQUIRE0.OFFSET = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) cmd.ACQUIRE0.NTSCSWEEP = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) cmd.ACQUIRE0.FA = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) cmd.ACQUIRE0.BW = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) /* if (enableOffset) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) cmd.IF_OFFSET0 = xx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) cmd.IF_OFFSET1 = xx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) cmd.SYM_OFFSET0 = xx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) cmd.SYM_OFFSET1 = xx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) if (enableNtscSweep) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) cmd.NTSC_OFFSET0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) cmd.NTSC_OFFSET1;
^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) bcm3510_do_hab_cmd(st, CMD_ACQUIRE, MSGID_EXT_TUNER_ACQUIRE, (u8 *) &cmd, sizeof(cmd), NULL, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) /* doing it with different MSGIDs, data book and source differs */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) bert.BE = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) bert.unused = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) bcm3510_do_hab_cmd(st, CMD_STATE_CONTROL, MSGID_BERT_CONTROL, (u8 *) &bert, sizeof(bert), NULL, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) bcm3510_do_hab_cmd(st, CMD_STATE_CONTROL, MSGID_BERT_SET, (u8 *) &bert, sizeof(bert), NULL, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) bcm3510_bert_reset(st);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) ret = bcm3510_set_freq(st, c->frequency);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) memset(&st->status1,0,sizeof(st->status1));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) memset(&st->status2,0,sizeof(st->status2));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) st->status_check_interval = 500;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) /* Give the AP some time */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) msleep(200);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) static int bcm3510_sleep(struct dvb_frontend* fe)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) static int bcm3510_get_tune_settings(struct dvb_frontend *fe, struct dvb_frontend_tune_settings *s)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) s->min_delay_ms = 1000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) s->step_size = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) s->max_drift = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) static void bcm3510_release(struct dvb_frontend* fe)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) struct bcm3510_state* state = fe->demodulator_priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) kfree(state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) /* firmware download:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) * firmware file is build up like this:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) * 16bit addr, 16bit length, 8byte of length
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) #define BCM3510_DEFAULT_FIRMWARE "dvb-fe-bcm3510-01.fw"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) static int bcm3510_write_ram(struct bcm3510_state *st, u16 addr, const u8 *b,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) u16 len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) int ret = 0,i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) bcm3510_register_value vH, vL,vD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) vH.MADRH_a9 = addr >> 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) vL.MADRL_aa = addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) if ((ret = bcm3510_writeB(st,0xa9,vH)) < 0) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) if ((ret = bcm3510_writeB(st,0xaa,vL)) < 0) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) for (i = 0; i < len; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) vD.MDATA_ab = b[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) if ((ret = bcm3510_writeB(st,0xab,vD)) < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) static int bcm3510_download_firmware(struct dvb_frontend* fe)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) struct bcm3510_state* st = fe->demodulator_priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) const struct firmware *fw;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) u16 addr,len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) const u8 *b;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) int ret,i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) deb_info("requesting firmware\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) if ((ret = st->config->request_firmware(fe, &fw, BCM3510_DEFAULT_FIRMWARE)) < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) err("could not load firmware (%s): %d",BCM3510_DEFAULT_FIRMWARE,ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) deb_info("got firmware: %zu\n", fw->size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) b = fw->data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) for (i = 0; i < fw->size;) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) addr = le16_to_cpu(*((__le16 *)&b[i]));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) len = le16_to_cpu(*((__le16 *)&b[i+2]));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) deb_info("firmware chunk, addr: 0x%04x, len: 0x%04x, total length: 0x%04zx\n",addr,len,fw->size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) if ((ret = bcm3510_write_ram(st,addr,&b[i+4],len)) < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) err("firmware download failed: %d\n",ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) i += 4 + len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) release_firmware(fw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) deb_info("firmware download successfully completed\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) static int bcm3510_check_firmware_version(struct bcm3510_state *st)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) struct bcm3510_hab_cmd_get_version_info ver;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) bcm3510_do_hab_cmd(st,CMD_GET_VERSION_INFO,MSGID_GET_VERSION_INFO,NULL,0,(u8*)&ver,sizeof(ver));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) deb_info("Version information: 0x%02x 0x%02x 0x%02x 0x%02x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) ver.microcode_version, ver.script_version, ver.config_version, ver.demod_version);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) if (ver.script_version == BCM3510_DEF_SCRIPT_VERSION &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) ver.config_version == BCM3510_DEF_CONFIG_VERSION &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) ver.demod_version == BCM3510_DEF_DEMOD_VERSION)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) deb_info("version check failed\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) /* (un)resetting the AP */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) static int bcm3510_reset(struct bcm3510_state *st)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) unsigned long t;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) bcm3510_register_value v;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) bcm3510_readB(st,0xa0,&v); v.HCTL1_a0.RESET = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) if ((ret = bcm3510_writeB(st,0xa0,v)) < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) t = jiffies + 3*HZ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) while (time_before(jiffies, t)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) msleep(10);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) if ((ret = bcm3510_readB(st,0xa2,&v)) < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) if (v.APSTAT1_a2.RESET)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) deb_info("reset timed out\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) return -ETIMEDOUT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) static int bcm3510_clear_reset(struct bcm3510_state *st)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) bcm3510_register_value v;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) unsigned long t;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) v.raw = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) if ((ret = bcm3510_writeB(st,0xa0,v)) < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) t = jiffies + 3*HZ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) while (time_before(jiffies, t)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714) msleep(10);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) if ((ret = bcm3510_readB(st,0xa2,&v)) < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) /* verify that reset is cleared */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719) if (!v.APSTAT1_a2.RESET)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) deb_info("reset clear timed out\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723) return -ETIMEDOUT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726) static int bcm3510_init_cold(struct bcm3510_state *st)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729) bcm3510_register_value v;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) /* read Acquisation Processor status register and check it is not in RUN mode */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732) if ((ret = bcm3510_readB(st,0xa2,&v)) < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) if (v.APSTAT1_a2.RUN) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735) deb_info("AP is already running - firmware already loaded.\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739) deb_info("reset?\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740) if ((ret = bcm3510_reset(st)) < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) deb_info("tristate?\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744) /* tri-state */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) v.TSTCTL_2e.CTL = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746) if ((ret = bcm3510_writeB(st,0x2e,v)) < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) deb_info("firmware?\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) if ((ret = bcm3510_download_firmware(&st->frontend)) < 0 ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) (ret = bcm3510_clear_reset(st)) < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754) /* anything left here to Let the acquisition processor begin execution at program counter 0000 ??? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759) static int bcm3510_init(struct dvb_frontend* fe)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761) struct bcm3510_state* st = fe->demodulator_priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762) bcm3510_register_value j;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763) struct bcm3510_hab_cmd_set_agc c;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766) if ((ret = bcm3510_readB(st,0xca,&j)) < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769) deb_info("JDEC: %02x\n",j.raw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771) switch (j.JDEC_ca.JDEC) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772) case JDEC_WAIT_AT_RAM:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773) deb_info("attempting to download firmware\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774) if ((ret = bcm3510_init_cold(st)) < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776) fallthrough;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777) case JDEC_EEPROM_LOAD_WAIT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778) deb_info("firmware is loaded\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779) bcm3510_check_firmware_version(st);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785) memset(&c,0,1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786) c.SEL = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787) bcm3510_do_hab_cmd(st,CMD_AUTO_PARAM,MSGID_SET_RF_AGC_SEL,(u8 *)&c,sizeof(c),NULL,0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793) static const struct dvb_frontend_ops bcm3510_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795) struct dvb_frontend* bcm3510_attach(const struct bcm3510_config *config,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796) struct i2c_adapter *i2c)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798) struct bcm3510_state* state = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800) bcm3510_register_value v;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802) /* allocate memory for the internal state */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803) state = kzalloc(sizeof(struct bcm3510_state), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804) if (state == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805) goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807) /* setup the state */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809) state->config = config;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810) state->i2c = i2c;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812) /* create dvb_frontend */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813) memcpy(&state->frontend.ops, &bcm3510_ops, sizeof(struct dvb_frontend_ops));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814) state->frontend.demodulator_priv = state;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816) mutex_init(&state->hab_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818) if ((ret = bcm3510_readB(state,0xe0,&v)) < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819) goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821) deb_info("Revision: 0x%1x, Layer: 0x%1x.\n",v.REVID_e0.REV,v.REVID_e0.LAYER);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823) if ((v.REVID_e0.REV != 0x1 && v.REVID_e0.LAYER != 0xb) && /* cold */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824) (v.REVID_e0.REV != 0x8 && v.REVID_e0.LAYER != 0x0)) /* warm */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825) goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827) info("Revision: 0x%1x, Layer: 0x%1x.",v.REVID_e0.REV,v.REVID_e0.LAYER);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829) bcm3510_reset(state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831) return &state->frontend;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833) error:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834) kfree(state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837) EXPORT_SYMBOL(bcm3510_attach);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839) static const struct dvb_frontend_ops bcm3510_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840) .delsys = { SYS_ATSC, SYS_DVBC_ANNEX_B },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841) .info = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842) .name = "Broadcom BCM3510 VSB/QAM frontend",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843) .frequency_min_hz = 54 * MHz,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844) .frequency_max_hz = 803 * MHz,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845) .caps =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846) FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847) FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848) FE_CAN_8VSB | FE_CAN_16VSB |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849) FE_CAN_QAM_16 | FE_CAN_QAM_64 | FE_CAN_QAM_128 | FE_CAN_QAM_256
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 851)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852) .release = bcm3510_release,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 853)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854) .init = bcm3510_init,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 855) .sleep = bcm3510_sleep,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 856)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 857) .set_frontend = bcm3510_set_frontend,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 858) .get_tune_settings = bcm3510_get_tune_settings,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 859)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 860) .read_status = bcm3510_read_status,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 861) .read_ber = bcm3510_read_ber,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 862) .read_signal_strength = bcm3510_read_signal_strength,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 863) .read_snr = bcm3510_read_snr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 864) .read_ucblocks = bcm3510_read_unc,
^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) MODULE_DESCRIPTION("Broadcom BCM3510 ATSC (8VSB/16VSB & ITU J83 AnnexB FEC QAM64/256) demodulator driver");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 868) MODULE_AUTHOR("Patrick Boettcher <patrick.boettcher@posteo.de>");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 869) MODULE_LICENSE("GPL");