diff options
author | Johannes Stezenbach <js@linuxtv.org> | 2005-06-24 01:02:41 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-06-24 03:05:31 -0400 |
commit | 55f51efdb696ff6e9d2056377d05268a97f3d4e4 (patch) | |
tree | 980d8960fecb4db3bf337776bc2f53401e103bdf /drivers/media | |
parent | cc89c229d9d7ec63cd33e960c20e75b77bc987d0 (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/Kconfig | 1 | ||||
-rw-r--r-- | drivers/media/dvb/b2c2/flexcop-fe-tuner.c | 26 | ||||
-rw-r--r-- | drivers/media/dvb/b2c2/flexcop-misc.c | 11 | ||||
-rw-r--r-- | drivers/media/dvb/b2c2/flexcop-reg.h | 3 | ||||
-rw-r--r-- | drivers/media/dvb/frontends/Kconfig | 8 | ||||
-rw-r--r-- | drivers/media/dvb/frontends/Makefile | 1 | ||||
-rw-r--r-- | drivers/media/dvb/frontends/bcm3510.c | 853 | ||||
-rw-r--r-- | drivers/media/dvb/frontends/bcm3510.h | 40 | ||||
-rw-r--r-- | drivers/media/dvb/frontends/bcm3510_priv.h | 460 |
9 files changed, 1389 insertions, 14 deletions
diff --git a/drivers/media/dvb/b2c2/Kconfig b/drivers/media/dvb/b2c2/Kconfig index 99bd675df95..fafd0ab3a28 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 71be400e9ae..0410cc96a48 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 | ||
287 | static struct mt352_config samsung_tdtc9251dh0_config = { | 288 | static 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 | ||
294 | static int nxt2002_request_firmware(struct dvb_frontend* fe, const struct firmware **fw, char* name) | 294 | static 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 | ||
300 | static struct nxt2002_config samsung_tbmv_config = { | 300 | static 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 | |||
305 | static struct bcm3510_config air2pc_atsc_first_gen_config = { | ||
306 | .demod_address = 0x0f, | ||
307 | .request_firmware = flexcop_fe_request_firmware, | ||
303 | }; | 308 | }; |
304 | 309 | ||
305 | static int skystar23_samsung_tbdu18132_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params) | 310 | static 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 19e06da4677..23082545651 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 | ||
46 | const char *flexcop_device_names[] = { | 46 | const 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 | ||
55 | const char *flexcop_bus_names[] = { | 56 | const char *flexcop_bus_names[] = { |
diff --git a/drivers/media/dvb/b2c2/flexcop-reg.h b/drivers/media/dvb/b2c2/flexcop-reg.h index 5e131be55cb..75b50f21afe 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[]; | |||
21 | typedef enum { | 21 | typedef 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 75fb556ec01..b4fddf513eb 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 | ||
176 | config 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 | |||
176 | endmenu | 184 | endmenu |
diff --git a/drivers/media/dvb/frontends/Makefile b/drivers/media/dvb/frontends/Makefile index 7f8784870ea..91d6d3576d3 100644 --- a/drivers/media/dvb/frontends/Makefile +++ b/drivers/media/dvb/frontends/Makefile | |||
@@ -28,3 +28,4 @@ obj-$(CONFIG_DVB_STV0297) += stv0297.o | |||
28 | obj-$(CONFIG_DVB_NXT2002) += nxt2002.o | 28 | obj-$(CONFIG_DVB_NXT2002) += nxt2002.o |
29 | obj-$(CONFIG_DVB_OR51211) += or51211.o | 29 | obj-$(CONFIG_DVB_OR51211) += or51211.o |
30 | obj-$(CONFIG_DVB_OR51132) += or51132.o | 30 | obj-$(CONFIG_DVB_OR51132) += or51132.o |
31 | obj-$(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 00000000000..f5fdc5c3e60 --- /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 | |||
44 | struct 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 | |||
61 | static int debug; | ||
62 | module_param(debug, int, 0644); | ||
63 | MODULE_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 */ | ||
76 | static 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 | |||
99 | static 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 = ®, .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 | |||
121 | static 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 | |||
126 | static 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 */ | ||
132 | static 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 | |||
149 | static 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 | |||
200 | static 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); | ||
225 | error: | ||
226 | up(&st->hab_sem); | ||
227 | return ret; | ||
228 | } | ||
229 | |||
230 | #if 0 | ||
231 | /* not needed, we use a semaphore to prevent HAB races */ | ||
232 | static 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 | |||
250 | static 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 | |||
267 | static 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 | |||
277 | static 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 | |||
301 | static 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 | |||
310 | static 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 | |||
318 | static 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 | |||
338 | static 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 */ | ||
348 | static 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 | |||
437 | static 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 | |||
480 | static 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 | |||
566 | static int bcm3510_sleep(struct dvb_frontend* fe) | ||
567 | { | ||
568 | return 0; | ||
569 | } | ||
570 | |||
571 | static 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 | |||
579 | static 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 | |||
591 | static 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 | |||
610 | static 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 | |||
641 | static 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 */ | ||
659 | static 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 | |||
682 | static 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 | |||
706 | static 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 | |||
739 | static 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 | |||
772 | static struct dvb_frontend_ops bcm3510_ops; | ||
773 | |||
774 | struct 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 | |||
814 | error: | ||
815 | kfree(state); | ||
816 | return NULL; | ||
817 | } | ||
818 | EXPORT_SYMBOL(bcm3510_attach); | ||
819 | |||
820 | static 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 | |||
851 | MODULE_DESCRIPTION("Broadcom BCM3510 ATSC (8VSB/16VSB & ITU J83 AnnexB FEC QAM64/256) demodulator driver"); | ||
852 | MODULE_AUTHOR("Patrick Boettcher <patrick.boettcher@desy.de>"); | ||
853 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/media/dvb/frontends/bcm3510.h b/drivers/media/dvb/frontends/bcm3510.h new file mode 100644 index 00000000000..80f5d0953d0 --- /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 | |||
28 | struct 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 | |||
37 | extern 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 00000000000..3bb1bc2a04f --- /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 | |||
38 | typedef 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 | ||
171 | struct 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 | ||
187 | struct 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 | ||
212 | struct 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 | ||
264 | struct 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 | ||
273 | struct 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 | ||
283 | struct 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 | ||
289 | struct 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 | ||
296 | struct 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 | ||
306 | struct bcm3510_hab_cmd_bert_control { | ||
307 | u8 BE :1; | ||
308 | u8 unused :7; | ||
309 | } PACKED; | ||
310 | |||
311 | #define MSGID_TRI_STATE 0x2e | ||
312 | struct 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 | ||
324 | struct 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 | |||
345 | struct 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 | ||
356 | struct 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 | ||
418 | struct 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 | ||