aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media
diff options
context:
space:
mode:
authorJohannes Stezenbach <js@linuxtv.org>2005-06-24 01:02:41 -0400
committerLinus Torvalds <torvalds@ppc970.osdl.org>2005-06-24 03:05:31 -0400
commit55f51efdb696ff6e9d2056377d05268a97f3d4e4 (patch)
tree980d8960fecb4db3bf337776bc2f53401e103bdf /drivers/media
parentcc89c229d9d7ec63cd33e960c20e75b77bc987d0 (diff)
[PATCH] dvb: flexcop: add BCM3510 ATSC frontend support for Air2PC card
Added support for the Broadcom BCM3510 ATSC (8VSB/16VSB & ITU J83 AnnexB FEC QAM64/256) demodulator used in the first generation of Air2PC ATSC PCI-cards/USB-boxes made by B2C2. Signed-off-by: Patrick Boettcher <pb@linuxtv.org> Signed-off-by: Johannes Stezenbach <js@linuxtv.org> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'drivers/media')
-rw-r--r--drivers/media/dvb/b2c2/Kconfig1
-rw-r--r--drivers/media/dvb/b2c2/flexcop-fe-tuner.c26
-rw-r--r--drivers/media/dvb/b2c2/flexcop-misc.c11
-rw-r--r--drivers/media/dvb/b2c2/flexcop-reg.h3
-rw-r--r--drivers/media/dvb/frontends/Kconfig8
-rw-r--r--drivers/media/dvb/frontends/Makefile1
-rw-r--r--drivers/media/dvb/frontends/bcm3510.c853
-rw-r--r--drivers/media/dvb/frontends/bcm3510.h40
-rw-r--r--drivers/media/dvb/frontends/bcm3510_priv.h460
9 files changed, 1389 insertions, 14 deletions
diff --git a/drivers/media/dvb/b2c2/Kconfig b/drivers/media/dvb/b2c2/Kconfig
index 99bd675df955..fafd0ab3a28f 100644
--- a/drivers/media/dvb/b2c2/Kconfig
+++ b/drivers/media/dvb/b2c2/Kconfig
@@ -6,6 +6,7 @@ config DVB_B2C2_FLEXCOP
6 select DVB_MT312 6 select DVB_MT312
7 select DVB_NXT2002 7 select DVB_NXT2002
8 select DVB_STV0297 8 select DVB_STV0297
9 select DVB_BCM3510
9 help 10 help
10 Support for the digital TV receiver chip made by B2C2 Inc. included in 11 Support for the digital TV receiver chip made by B2C2 Inc. included in
11 Technisats PCI cards and USB boxes. 12 Technisats PCI cards and USB boxes.
diff --git a/drivers/media/dvb/b2c2/flexcop-fe-tuner.c b/drivers/media/dvb/b2c2/flexcop-fe-tuner.c
index 71be400e9aeb..0410cc96a48e 100644
--- a/drivers/media/dvb/b2c2/flexcop-fe-tuner.c
+++ b/drivers/media/dvb/b2c2/flexcop-fe-tuner.c
@@ -10,6 +10,7 @@
10#include "stv0299.h" 10#include "stv0299.h"
11#include "mt352.h" 11#include "mt352.h"
12#include "nxt2002.h" 12#include "nxt2002.h"
13#include "bcm3510.h"
13#include "stv0297.h" 14#include "stv0297.h"
14#include "mt312.h" 15#include "mt312.h"
15 16
@@ -285,21 +286,25 @@ static int samsung_tdtc9251dh0_pll_set(struct dvb_frontend* fe, struct dvb_front
285} 286}
286 287
287static struct mt352_config samsung_tdtc9251dh0_config = { 288static struct mt352_config samsung_tdtc9251dh0_config = {
288
289 .demod_address = 0x0f, 289 .demod_address = 0x0f,
290 .demod_init = samsung_tdtc9251dh0_demod_init, 290 .demod_init = samsung_tdtc9251dh0_demod_init,
291 .pll_set = samsung_tdtc9251dh0_pll_set, 291 .pll_set = samsung_tdtc9251dh0_pll_set,
292}; 292};
293 293
294static int nxt2002_request_firmware(struct dvb_frontend* fe, const struct firmware **fw, char* name) 294static int flexcop_fe_request_firmware(struct dvb_frontend* fe, const struct firmware **fw, char* name)
295{ 295{
296 struct flexcop_device *fc = fe->dvb->priv; 296 struct flexcop_device *fc = fe->dvb->priv;
297 return request_firmware(fw, name, fc->dev); 297 return request_firmware(fw, name, fc->dev);
298} 298}
299 299
300static struct nxt2002_config samsung_tbmv_config = { 300static struct nxt2002_config samsung_tbmv_config = {
301 .demod_address = 0x0a, 301 .demod_address = 0x0a,
302 .request_firmware = nxt2002_request_firmware, 302 .request_firmware = flexcop_fe_request_firmware,
303};
304
305static struct bcm3510_config air2pc_atsc_first_gen_config = {
306 .demod_address = 0x0f,
307 .request_firmware = flexcop_fe_request_firmware,
303}; 308};
304 309
305static int skystar23_samsung_tbdu18132_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params) 310static int skystar23_samsung_tbdu18132_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params)
@@ -354,11 +359,16 @@ int flexcop_frontend_init(struct flexcop_device *fc)
354 fc->dev_type = FC_AIR_DVB; 359 fc->dev_type = FC_AIR_DVB;
355 info("found the mt352 at i2c address: 0x%02x",samsung_tdtc9251dh0_config.demod_address); 360 info("found the mt352 at i2c address: 0x%02x",samsung_tdtc9251dh0_config.demod_address);
356 } else 361 } else
357 /* try the air atsc (nxt2002) */ 362 /* try the air atsc 2nd generation (nxt2002) */
358 if ((fc->fe = nxt2002_attach(&samsung_tbmv_config, &fc->i2c_adap)) != NULL) { 363 if ((fc->fe = nxt2002_attach(&samsung_tbmv_config, &fc->i2c_adap)) != NULL) {
359 fc->dev_type = FC_AIR_ATSC; 364 fc->dev_type = FC_AIR_ATSC2;
360 info("found the nxt2002 at i2c address: 0x%02x",samsung_tbmv_config.demod_address); 365 info("found the nxt2002 at i2c address: 0x%02x",samsung_tbmv_config.demod_address);
361 } else 366 } else
367 /* try the air atsc 1nd generation (bcm3510)/panasonic ct10s */
368 if ((fc->fe = bcm3510_attach(&air2pc_atsc_first_gen_config, &fc->i2c_adap)) != NULL) {
369 fc->dev_type = FC_AIR_ATSC1;
370 info("found the bcm3510 at i2c address: 0x%02x",air2pc_atsc_first_gen_config.demod_address);
371 } else
362 /* try the cable dvb (stv0297) */ 372 /* try the cable dvb (stv0297) */
363 if ((fc->fe = stv0297_attach(&alps_tdee4_stv0297_config, &fc->i2c_adap, 0xf8)) != NULL) { 373 if ((fc->fe = stv0297_attach(&alps_tdee4_stv0297_config, &fc->i2c_adap, 0xf8)) != NULL) {
364 fc->dev_type = FC_CABLE; 374 fc->dev_type = FC_CABLE;
diff --git a/drivers/media/dvb/b2c2/flexcop-misc.c b/drivers/media/dvb/b2c2/flexcop-misc.c
index 19e06da46774..23082545651f 100644
--- a/drivers/media/dvb/b2c2/flexcop-misc.c
+++ b/drivers/media/dvb/b2c2/flexcop-misc.c
@@ -45,11 +45,12 @@ const char *flexcop_revision_names[] = {
45 45
46const char *flexcop_device_names[] = { 46const char *flexcop_device_names[] = {
47 "Unkown device", 47 "Unkown device",
48 "AirStar 2 DVB-T", 48 "Air2PC/AirStar 2 DVB-T",
49 "AirStar 2 ATSC", 49 "Air2PC/AirStar 2 ATSC 1st generation",
50 "SkyStar 2 DVB-S", 50 "Air2PC/AirStar 2 ATSC 2nd generation",
51 "SkyStar 2 DVB-S (old version)", 51 "Sky2PC/SkyStar 2 DVB-S",
52 "CableStar 2 DVB-C", 52 "Sky2PC/SkyStar 2 DVB-S (old version)",
53 "Cable2PC/CableStar 2 DVB-C",
53}; 54};
54 55
55const char *flexcop_bus_names[] = { 56const char *flexcop_bus_names[] = {
diff --git a/drivers/media/dvb/b2c2/flexcop-reg.h b/drivers/media/dvb/b2c2/flexcop-reg.h
index 5e131be55cb3..75b50f21afe6 100644
--- a/drivers/media/dvb/b2c2/flexcop-reg.h
+++ b/drivers/media/dvb/b2c2/flexcop-reg.h
@@ -21,7 +21,8 @@ extern const char *flexcop_revision_names[];
21typedef enum { 21typedef enum {
22 FC_UNK = 0, 22 FC_UNK = 0,
23 FC_AIR_DVB, 23 FC_AIR_DVB,
24 FC_AIR_ATSC, 24 FC_AIR_ATSC1,
25 FC_AIR_ATSC2,
25 FC_SKY, 26 FC_SKY,
26 FC_SKY_OLD, 27 FC_SKY_OLD,
27 FC_CABLE, 28 FC_CABLE,
diff --git a/drivers/media/dvb/frontends/Kconfig b/drivers/media/dvb/frontends/Kconfig
index 75fb556ec01f..b4fddf513ebe 100644
--- a/drivers/media/dvb/frontends/Kconfig
+++ b/drivers/media/dvb/frontends/Kconfig
@@ -173,4 +173,12 @@ config DVB_OR51132
173 An ATSC 8VSB and QAM64/256 tuner module. Say Y when you want 173 An ATSC 8VSB and QAM64/256 tuner module. Say Y when you want
174 to support this frontend. 174 to support this frontend.
175 175
176config DVB_BCM3510
177 tristate "Broadcom BCM3510"
178 depends on DVB_CORE
179 select FW_LOADER
180 help
181 An ATSC 8VSB/16VSB and QAM64/256 tuner module. Say Y when you want to
182 support this frontend.
183
176endmenu 184endmenu
diff --git a/drivers/media/dvb/frontends/Makefile b/drivers/media/dvb/frontends/Makefile
index 7f8784870eab..91d6d3576d3d 100644
--- a/drivers/media/dvb/frontends/Makefile
+++ b/drivers/media/dvb/frontends/Makefile
@@ -28,3 +28,4 @@ obj-$(CONFIG_DVB_STV0297) += stv0297.o
28obj-$(CONFIG_DVB_NXT2002) += nxt2002.o 28obj-$(CONFIG_DVB_NXT2002) += nxt2002.o
29obj-$(CONFIG_DVB_OR51211) += or51211.o 29obj-$(CONFIG_DVB_OR51211) += or51211.o
30obj-$(CONFIG_DVB_OR51132) += or51132.o 30obj-$(CONFIG_DVB_OR51132) += or51132.o
31obj-$(CONFIG_DVB_BCM3510) += bcm3510.o
diff --git a/drivers/media/dvb/frontends/bcm3510.c b/drivers/media/dvb/frontends/bcm3510.c
new file mode 100644
index 000000000000..f5fdc5c3e605
--- /dev/null
+++ b/drivers/media/dvb/frontends/bcm3510.c
@@ -0,0 +1,853 @@
1/*
2 * Support for the Broadcom BCM3510 ATSC demodulator (1st generation Air2PC)
3 *
4 * Copyright (C) 2001-5, B2C2 inc.
5 *
6 * GPL/Linux driver written by Patrick Boettcher <patrick.boettcher@desy.de>
7 *
8 * This driver is "hard-coded" to be used with the 1st generation of
9 * Technisat/B2C2's Air2PC ATSC PCI/USB cards/boxes. The pll-programming
10 * (Panasonic CT10S) is located here, which is actually wrong. Unless there is
11 * another device with a BCM3510, this is no problem.
12 *
13 * The driver works also with QAM64 DVB-C, but had an unreasonable high
14 * UNC. (Tested with the Air2PC ATSC 1st generation)
15 *
16 * You'll need a firmware for this driver in order to get it running. It is
17 * called "dvb-fe-bcm3510-01.fw".
18 *
19 * This program is free software; you can redistribute it and/or modify it
20 * under the terms of the GNU General Public License as published by the Free
21 * Software Foundation; either version 2 of the License, or (at your option)
22 * any later version.
23 *
24 * This program is distributed in the hope that it will be useful, but WITHOUT
25 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
26 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
27 * more details.
28 *
29 * You should have received a copy of the GNU General Public License along with
30 * this program; if not, write to the Free Software Foundation, Inc., 675 Mass
31 * Ave, Cambridge, MA 02139, USA.
32 */
33
34#include <linux/init.h>
35#include <linux/module.h>
36#include <linux/moduleparam.h>
37#include <linux/device.h>
38#include <linux/firmware.h>
39
40#include "dvb_frontend.h"
41#include "bcm3510.h"
42#include "bcm3510_priv.h"
43
44struct bcm3510_state {
45
46 struct i2c_adapter* i2c;
47 struct dvb_frontend_ops ops;
48 const struct bcm3510_config* config;
49 struct dvb_frontend frontend;
50
51 /* demodulator private data */
52 struct semaphore hab_sem;
53 u8 firmware_loaded:1;
54
55 unsigned long next_status_check;
56 unsigned long status_check_interval;
57 struct bcm3510_hab_cmd_status1 status1;
58 struct bcm3510_hab_cmd_status2 status2;
59};
60
61static int debug;
62module_param(debug, int, 0644);
63MODULE_PARM_DESC(debug, "set debugging level (1=info,2=i2c (|-able)).");
64
65#define dprintk(level,x...) if (level & debug) printk(x)
66#define dbufout(b,l,m) {\
67 int i; \
68 for (i = 0; i < l; i++) \
69 m("%02x ",b[i]); \
70}
71#define deb_info(args...) dprintk(0x01,args)
72#define deb_i2c(args...) dprintk(0x02,args)
73#define deb_hab(args...) dprintk(0x04,args)
74
75/* transfer functions */
76static int bcm3510_writebytes (struct bcm3510_state *state, u8 reg, u8 *buf, u8 len)
77{
78 u8 b[256];
79 int err;
80 struct i2c_msg msg = { .addr = state->config->demod_address, .flags = 0, .buf = b, .len = len + 1 };
81
82 b[0] = reg;
83 memcpy(&b[1],buf,len);
84
85 deb_i2c("i2c wr %02x: ",reg);
86 dbufout(buf,len,deb_i2c);
87 deb_i2c("\n");
88
89 if ((err = i2c_transfer (state->i2c, &msg, 1)) != 1) {
90
91 deb_info("%s: i2c write error (addr %02x, reg %02x, err == %i)\n",
92 __FUNCTION__, state->config->demod_address, reg, err);
93 return -EREMOTEIO;
94 }
95
96 return 0;
97}
98
99static int bcm3510_readbytes (struct bcm3510_state *state, u8 reg, u8 *buf, u8 len)
100{
101 struct i2c_msg msg[] = {
102 { .addr = state->config->demod_address, .flags = 0, .buf = &reg, .len = 1 },
103 { .addr = state->config->demod_address, .flags = I2C_M_RD, .buf = buf, .len = len }
104 };
105 int err;
106
107 memset(buf,0,len);
108
109 if ((err = i2c_transfer (state->i2c, msg, 2)) != 2) {
110 deb_info("%s: i2c read error (addr %02x, reg %02x, err == %i)\n",
111 __FUNCTION__, state->config->demod_address, reg, err);
112 return -EREMOTEIO;
113 }
114 deb_i2c("i2c rd %02x: ",reg);
115 dbufout(buf,len,deb_i2c);
116 deb_i2c("\n");
117
118 return 0;
119}
120
121static int bcm3510_writeB(struct bcm3510_state *state, u8 reg, bcm3510_register_value v)
122{
123 return bcm3510_writebytes(state,reg,&v.raw,1);
124}
125
126static int bcm3510_readB(struct bcm3510_state *state, u8 reg, bcm3510_register_value *v)
127{
128 return bcm3510_readbytes(state,reg,&v->raw,1);
129}
130
131/* Host Access Buffer transfers */
132static int bcm3510_hab_get_response(struct bcm3510_state *st, u8 *buf, int len)
133{
134 bcm3510_register_value v;
135 int ret,i;
136
137 v.HABADR_a6.HABADR = 0;
138 if ((ret = bcm3510_writeB(st,0xa6,v)) < 0)
139 return ret;
140
141 for (i = 0; i < len; i++) {
142 if ((ret = bcm3510_readB(st,0xa7,&v)) < 0)
143 return ret;
144 buf[i] = v.HABDATA_a7;
145 }
146 return 0;
147}
148
149static int bcm3510_hab_send_request(struct bcm3510_state *st, u8 *buf, int len)
150{
151 bcm3510_register_value v,hab;
152 int ret,i;
153 unsigned long t;
154
155/* Check if any previous HAB request still needs to be serviced by the
156 * Aquisition Processor before sending new request */
157 if ((ret = bcm3510_readB(st,0xa8,&v)) < 0)
158 return ret;
159 if (v.HABSTAT_a8.HABR) {
160 deb_info("HAB is running already - clearing it.\n");
161 v.HABSTAT_a8.HABR = 0;
162 bcm3510_writeB(st,0xa8,v);
163// return -EBUSY;
164 }
165
166/* Send the start HAB Address (automatically incremented after write of
167 * HABDATA) and write the HAB Data */
168 hab.HABADR_a6.HABADR = 0;
169 if ((ret = bcm3510_writeB(st,0xa6,hab)) < 0)
170 return ret;
171
172 for (i = 0; i < len; i++) {
173 hab.HABDATA_a7 = buf[i];
174 if ((ret = bcm3510_writeB(st,0xa7,hab)) < 0)
175 return ret;
176 }
177
178/* Set the HABR bit to indicate AP request in progress (LBHABR allows HABR to
179 * be written) */
180 v.raw = 0; v.HABSTAT_a8.HABR = 1; v.HABSTAT_a8.LDHABR = 1;
181 if ((ret = bcm3510_writeB(st,0xa8,v)) < 0)
182 return ret;
183
184/* Polling method: Wait until the AP finishes processing the HAB request */
185 t = jiffies + 1*HZ;
186 while (time_before(jiffies, t)) {
187 deb_info("waiting for HAB to complete\n");
188 msleep(10);
189 if ((ret = bcm3510_readB(st,0xa8,&v)) < 0)
190 return ret;
191
192 if (!v.HABSTAT_a8.HABR)
193 return 0;
194 }
195
196 deb_info("send_request execution timed out.\n");
197 return -ETIMEDOUT;
198}
199
200static int bcm3510_do_hab_cmd(struct bcm3510_state *st, u8 cmd, u8 msgid, u8 *obuf, u8 olen, u8 *ibuf, u8 ilen)
201{
202 u8 ob[olen+2],ib[ilen+2];
203 int ret = 0;
204
205 ob[0] = cmd;
206 ob[1] = msgid;
207 memcpy(&ob[2],obuf,olen);
208
209 deb_hab("hab snd: ");
210 dbufout(ob,olen+2,deb_hab);
211 deb_hab("\n");
212
213 if (down_interruptible(&st->hab_sem) < 0)
214 return -EAGAIN;
215
216 if ((ret = bcm3510_hab_send_request(st, ob, olen+2)) < 0 ||
217 (ret = bcm3510_hab_get_response(st, ib, ilen+2)) < 0)
218 goto error;
219
220 deb_hab("hab get: ");
221 dbufout(ib,ilen+2,deb_hab);
222 deb_hab("\n");
223
224 memcpy(ibuf,&ib[2],ilen);
225error:
226 up(&st->hab_sem);
227 return ret;
228}
229
230#if 0
231/* not needed, we use a semaphore to prevent HAB races */
232static int bcm3510_is_ap_ready(struct bcm3510_state *st)
233{
234 bcm3510_register_value ap,hab;
235 int ret;
236
237 if ((ret = bcm3510_readB(st,0xa8,&hab)) < 0 ||
238 (ret = bcm3510_readB(st,0xa2,&ap) < 0))
239 return ret;
240
241 if (ap.APSTAT1_a2.RESET || ap.APSTAT1_a2.IDLE || ap.APSTAT1_a2.STOP || hab.HABSTAT_a8.HABR) {
242 deb_info("AP is busy\n");
243 return -EBUSY;
244 }
245
246 return 0;
247}
248#endif
249
250static int bcm3510_bert_reset(struct bcm3510_state *st)
251{
252 bcm3510_register_value b;
253 int ret;
254
255 if ((ret < bcm3510_readB(st,0xfa,&b)) < 0)
256 return ret;
257
258 b.BERCTL_fa.RESYNC = 0; bcm3510_writeB(st,0xfa,b);
259 b.BERCTL_fa.RESYNC = 1; bcm3510_writeB(st,0xfa,b);
260 b.BERCTL_fa.RESYNC = 0; bcm3510_writeB(st,0xfa,b);
261 b.BERCTL_fa.CNTCTL = 1; b.BERCTL_fa.BITCNT = 1; bcm3510_writeB(st,0xfa,b);
262
263 /* clear residual bit counter TODO */
264 return 0;
265}
266
267static int bcm3510_refresh_state(struct bcm3510_state *st)
268{
269 if (time_after(jiffies,st->next_status_check)) {
270 bcm3510_do_hab_cmd(st, CMD_STATUS, MSGID_STATUS1, NULL,0, (u8 *)&st->status1, sizeof(st->status1));
271 bcm3510_do_hab_cmd(st, CMD_STATUS, MSGID_STATUS2, NULL,0, (u8 *)&st->status2, sizeof(st->status2));
272 st->next_status_check = jiffies + (st->status_check_interval*HZ)/1000;
273 }
274 return 0;
275}
276
277static int bcm3510_read_status(struct dvb_frontend *fe, fe_status_t *status)
278{
279 struct bcm3510_state* st = fe->demodulator_priv;
280 bcm3510_refresh_state(st);
281
282 *status = 0;
283 if (st->status1.STATUS1.RECEIVER_LOCK)
284 *status |= FE_HAS_LOCK | FE_HAS_SYNC;
285
286 if (st->status1.STATUS1.FEC_LOCK)
287 *status |= FE_HAS_VITERBI;
288
289 if (st->status1.STATUS1.OUT_PLL_LOCK)
290 *status |= FE_HAS_SIGNAL | FE_HAS_CARRIER;
291
292 if (*status & FE_HAS_LOCK)
293 st->status_check_interval = 1500;
294 else /* more frequently checks if no lock has been achieved yet */
295 st->status_check_interval = 500;
296
297 deb_info("real_status: %02x\n",*status);
298 return 0;
299}
300
301static int bcm3510_read_ber(struct dvb_frontend* fe, u32* ber)
302{
303 struct bcm3510_state* st = fe->demodulator_priv;
304 bcm3510_refresh_state(st);
305
306 *ber = (st->status2.LDBER0 << 16) | (st->status2.LDBER1 << 8) | st->status2.LDBER2;
307 return 0;
308}
309
310static int bcm3510_read_unc(struct dvb_frontend* fe, u32* unc)
311{
312 struct bcm3510_state* st = fe->demodulator_priv;
313 bcm3510_refresh_state(st);
314 *unc = (st->status2.LDUERC0 << 8) | st->status2.LDUERC1;
315 return 0;
316}
317
318static int bcm3510_read_signal_strength(struct dvb_frontend* fe, u16* strength)
319{
320 struct bcm3510_state* st = fe->demodulator_priv;
321 s32 t;
322
323 bcm3510_refresh_state(st);
324 t = st->status2.SIGNAL;
325
326 if (t > 190)
327 t = 190;
328 if (t < 90)
329 t = 90;
330
331 t -= 90;
332 t = t * 0xff / 100;
333 /* normalize if necessary */
334 *strength = (t << 8) | t;
335 return 0;
336}
337
338static int bcm3510_read_snr(struct dvb_frontend* fe, u16* snr)
339{
340 struct bcm3510_state* st = fe->demodulator_priv;
341 bcm3510_refresh_state(st);
342
343 *snr = st->status1.SNR_EST0*1000 + ((st->status1.SNR_EST1*1000) >> 8);
344 return 0;
345}
346
347/* tuner frontend programming */
348static int bcm3510_tuner_cmd(struct bcm3510_state* st,u8 bc, u16 n, u8 a)
349{
350 struct bcm3510_hab_cmd_tune c;
351 memset(&c,0,sizeof(struct bcm3510_hab_cmd_tune));
352
353/* I2C Mode disabled, set 16 control / Data pairs */
354 c.length = 0x10;
355 c.clock_width = 0;
356/* CS1, CS0, DATA, CLK bits control the tuner RF_AGC_SEL pin is set to
357 * logic high (as Configuration) */
358 c.misc = 0x10;
359/* Set duration of the initial state of TUNCTL = 3.34 micro Sec */
360 c.TUNCTL_state = 0x40;
361
362/* PRESCALER DEVIDE RATIO | BC1_2_3_4; (band switch), 1stosc REFERENCE COUNTER REF_S12 and REF_S11 */
363 c.ctl_dat[0].ctrl.size = BITS_8;
364 c.ctl_dat[0].data = 0x80 | bc;
365
366/* Control DATA pin, 1stosc REFERENCE COUNTER REF_S10 to REF_S3 */
367 c.ctl_dat[1].ctrl.size = BITS_8;
368 c.ctl_dat[1].data = 4;
369
370/* set CONTROL BIT 1 to 1, 1stosc REFERENCE COUNTER REF_S2 to REF_S1 */
371 c.ctl_dat[2].ctrl.size = BITS_3;
372 c.ctl_dat[2].data = 0x20;
373
374/* control CS0 pin, pulse byte ? */
375 c.ctl_dat[3].ctrl.size = BITS_3;
376 c.ctl_dat[3].ctrl.clk_off = 1;
377 c.ctl_dat[3].ctrl.cs0 = 1;
378 c.ctl_dat[3].data = 0x40;
379
380/* PGM_S18 to PGM_S11 */
381 c.ctl_dat[4].ctrl.size = BITS_8;
382 c.ctl_dat[4].data = n >> 3;
383
384/* PGM_S10 to PGM_S8, SWL_S7 to SWL_S3 */
385 c.ctl_dat[5].ctrl.size = BITS_8;
386 c.ctl_dat[5].data = ((n & 0x7) << 5) | (a >> 2);
387
388/* SWL_S2 and SWL_S1, set CONTROL BIT 2 to 0 */
389 c.ctl_dat[6].ctrl.size = BITS_3;
390 c.ctl_dat[6].data = (a << 6) & 0xdf;
391
392/* control CS0 pin, pulse byte ? */
393 c.ctl_dat[7].ctrl.size = BITS_3;
394 c.ctl_dat[7].ctrl.clk_off = 1;
395 c.ctl_dat[7].ctrl.cs0 = 1;
396 c.ctl_dat[7].data = 0x40;
397
398/* PRESCALER DEVIDE RATIO, 2ndosc REFERENCE COUNTER REF_S12 and REF_S11 */
399 c.ctl_dat[8].ctrl.size = BITS_8;
400 c.ctl_dat[8].data = 0x80;
401
402/* 2ndosc REFERENCE COUNTER REF_S10 to REF_S3 */
403 c.ctl_dat[9].ctrl.size = BITS_8;
404 c.ctl_dat[9].data = 0x10;
405
406/* set CONTROL BIT 1 to 1, 2ndosc REFERENCE COUNTER REF_S2 to REF_S1 */
407 c.ctl_dat[10].ctrl.size = BITS_3;
408 c.ctl_dat[10].data = 0x20;
409
410/* pulse byte */
411 c.ctl_dat[11].ctrl.size = BITS_3;
412 c.ctl_dat[11].ctrl.clk_off = 1;
413 c.ctl_dat[11].ctrl.cs1 = 1;
414 c.ctl_dat[11].data = 0x40;
415
416/* PGM_S18 to PGM_S11 */
417 c.ctl_dat[12].ctrl.size = BITS_8;
418 c.ctl_dat[12].data = 0x2a;
419
420/* PGM_S10 to PGM_S8 and SWL_S7 to SWL_S3 */
421 c.ctl_dat[13].ctrl.size = BITS_8;
422 c.ctl_dat[13].data = 0x8e;
423
424/* SWL_S2 and SWL_S1 and set CONTROL BIT 2 to 0 */
425 c.ctl_dat[14].ctrl.size = BITS_3;
426 c.ctl_dat[14].data = 0;
427
428/* Pulse Byte */
429 c.ctl_dat[15].ctrl.size = BITS_3;
430 c.ctl_dat[15].ctrl.clk_off = 1;
431 c.ctl_dat[15].ctrl.cs1 = 1;
432 c.ctl_dat[15].data = 0x40;
433
434 return bcm3510_do_hab_cmd(st,CMD_TUNE, MSGID_TUNE,(u8 *) &c,sizeof(c), NULL, 0);
435}
436
437static int bcm3510_set_freq(struct bcm3510_state* st,u32 freq)
438{
439 u8 bc,a;
440 u16 n;
441 s32 YIntercept,Tfvco1;
442
443 freq /= 1000;
444
445 deb_info("%dkHz:",freq);
446 /* set Band Switch */
447 if (freq <= 168000)
448 bc = 0x1c;
449 else if (freq <= 378000)
450 bc = 0x2c;
451 else
452 bc = 0x30;
453
454 if (freq >= 470000) {
455 freq -= 470001;
456 YIntercept = 18805;
457 } else if (freq >= 90000) {
458 freq -= 90001;
459 YIntercept = 15005;
460 } else if (freq >= 76000){
461 freq -= 76001;
462 YIntercept = 14865;
463 } else {
464 freq -= 54001;
465 YIntercept = 14645;
466 }
467
468 Tfvco1 = (((freq/6000)*60 + YIntercept)*4)/10;
469
470 n = Tfvco1 >> 6;
471 a = Tfvco1 & 0x3f;
472
473 deb_info(" BC1_2_3_4: %x, N: %x A: %x\n", bc, n, a);
474 if (n >= 16 && n <= 2047)
475 return bcm3510_tuner_cmd(st,bc,n,a);
476
477 return -EINVAL;
478}
479
480static int bcm3510_set_frontend(struct dvb_frontend* fe,
481 struct dvb_frontend_parameters *p)
482{
483 struct bcm3510_state* st = fe->demodulator_priv;
484 struct bcm3510_hab_cmd_ext_acquire cmd;
485 struct bcm3510_hab_cmd_bert_control bert;
486 int ret;
487
488 memset(&cmd,0,sizeof(cmd));
489 switch (p->u.vsb.modulation) {
490 case QAM_256:
491 cmd.ACQUIRE0.MODE = 0x1;
492 cmd.ACQUIRE1.SYM_RATE = 0x1;
493 cmd.ACQUIRE1.IF_FREQ = 0x1;
494 break;
495 case QAM_64:
496 cmd.ACQUIRE0.MODE = 0x2;
497 cmd.ACQUIRE1.SYM_RATE = 0x2;
498 cmd.ACQUIRE1.IF_FREQ = 0x1;
499 break;
500/* case QAM_256:
501 cmd.ACQUIRE0.MODE = 0x3;
502 break;
503 case QAM_128:
504 cmd.ACQUIRE0.MODE = 0x4;
505 break;
506 case QAM_64:
507 cmd.ACQUIRE0.MODE = 0x5;
508 break;
509 case QAM_32:
510 cmd.ACQUIRE0.MODE = 0x6;
511 break;
512 case QAM_16:
513 cmd.ACQUIRE0.MODE = 0x7;
514 break;*/
515 case VSB_8:
516 cmd.ACQUIRE0.MODE = 0x8;
517 cmd.ACQUIRE1.SYM_RATE = 0x0;
518 cmd.ACQUIRE1.IF_FREQ = 0x0;
519 break;
520 case VSB_16:
521 cmd.ACQUIRE0.MODE = 0x9;
522 cmd.ACQUIRE1.SYM_RATE = 0x0;
523 cmd.ACQUIRE1.IF_FREQ = 0x0;
524 default:
525 return -EINVAL;
526 };
527 cmd.ACQUIRE0.OFFSET = 0;
528 cmd.ACQUIRE0.NTSCSWEEP = 1;
529 cmd.ACQUIRE0.FA = 1;
530 cmd.ACQUIRE0.BW = 0;
531
532/* if (enableOffset) {
533 cmd.IF_OFFSET0 = xx;
534 cmd.IF_OFFSET1 = xx;
535
536 cmd.SYM_OFFSET0 = xx;
537 cmd.SYM_OFFSET1 = xx;
538 if (enableNtscSweep) {
539 cmd.NTSC_OFFSET0;
540 cmd.NTSC_OFFSET1;
541 }
542 } */
543 bcm3510_do_hab_cmd(st, CMD_ACQUIRE, MSGID_EXT_TUNER_ACQUIRE, (u8 *) &cmd, sizeof(cmd), NULL, 0);
544
545/* doing it with different MSGIDs, data book and source differs */
546 bert.BE = 0;
547 bert.unused = 0;
548 bcm3510_do_hab_cmd(st, CMD_STATE_CONTROL, MSGID_BERT_CONTROL, (u8 *) &bert, sizeof(bert), NULL, 0);
549 bcm3510_do_hab_cmd(st, CMD_STATE_CONTROL, MSGID_BERT_SET, (u8 *) &bert, sizeof(bert), NULL, 0);
550
551 bcm3510_bert_reset(st);
552
553 if ((ret = bcm3510_set_freq(st,p->frequency)) < 0)
554 return ret;
555
556 memset(&st->status1,0,sizeof(st->status1));
557 memset(&st->status2,0,sizeof(st->status2));
558 st->status_check_interval = 500;
559
560/* Give the AP some time */
561 msleep(200);
562
563 return 0;
564}
565
566static int bcm3510_sleep(struct dvb_frontend* fe)
567{
568 return 0;
569}
570
571static int bcm3510_get_tune_settings(struct dvb_frontend *fe, struct dvb_frontend_tune_settings *s)
572{
573 s->min_delay_ms = 1000;
574 s->step_size = 0;
575 s->max_drift = 0;
576 return 0;
577}
578
579static void bcm3510_release(struct dvb_frontend* fe)
580{
581 struct bcm3510_state* state = fe->demodulator_priv;
582 kfree(state);
583}
584
585/* firmware download:
586 * firmware file is build up like this:
587 * 16bit addr, 16bit length, 8byte of length
588 */
589#define BCM3510_DEFAULT_FIRMWARE "dvb-fe-bcm3510-01.fw"
590
591static int bcm3510_write_ram(struct bcm3510_state *st, u16 addr, u8 *b, u16 len)
592{
593 int ret = 0,i;
594 bcm3510_register_value vH, vL,vD;
595
596 vH.MADRH_a9 = addr >> 8;
597 vL.MADRL_aa = addr;
598 if ((ret = bcm3510_writeB(st,0xa9,vH)) < 0) return ret;
599 if ((ret = bcm3510_writeB(st,0xaa,vL)) < 0) return ret;
600
601 for (i = 0; i < len; i++) {
602 vD.MDATA_ab = b[i];
603 if ((ret = bcm3510_writeB(st,0xab,vD)) < 0)
604 return ret;
605 }
606
607 return 0;
608}
609
610static int bcm3510_download_firmware(struct dvb_frontend* fe)
611{
612 struct bcm3510_state* st = fe->demodulator_priv;
613 const struct firmware *fw;
614 u16 addr,len;
615 u8 *b;
616 int ret,i;
617
618 deb_info("requesting firmware\n");
619 if ((ret = st->config->request_firmware(fe, &fw, BCM3510_DEFAULT_FIRMWARE)) < 0) {
620 err("could not load firmware (%s): %d",BCM3510_DEFAULT_FIRMWARE,ret);
621 return ret;
622 }
623 deb_info("got firmware: %d\n",fw->size);
624
625 b = fw->data;
626 for (i = 0; i < fw->size;) {
627 addr = le16_to_cpu( *( (u16 *)&b[i] ) );
628 len = le16_to_cpu( *( (u16 *)&b[i+2] ) );
629 deb_info("firmware chunk, addr: 0x%04x, len: 0x%04x, total length: 0x%04x\n",addr,len,fw->size);
630 if ((ret = bcm3510_write_ram(st,addr,&b[i+4],len)) < 0) {
631 err("firmware download failed: %d\n",ret);
632 return ret;
633 }
634 i += 4 + len;
635 }
636 release_firmware(fw);
637 deb_info("firmware download successfully completed\n");
638 return 0;
639}
640
641static int bcm3510_check_firmware_version(struct bcm3510_state *st)
642{
643 struct bcm3510_hab_cmd_get_version_info ver;
644 bcm3510_do_hab_cmd(st,CMD_GET_VERSION_INFO,MSGID_GET_VERSION_INFO,NULL,0,(u8*)&ver,sizeof(ver));
645
646 deb_info("Version information: 0x%02x 0x%02x 0x%02x 0x%02x\n",
647 ver.microcode_version, ver.script_version, ver.config_version, ver.demod_version);
648
649 if (ver.script_version == BCM3510_DEF_SCRIPT_VERSION &&
650 ver.config_version == BCM3510_DEF_CONFIG_VERSION &&
651 ver.demod_version == BCM3510_DEF_DEMOD_VERSION)
652 return 0;
653
654 deb_info("version check failed\n");
655 return -ENODEV;
656}
657
658/* (un)resetting the AP */
659static int bcm3510_reset(struct bcm3510_state *st)
660{
661 int ret;
662 unsigned long t;
663 bcm3510_register_value v;
664
665 bcm3510_readB(st,0xa0,&v); v.HCTL1_a0.RESET = 1;
666 if ((ret = bcm3510_writeB(st,0xa0,v)) < 0)
667 return ret;
668
669 t = jiffies + 3*HZ;
670 while (time_before(jiffies, t)) {
671 msleep(10);
672 if ((ret = bcm3510_readB(st,0xa2,&v)) < 0)
673 return ret;
674
675 if (v.APSTAT1_a2.RESET)
676 return 0;
677 }
678 deb_info("reset timed out\n");
679 return -ETIMEDOUT;
680}
681
682static int bcm3510_clear_reset(struct bcm3510_state *st)
683{
684 bcm3510_register_value v;
685 int ret;
686 unsigned long t;
687
688 v.raw = 0;
689 if ((ret = bcm3510_writeB(st,0xa0,v)) < 0)
690 return ret;
691
692 t = jiffies + 3*HZ;
693 while (time_before(jiffies, t)) {
694 msleep(10);
695 if ((ret = bcm3510_readB(st,0xa2,&v)) < 0)
696 return ret;
697
698 /* verify that reset is cleared */
699 if (!v.APSTAT1_a2.RESET)
700 return 0;
701 }
702 deb_info("reset clear timed out\n");
703 return -ETIMEDOUT;
704}
705
706static int bcm3510_init_cold(struct bcm3510_state *st)
707{
708 int ret;
709 bcm3510_register_value v;
710
711 /* read Acquisation Processor status register and check it is not in RUN mode */
712 if ((ret = bcm3510_readB(st,0xa2,&v)) < 0)
713 return ret;
714 if (v.APSTAT1_a2.RUN) {
715 deb_info("AP is already running - firmware already loaded.\n");
716 return 0;
717 }
718
719 deb_info("reset?\n");
720 if ((ret = bcm3510_reset(st)) < 0)
721 return ret;
722
723 deb_info("tristate?\n");
724 /* tri-state */
725 v.TSTCTL_2e.CTL = 0;
726 if ((ret = bcm3510_writeB(st,0x2e,v)) < 0)
727 return ret;
728
729 deb_info("firmware?\n");
730 if ((ret = bcm3510_download_firmware(&st->frontend)) < 0 ||
731 (ret = bcm3510_clear_reset(st)) < 0)
732 return ret;
733
734 /* anything left here to Let the acquisition processor begin execution at program counter 0000 ??? */
735
736 return 0;
737}
738
739static int bcm3510_init(struct dvb_frontend* fe)
740{
741 struct bcm3510_state* st = fe->demodulator_priv;
742 bcm3510_register_value j;
743 struct bcm3510_hab_cmd_set_agc c;
744 int ret;
745
746 if ((ret = bcm3510_readB(st,0xca,&j)) < 0)
747 return ret;
748
749 deb_info("JDEC: %02x\n",j.raw);
750
751 switch (j.JDEC_ca.JDEC) {
752 case JDEC_WAIT_AT_RAM:
753 deb_info("attempting to download firmware\n");
754 if ((ret = bcm3510_init_cold(st)) < 0)
755 return ret;
756 case JDEC_EEPROM_LOAD_WAIT: /* fall-through is wanted */
757 deb_info("firmware is loaded\n");
758 bcm3510_check_firmware_version(st);
759 break;
760 default:
761 return -ENODEV;
762 }
763
764 memset(&c,0,1);
765 c.SEL = 1;
766 bcm3510_do_hab_cmd(st,CMD_AUTO_PARAM,MSGID_SET_RF_AGC_SEL,(u8 *)&c,sizeof(c),NULL,0);
767
768 return 0;
769}
770
771
772static struct dvb_frontend_ops bcm3510_ops;
773
774struct dvb_frontend* bcm3510_attach(const struct bcm3510_config *config,
775 struct i2c_adapter *i2c)
776{
777 struct bcm3510_state* state = NULL;
778 int ret;
779 bcm3510_register_value v;
780
781 /* allocate memory for the internal state */
782 state = kmalloc(sizeof(struct bcm3510_state), GFP_KERNEL);
783 if (state == NULL)
784 goto error;
785 memset(state,0,sizeof(struct bcm3510_state));
786
787 /* setup the state */
788
789 state->config = config;
790 state->i2c = i2c;
791 memcpy(&state->ops, &bcm3510_ops, sizeof(struct dvb_frontend_ops));
792
793 /* create dvb_frontend */
794 state->frontend.ops = &state->ops;
795 state->frontend.demodulator_priv = state;
796
797 sema_init(&state->hab_sem, 1);
798
799 if ((ret = bcm3510_readB(state,0xe0,&v)) < 0)
800 goto error;
801
802 deb_info("Revision: 0x%1x, Layer: 0x%1x.\n",v.REVID_e0.REV,v.REVID_e0.LAYER);
803
804 if ((v.REVID_e0.REV != 0x1 && v.REVID_e0.LAYER != 0xb) && /* cold */
805 (v.REVID_e0.REV != 0x8 && v.REVID_e0.LAYER != 0x0)) /* warm */
806 goto error;
807
808 info("Revision: 0x%1x, Layer: 0x%1x.",v.REVID_e0.REV,v.REVID_e0.LAYER);
809
810 bcm3510_reset(state);
811
812 return &state->frontend;
813
814error:
815 kfree(state);
816 return NULL;
817}
818EXPORT_SYMBOL(bcm3510_attach);
819
820static struct dvb_frontend_ops bcm3510_ops = {
821
822 .info = {
823 .name = "Broadcom BCM3510 VSB/QAM frontend",
824 .type = FE_ATSC,
825 .frequency_min = 54000000,
826 .frequency_max = 803000000,
827 /* stepsize is just a guess */
828 .frequency_stepsize = 0,
829 .caps =
830 FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 |
831 FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO |
832 FE_CAN_8VSB | FE_CAN_16VSB |
833 FE_CAN_QAM_16 | FE_CAN_QAM_64 | FE_CAN_QAM_128 | FE_CAN_QAM_256
834 },
835
836 .release = bcm3510_release,
837
838 .init = bcm3510_init,
839 .sleep = bcm3510_sleep,
840
841 .set_frontend = bcm3510_set_frontend,
842 .get_tune_settings = bcm3510_get_tune_settings,
843
844 .read_status = bcm3510_read_status,
845 .read_ber = bcm3510_read_ber,
846 .read_signal_strength = bcm3510_read_signal_strength,
847 .read_snr = bcm3510_read_snr,
848 .read_ucblocks = bcm3510_read_unc,
849};
850
851MODULE_DESCRIPTION("Broadcom BCM3510 ATSC (8VSB/16VSB & ITU J83 AnnexB FEC QAM64/256) demodulator driver");
852MODULE_AUTHOR("Patrick Boettcher <patrick.boettcher@desy.de>");
853MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb/frontends/bcm3510.h b/drivers/media/dvb/frontends/bcm3510.h
new file mode 100644
index 000000000000..80f5d0953d02
--- /dev/null
+++ b/drivers/media/dvb/frontends/bcm3510.h
@@ -0,0 +1,40 @@
1/*
2 * Support for the Broadcom BCM3510 ATSC demodulator (1st generation Air2PC)
3 *
4 * Copyright (C) 2001-5, B2C2 inc.
5 *
6 * GPL/Linux driver written by Patrick Boettcher <patrick.boettcher@desy.de>
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 */
22#ifndef BCM3510_H
23#define BCM3510_H
24
25#include <linux/dvb/frontend.h>
26#include <linux/firmware.h>
27
28struct bcm3510_config
29{
30 /* the demodulator's i2c address */
31 u8 demod_address;
32
33 /* request firmware for device */
34 int (*request_firmware)(struct dvb_frontend* fe, const struct firmware **fw, char* name);
35};
36
37extern struct dvb_frontend* bcm3510_attach(const struct bcm3510_config* config,
38 struct i2c_adapter* i2c);
39
40#endif
diff --git a/drivers/media/dvb/frontends/bcm3510_priv.h b/drivers/media/dvb/frontends/bcm3510_priv.h
new file mode 100644
index 000000000000..3bb1bc2a04f0
--- /dev/null
+++ b/drivers/media/dvb/frontends/bcm3510_priv.h
@@ -0,0 +1,460 @@
1/*
2 * Support for the Broadcom BCM3510 ATSC demodulator (1st generation Air2PC)
3 *
4 * Copyright (C) 2001-5, B2C2 inc.
5 *
6 * GPL/Linux driver written by Patrick Boettcher <patrick.boettcher@desy.de>
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 */
22#ifndef __BCM3510_PRIV_H__
23#define __BCM3510_PRIV_H__
24
25#define PACKED __attribute__((packed))
26
27#undef err
28#define err(format, arg...) printk(KERN_ERR "bcm3510: " format "\n" , ## arg)
29#undef info
30#define info(format, arg...) printk(KERN_INFO "bcm3510: " format "\n" , ## arg)
31#undef warn
32#define warn(format, arg...) printk(KERN_WARNING "bcm3510: " format "\n" , ## arg)
33
34
35#define PANASONIC_FIRST_IF_BASE_IN_KHz 1407500
36#define BCM3510_SYMBOL_RATE 5381000
37
38typedef union {
39 u8 raw;
40
41 struct {
42 u8 CTL :8;
43 } TSTCTL_2e;
44
45 u8 LDCERC_4e;
46 u8 LDUERC_4f;
47 u8 LD_BER0_65;
48 u8 LD_BER1_66;
49 u8 LD_BER2_67;
50 u8 LD_BER3_68;
51
52 struct {
53 u8 RESET :1;
54 u8 IDLE :1;
55 u8 STOP :1;
56 u8 HIRQ0 :1;
57 u8 HIRQ1 :1;
58 u8 na0 :1;
59 u8 HABAV :1;
60 u8 na1 :1;
61 } HCTL1_a0;
62
63 struct {
64 u8 na0 :1;
65 u8 IDLMSK :1;
66 u8 STMSK :1;
67 u8 I0MSK :1;
68 u8 I1MSK :1;
69 u8 na1 :1;
70 u8 HABMSK :1;
71 u8 na2 :1;
72 } HCTLMSK_a1;
73
74 struct {
75 u8 RESET :1;
76 u8 IDLE :1;
77 u8 STOP :1;
78 u8 RUN :1;
79 u8 HABAV :1;
80 u8 MEMAV :1;
81 u8 ALDONE :1;
82 u8 REIRQ :1;
83 } APSTAT1_a2;
84
85 struct {
86 u8 RSTMSK :1;
87 u8 IMSK :1;
88 u8 SMSK :1;
89 u8 RMSK :1;
90 u8 HABMSK :1;
91 u8 MAVMSK :1;
92 u8 ALDMSK :1;
93 u8 REMSK :1;
94 } APMSK1_a3;
95
96 u8 APSTAT2_a4;
97 u8 APMSK2_a5;
98
99 struct {
100 u8 HABADR :7;
101 u8 na :1;
102 } HABADR_a6;
103
104 u8 HABDATA_a7;
105
106 struct {
107 u8 HABR :1;
108 u8 LDHABR :1;
109 u8 APMSK :1;
110 u8 HMSK :1;
111 u8 LDMSK :1;
112 u8 na :3;
113 } HABSTAT_a8;
114
115 u8 MADRH_a9;
116 u8 MADRL_aa;
117 u8 MDATA_ab;
118
119 struct {
120#define JDEC_WAIT_AT_RAM 0x7
121#define JDEC_EEPROM_LOAD_WAIT 0x4
122 u8 JDEC :3;
123 u8 na :5;
124 } JDEC_ca;
125
126 struct {
127 u8 REV :4;
128 u8 LAYER :4;
129 } REVID_e0;
130
131 struct {
132 u8 unk0 :1;
133 u8 CNTCTL :1;
134 u8 BITCNT :1;
135 u8 unk1 :1;
136 u8 RESYNC :1;
137 u8 unk2 :3;
138 } BERCTL_fa;
139
140 struct {
141 u8 CSEL0 :1;
142 u8 CLKED0 :1;
143 u8 CSEL1 :1;
144 u8 CLKED1 :1;
145 u8 CLKLEV :1;
146 u8 SPIVAR :1;
147 u8 na :2;
148 } TUNSET_fc;
149
150 struct {
151 u8 CLK :1;
152 u8 DATA :1;
153 u8 CS0 :1;
154 u8 CS1 :1;
155 u8 AGCSEL :1;
156 u8 na0 :1;
157 u8 TUNSEL :1;
158 u8 na1 :1;
159 } TUNCTL_fd;
160
161 u8 TUNSEL0_fe;
162 u8 TUNSEL1_ff;
163
164} bcm3510_register_value;
165
166/* HAB commands */
167
168/* version */
169#define CMD_GET_VERSION_INFO 0x3D
170#define MSGID_GET_VERSION_INFO 0x15
171struct bcm3510_hab_cmd_get_version_info {
172 u8 microcode_version;
173 u8 script_version;
174 u8 config_version;
175 u8 demod_version;
176} PACKED;
177
178#define BCM3510_DEF_MICROCODE_VERSION 0x0E
179#define BCM3510_DEF_SCRIPT_VERSION 0x06
180#define BCM3510_DEF_CONFIG_VERSION 0x01
181#define BCM3510_DEF_DEMOD_VERSION 0xB1
182
183/* acquire */
184#define CMD_ACQUIRE 0x38
185
186#define MSGID_EXT_TUNER_ACQUIRE 0x0A
187struct bcm3510_hab_cmd_ext_acquire {
188 struct {
189 u8 MODE :4;
190 u8 BW :1;
191 u8 FA :1;
192 u8 NTSCSWEEP :1;
193 u8 OFFSET :1;
194 } PACKED ACQUIRE0; /* control_byte */
195
196 struct {
197 u8 IF_FREQ :3;
198 u8 zero0 :1;
199 u8 SYM_RATE :3;
200 u8 zero1 :1;
201 } PACKED ACQUIRE1; /* sym_if */
202
203 u8 IF_OFFSET0; /* IF_Offset_10hz */
204 u8 IF_OFFSET1;
205 u8 SYM_OFFSET0; /* SymbolRateOffset */
206 u8 SYM_OFFSET1;
207 u8 NTSC_OFFSET0; /* NTSC_Offset_10hz */
208 u8 NTSC_OFFSET1;
209} PACKED;
210
211#define MSGID_INT_TUNER_ACQUIRE 0x0B
212struct bcm3510_hab_cmd_int_acquire {
213 struct {
214 u8 MODE :4;
215 u8 BW :1;
216 u8 FA :1;
217 u8 NTSCSWEEP :1;
218 u8 OFFSET :1;
219 } PACKED ACQUIRE0; /* control_byte */
220
221 struct {
222 u8 IF_FREQ :3;
223 u8 zero0 :1;
224 u8 SYM_RATE :3;
225 u8 zero1 :1;
226 } PACKED ACQUIRE1; /* sym_if */
227
228 u8 TUNER_FREQ0;
229 u8 TUNER_FREQ1;
230 u8 TUNER_FREQ2;
231 u8 TUNER_FREQ3;
232 u8 IF_OFFSET0; /* IF_Offset_10hz */
233 u8 IF_OFFSET1;
234 u8 SYM_OFFSET0; /* SymbolRateOffset */
235 u8 SYM_OFFSET1;
236 u8 NTSC_OFFSET0; /* NTSC_Offset_10hz */
237 u8 NTSC_OFFSET1;
238} PACKED;
239
240/* modes */
241#define BCM3510_QAM16 = 0x01
242#define BCM3510_QAM32 = 0x02
243#define BCM3510_QAM64 = 0x03
244#define BCM3510_QAM128 = 0x04
245#define BCM3510_QAM256 = 0x05
246#define BCM3510_8VSB = 0x0B
247#define BCM3510_16VSB = 0x0D
248
249/* IF_FREQS */
250#define BCM3510_IF_TERRESTRIAL 0x0
251#define BCM3510_IF_CABLE 0x1
252#define BCM3510_IF_USE_CMD 0x7
253
254/* SYM_RATE */
255#define BCM3510_SR_8VSB 0x0 /* 5381119 s/sec */
256#define BCM3510_SR_256QAM 0x1 /* 5360537 s/sec */
257#define BCM3510_SR_16QAM 0x2 /* 5056971 s/sec */
258#define BCM3510_SR_MISC 0x3 /* 5000000 s/sec */
259#define BCM3510_SR_USE_CMD 0x7
260
261/* special symbol rate */
262#define CMD_SET_VALUE_NOT_LISTED 0x2d
263#define MSGID_SET_SYMBOL_RATE_NOT_LISTED 0x0c
264struct bcm3510_hab_cmd_set_sr_not_listed {
265 u8 HOST_SYM_RATE0;
266 u8 HOST_SYM_RATE1;
267 u8 HOST_SYM_RATE2;
268 u8 HOST_SYM_RATE3;
269} PACKED;
270
271/* special IF */
272#define MSGID_SET_IF_FREQ_NOT_LISTED 0x0d
273struct bcm3510_hab_cmd_set_if_freq_not_listed {
274 u8 HOST_IF_FREQ0;
275 u8 HOST_IF_FREQ1;
276 u8 HOST_IF_FREQ2;
277 u8 HOST_IF_FREQ3;
278} PACKED;
279
280/* auto reacquire */
281#define CMD_AUTO_PARAM 0x2a
282#define MSGID_AUTO_REACQUIRE 0x0e
283struct bcm3510_hab_cmd_auto_reacquire {
284 u8 ACQ :1; /* on/off*/
285 u8 unused :7;
286} PACKED;
287
288#define MSGID_SET_RF_AGC_SEL 0x12
289struct bcm3510_hab_cmd_set_agc {
290 u8 LVL :1;
291 u8 unused :6;
292 u8 SEL :1;
293} PACKED;
294
295#define MSGID_SET_AUTO_INVERSION 0x14
296struct bcm3510_hab_cmd_auto_inversion {
297 u8 AI :1;
298 u8 unused :7;
299} PACKED;
300
301
302/* bert control */
303#define CMD_STATE_CONTROL 0x12
304#define MSGID_BERT_CONTROL 0x0e
305#define MSGID_BERT_SET 0xfa
306struct bcm3510_hab_cmd_bert_control {
307 u8 BE :1;
308 u8 unused :7;
309} PACKED;
310
311#define MSGID_TRI_STATE 0x2e
312struct bcm3510_hab_cmd_tri_state {
313 u8 RE :1; /* a/d ram port pins */
314 u8 PE :1; /* baud clock pin */
315 u8 AC :1; /* a/d clock pin */
316 u8 BE :1; /* baud clock pin */
317 u8 unused :4;
318} PACKED;
319
320
321/* tune */
322#define CMD_TUNE 0x38
323#define MSGID_TUNE 0x16
324struct bcm3510_hab_cmd_tune_ctrl_data_pair {
325 struct {
326#define BITS_8 0x07
327#define BITS_7 0x06
328#define BITS_6 0x05
329#define BITS_5 0x04
330#define BITS_4 0x03
331#define BITS_3 0x02
332#define BITS_2 0x01
333#define BITS_1 0x00
334 u8 size :3;
335 u8 unk :2;
336 u8 clk_off :1;
337 u8 cs0 :1;
338 u8 cs1 :1;
339
340 } PACKED ctrl;
341
342 u8 data;
343} PACKED;
344
345struct bcm3510_hab_cmd_tune {
346 u8 length;
347 u8 clock_width;
348 u8 misc;
349 u8 TUNCTL_state;
350
351 struct bcm3510_hab_cmd_tune_ctrl_data_pair ctl_dat[16];
352} PACKED;
353
354#define CMD_STATUS 0x38
355#define MSGID_STATUS1 0x08
356struct bcm3510_hab_cmd_status1 {
357 struct {
358 u8 EQ_MODE :4;
359 u8 reserved :2;
360 u8 QRE :1; /* if QSE and the spectrum is inversed */
361 u8 QSE :1; /* automatic spectral inversion */
362 } PACKED STATUS0;
363
364 struct {
365 u8 RECEIVER_LOCK :1;
366 u8 FEC_LOCK :1;
367 u8 OUT_PLL_LOCK :1;
368 u8 reserved :5;
369 } PACKED STATUS1;
370
371 struct {
372 u8 reserved :2;
373 u8 BW :1;
374 u8 NTE :1; /* NTSC filter sweep enabled */
375 u8 AQI :1; /* currently acquiring */
376 u8 FA :1; /* fast acquisition */
377 u8 ARI :1; /* auto reacquire */
378 u8 TI :1; /* programming the tuner */
379 } PACKED STATUS2;
380 u8 STATUS3;
381 u8 SNR_EST0;
382 u8 SNR_EST1;
383 u8 TUNER_FREQ0;
384 u8 TUNER_FREQ1;
385 u8 TUNER_FREQ2;
386 u8 TUNER_FREQ3;
387 u8 SYM_RATE0;
388 u8 SYM_RATE1;
389 u8 SYM_RATE2;
390 u8 SYM_RATE3;
391 u8 SYM_OFFSET0;
392 u8 SYM_OFFSET1;
393 u8 SYM_ERROR0;
394 u8 SYM_ERROR1;
395 u8 IF_FREQ0;
396 u8 IF_FREQ1;
397 u8 IF_FREQ2;
398 u8 IF_FREQ3;
399 u8 IF_OFFSET0;
400 u8 IF_OFFSET1;
401 u8 IF_ERROR0;
402 u8 IF_ERROR1;
403 u8 NTSC_FILTER0;
404 u8 NTSC_FILTER1;
405 u8 NTSC_FILTER2;
406 u8 NTSC_FILTER3;
407 u8 NTSC_OFFSET0;
408 u8 NTSC_OFFSET1;
409 u8 NTSC_ERROR0;
410 u8 NTSC_ERROR1;
411 u8 INT_AGC_LEVEL0;
412 u8 INT_AGC_LEVEL1;
413 u8 EXT_AGC_LEVEL0;
414 u8 EXT_AGC_LEVEL1;
415} PACKED;
416
417#define MSGID_STATUS2 0x14
418struct bcm3510_hab_cmd_status2 {
419 struct {
420 u8 EQ_MODE :4;
421 u8 reserved :2;
422 u8 QRE :1;
423 u8 QSR :1;
424 } PACKED STATUS0;
425 struct {
426 u8 RL :1;
427 u8 FL :1;
428 u8 OL :1;
429 u8 reserved :5;
430 } PACKED STATUS1;
431 u8 SYMBOL_RATE0;
432 u8 SYMBOL_RATE1;
433 u8 SYMBOL_RATE2;
434 u8 SYMBOL_RATE3;
435 u8 LDCERC0;
436 u8 LDCERC1;
437 u8 LDCERC2;
438 u8 LDCERC3;
439 u8 LDUERC0;
440 u8 LDUERC1;
441 u8 LDUERC2;
442 u8 LDUERC3;
443 u8 LDBER0;
444 u8 LDBER1;
445 u8 LDBER2;
446 u8 LDBER3;
447 struct {
448 u8 MODE_TYPE :4; /* acquire mode 0 */
449 u8 reservd :4;
450 } MODE_TYPE;
451 u8 SNR_EST0;
452 u8 SNR_EST1;
453 u8 SIGNAL;
454} PACKED;
455
456#define CMD_SET_RF_BW_NOT_LISTED 0x3f
457#define MSGID_SET_RF_BW_NOT_LISTED 0x11
458/* TODO */
459
460#endif