diff options
-rw-r--r-- | drivers/media/dvb/frontends/Kconfig | 5 | ||||
-rw-r--r-- | drivers/media/dvb/frontends/Makefile | 1 | ||||
-rw-r--r-- | drivers/media/dvb/frontends/af9033.c | 706 | ||||
-rw-r--r-- | drivers/media/dvb/frontends/af9033.h | 73 | ||||
-rw-r--r-- | drivers/media/dvb/frontends/af9033_priv.h | 242 |
5 files changed, 1027 insertions, 0 deletions
diff --git a/drivers/media/dvb/frontends/Kconfig b/drivers/media/dvb/frontends/Kconfig index 21246707fbfb..e11adb64e9e6 100644 --- a/drivers/media/dvb/frontends/Kconfig +++ b/drivers/media/dvb/frontends/Kconfig | |||
@@ -713,6 +713,11 @@ config DVB_M88RS2000 | |||
713 | A DVB-S tuner module. | 713 | A DVB-S tuner module. |
714 | Say Y when you want to support this frontend. | 714 | Say Y when you want to support this frontend. |
715 | 715 | ||
716 | config DVB_AF9033 | ||
717 | tristate "Afatech AF9033 DVB-T demodulator" | ||
718 | depends on DVB_CORE && I2C | ||
719 | default m if DVB_FE_CUSTOMISE | ||
720 | |||
716 | comment "Tools to develop new frontends" | 721 | comment "Tools to develop new frontends" |
717 | 722 | ||
718 | config DVB_DUMMY_FE | 723 | config DVB_DUMMY_FE |
diff --git a/drivers/media/dvb/frontends/Makefile b/drivers/media/dvb/frontends/Makefile index 86fa808bf589..6ca75578ecac 100644 --- a/drivers/media/dvb/frontends/Makefile +++ b/drivers/media/dvb/frontends/Makefile | |||
@@ -98,4 +98,5 @@ obj-$(CONFIG_DVB_A8293) += a8293.o | |||
98 | obj-$(CONFIG_DVB_TDA10071) += tda10071.o | 98 | obj-$(CONFIG_DVB_TDA10071) += tda10071.o |
99 | obj-$(CONFIG_DVB_RTL2830) += rtl2830.o | 99 | obj-$(CONFIG_DVB_RTL2830) += rtl2830.o |
100 | obj-$(CONFIG_DVB_M88RS2000) += m88rs2000.o | 100 | obj-$(CONFIG_DVB_M88RS2000) += m88rs2000.o |
101 | obj-$(CONFIG_DVB_AF9033) += af9033.o | ||
101 | 102 | ||
diff --git a/drivers/media/dvb/frontends/af9033.c b/drivers/media/dvb/frontends/af9033.c new file mode 100644 index 000000000000..161bbe5f2e3f --- /dev/null +++ b/drivers/media/dvb/frontends/af9033.c | |||
@@ -0,0 +1,706 @@ | |||
1 | /* | ||
2 | * Afatech AF9033 demodulator driver | ||
3 | * | ||
4 | * Copyright (C) 2009 Antti Palosaari <crope@iki.fi> | ||
5 | * Copyright (C) 2012 Antti Palosaari <crope@iki.fi> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License as published by | ||
9 | * the Free Software Foundation; either version 2 of the License, or | ||
10 | * (at your option) any later version. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, | ||
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
15 | * GNU General Public License for more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU General Public License along | ||
18 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
19 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | ||
20 | */ | ||
21 | |||
22 | #include "af9033_priv.h" | ||
23 | |||
24 | struct af9033_state { | ||
25 | struct i2c_adapter *i2c; | ||
26 | struct dvb_frontend fe; | ||
27 | struct af9033_config cfg; | ||
28 | |||
29 | u32 bandwidth_hz; | ||
30 | bool ts_mode_parallel; | ||
31 | bool ts_mode_serial; | ||
32 | }; | ||
33 | |||
34 | /* write multiple registers */ | ||
35 | static int af9033_wr_regs(struct af9033_state *state, u32 reg, const u8 *val, | ||
36 | int len) | ||
37 | { | ||
38 | int ret; | ||
39 | u8 buf[3 + len]; | ||
40 | struct i2c_msg msg[1] = { | ||
41 | { | ||
42 | .addr = state->cfg.i2c_addr, | ||
43 | .flags = 0, | ||
44 | .len = sizeof(buf), | ||
45 | .buf = buf, | ||
46 | } | ||
47 | }; | ||
48 | |||
49 | buf[0] = (reg >> 16) & 0xff; | ||
50 | buf[1] = (reg >> 8) & 0xff; | ||
51 | buf[2] = (reg >> 0) & 0xff; | ||
52 | memcpy(&buf[3], val, len); | ||
53 | |||
54 | ret = i2c_transfer(state->i2c, msg, 1); | ||
55 | if (ret == 1) { | ||
56 | ret = 0; | ||
57 | } else { | ||
58 | printk(KERN_WARNING "%s: i2c wr failed=%d reg=%06x len=%d\n", | ||
59 | __func__, ret, reg, len); | ||
60 | ret = -EREMOTEIO; | ||
61 | } | ||
62 | |||
63 | return ret; | ||
64 | } | ||
65 | |||
66 | /* read multiple registers */ | ||
67 | static int af9033_rd_regs(struct af9033_state *state, u32 reg, u8 *val, int len) | ||
68 | { | ||
69 | int ret; | ||
70 | u8 buf[3] = { (reg >> 16) & 0xff, (reg >> 8) & 0xff, | ||
71 | (reg >> 0) & 0xff }; | ||
72 | struct i2c_msg msg[2] = { | ||
73 | { | ||
74 | .addr = state->cfg.i2c_addr, | ||
75 | .flags = 0, | ||
76 | .len = sizeof(buf), | ||
77 | .buf = buf | ||
78 | }, { | ||
79 | .addr = state->cfg.i2c_addr, | ||
80 | .flags = I2C_M_RD, | ||
81 | .len = len, | ||
82 | .buf = val | ||
83 | } | ||
84 | }; | ||
85 | |||
86 | ret = i2c_transfer(state->i2c, msg, 2); | ||
87 | if (ret == 2) { | ||
88 | ret = 0; | ||
89 | } else { | ||
90 | printk(KERN_WARNING "%s: i2c rd failed=%d reg=%06x len=%d\n", | ||
91 | __func__, ret, reg, len); | ||
92 | ret = -EREMOTEIO; | ||
93 | } | ||
94 | |||
95 | return ret; | ||
96 | } | ||
97 | |||
98 | |||
99 | /* write single register */ | ||
100 | static int af9033_wr_reg(struct af9033_state *state, u32 reg, u8 val) | ||
101 | { | ||
102 | return af9033_wr_regs(state, reg, &val, 1); | ||
103 | } | ||
104 | |||
105 | /* read single register */ | ||
106 | static int af9033_rd_reg(struct af9033_state *state, u32 reg, u8 *val) | ||
107 | { | ||
108 | return af9033_rd_regs(state, reg, val, 1); | ||
109 | } | ||
110 | |||
111 | /* write single register with mask */ | ||
112 | static int af9033_wr_reg_mask(struct af9033_state *state, u32 reg, u8 val, | ||
113 | u8 mask) | ||
114 | { | ||
115 | int ret; | ||
116 | u8 tmp; | ||
117 | |||
118 | /* no need for read if whole reg is written */ | ||
119 | if (mask != 0xff) { | ||
120 | ret = af9033_rd_regs(state, reg, &tmp, 1); | ||
121 | if (ret) | ||
122 | return ret; | ||
123 | |||
124 | val &= mask; | ||
125 | tmp &= ~mask; | ||
126 | val |= tmp; | ||
127 | } | ||
128 | |||
129 | return af9033_wr_regs(state, reg, &val, 1); | ||
130 | } | ||
131 | |||
132 | /* read single register with mask */ | ||
133 | static int af9033_rd_reg_mask(struct af9033_state *state, u32 reg, u8 *val, | ||
134 | u8 mask) | ||
135 | { | ||
136 | int ret, i; | ||
137 | u8 tmp; | ||
138 | |||
139 | ret = af9033_rd_regs(state, reg, &tmp, 1); | ||
140 | if (ret) | ||
141 | return ret; | ||
142 | |||
143 | tmp &= mask; | ||
144 | |||
145 | /* find position of the first bit */ | ||
146 | for (i = 0; i < 8; i++) { | ||
147 | if ((mask >> i) & 0x01) | ||
148 | break; | ||
149 | } | ||
150 | *val = tmp >> i; | ||
151 | |||
152 | return 0; | ||
153 | } | ||
154 | |||
155 | static u32 af9033_div(u32 a, u32 b, u32 x) | ||
156 | { | ||
157 | u32 r = 0, c = 0, i; | ||
158 | |||
159 | pr_debug("%s: a=%d b=%d x=%d\n", __func__, a, b, x); | ||
160 | |||
161 | if (a > b) { | ||
162 | c = a / b; | ||
163 | a = a - c * b; | ||
164 | } | ||
165 | |||
166 | for (i = 0; i < x; i++) { | ||
167 | if (a >= b) { | ||
168 | r += 1; | ||
169 | a -= b; | ||
170 | } | ||
171 | a <<= 1; | ||
172 | r <<= 1; | ||
173 | } | ||
174 | r = (c << (u32)x) + r; | ||
175 | |||
176 | pr_debug("%s: a=%d b=%d x=%d r=%d r=%x\n", __func__, a, b, x, r, r); | ||
177 | |||
178 | return r; | ||
179 | } | ||
180 | |||
181 | static void af9033_release(struct dvb_frontend *fe) | ||
182 | { | ||
183 | struct af9033_state *state = fe->demodulator_priv; | ||
184 | |||
185 | kfree(state); | ||
186 | } | ||
187 | |||
188 | static int af9033_init(struct dvb_frontend *fe) | ||
189 | { | ||
190 | struct af9033_state *state = fe->demodulator_priv; | ||
191 | int ret, i, len; | ||
192 | const struct reg_val *init; | ||
193 | u8 buf[4]; | ||
194 | u32 adc_cw, clock_cw; | ||
195 | struct reg_val_mask tab[] = { | ||
196 | { 0x80fb24, 0x00, 0x08 }, | ||
197 | { 0x80004c, 0x00, 0xff }, | ||
198 | { 0x00f641, state->cfg.tuner, 0xff }, | ||
199 | { 0x80f5ca, 0x01, 0x01 }, | ||
200 | { 0x80f715, 0x01, 0x01 }, | ||
201 | { 0x00f41f, 0x04, 0x04 }, | ||
202 | { 0x00f41a, 0x01, 0x01 }, | ||
203 | { 0x80f731, 0x00, 0x01 }, | ||
204 | { 0x00d91e, 0x00, 0x01 }, | ||
205 | { 0x00d919, 0x00, 0x01 }, | ||
206 | { 0x80f732, 0x00, 0x01 }, | ||
207 | { 0x00d91f, 0x00, 0x01 }, | ||
208 | { 0x00d91a, 0x00, 0x01 }, | ||
209 | { 0x80f730, 0x00, 0x01 }, | ||
210 | { 0x80f778, 0x00, 0xff }, | ||
211 | { 0x80f73c, 0x01, 0x01 }, | ||
212 | { 0x80f776, 0x00, 0x01 }, | ||
213 | { 0x00d8fd, 0x01, 0xff }, | ||
214 | { 0x00d830, 0x01, 0xff }, | ||
215 | { 0x00d831, 0x00, 0xff }, | ||
216 | { 0x00d832, 0x00, 0xff }, | ||
217 | { 0x80f985, state->ts_mode_serial, 0x01 }, | ||
218 | { 0x80f986, state->ts_mode_parallel, 0x01 }, | ||
219 | { 0x00d827, 0x00, 0xff }, | ||
220 | { 0x00d829, 0x00, 0xff }, | ||
221 | }; | ||
222 | |||
223 | /* program clock control */ | ||
224 | clock_cw = af9033_div(state->cfg.clock, 1000000ul, 19ul); | ||
225 | buf[0] = (clock_cw >> 0) & 0xff; | ||
226 | buf[1] = (clock_cw >> 8) & 0xff; | ||
227 | buf[2] = (clock_cw >> 16) & 0xff; | ||
228 | buf[3] = (clock_cw >> 24) & 0xff; | ||
229 | |||
230 | pr_debug("%s: clock=%d clock_cw=%08x\n", __func__, state->cfg.clock, | ||
231 | clock_cw); | ||
232 | |||
233 | ret = af9033_wr_regs(state, 0x800025, buf, 4); | ||
234 | if (ret < 0) | ||
235 | goto err; | ||
236 | |||
237 | /* program ADC control */ | ||
238 | for (i = 0; i < ARRAY_SIZE(clock_adc_lut); i++) { | ||
239 | if (clock_adc_lut[i].clock == state->cfg.clock) | ||
240 | break; | ||
241 | } | ||
242 | |||
243 | adc_cw = af9033_div(clock_adc_lut[i].adc, 1000000ul, 19ul); | ||
244 | buf[0] = (adc_cw >> 0) & 0xff; | ||
245 | buf[1] = (adc_cw >> 8) & 0xff; | ||
246 | buf[2] = (adc_cw >> 16) & 0xff; | ||
247 | |||
248 | pr_debug("%s: adc=%d adc_cw=%06x\n", __func__, clock_adc_lut[i].adc, | ||
249 | adc_cw); | ||
250 | |||
251 | ret = af9033_wr_regs(state, 0x80f1cd, buf, 3); | ||
252 | if (ret < 0) | ||
253 | goto err; | ||
254 | |||
255 | /* program register table */ | ||
256 | for (i = 0; i < ARRAY_SIZE(tab); i++) { | ||
257 | ret = af9033_wr_reg_mask(state, tab[i].reg, tab[i].val, | ||
258 | tab[i].mask); | ||
259 | if (ret < 0) | ||
260 | goto err; | ||
261 | } | ||
262 | |||
263 | /* settings for TS interface */ | ||
264 | if (state->cfg.ts_mode == AF9033_TS_MODE_USB) { | ||
265 | ret = af9033_wr_reg_mask(state, 0x80f9a5, 0x00, 0x01); | ||
266 | if (ret < 0) | ||
267 | goto err; | ||
268 | |||
269 | ret = af9033_wr_reg_mask(state, 0x80f9b5, 0x01, 0x01); | ||
270 | if (ret < 0) | ||
271 | goto err; | ||
272 | } else { | ||
273 | ret = af9033_wr_reg_mask(state, 0x80f990, 0x00, 0x01); | ||
274 | if (ret < 0) | ||
275 | goto err; | ||
276 | |||
277 | ret = af9033_wr_reg_mask(state, 0x80f9b5, 0x00, 0x01); | ||
278 | if (ret < 0) | ||
279 | goto err; | ||
280 | } | ||
281 | |||
282 | /* load OFSM settings */ | ||
283 | pr_debug("%s: load ofsm settings\n", __func__); | ||
284 | len = ARRAY_SIZE(ofsm_init); | ||
285 | init = ofsm_init; | ||
286 | for (i = 0; i < len; i++) { | ||
287 | ret = af9033_wr_reg(state, init[i].reg, init[i].val); | ||
288 | if (ret < 0) | ||
289 | goto err; | ||
290 | } | ||
291 | |||
292 | /* load tuner specific settings */ | ||
293 | pr_debug("%s: load tuner specific settings\n", | ||
294 | __func__); | ||
295 | switch (state->cfg.tuner) { | ||
296 | case AF9033_TUNER_TUA9001: | ||
297 | len = ARRAY_SIZE(tuner_init_tua9001); | ||
298 | init = tuner_init_tua9001; | ||
299 | break; | ||
300 | default: | ||
301 | pr_debug("%s: unsupported tuner ID=%d\n", __func__, | ||
302 | state->cfg.tuner); | ||
303 | ret = -ENODEV; | ||
304 | goto err; | ||
305 | } | ||
306 | |||
307 | for (i = 0; i < len; i++) { | ||
308 | ret = af9033_wr_reg(state, init[i].reg, init[i].val); | ||
309 | if (ret < 0) | ||
310 | goto err; | ||
311 | } | ||
312 | |||
313 | state->bandwidth_hz = 0; /* force to program all parameters */ | ||
314 | |||
315 | return 0; | ||
316 | |||
317 | err: | ||
318 | pr_debug("%s: failed=%d\n", __func__, ret); | ||
319 | |||
320 | return ret; | ||
321 | } | ||
322 | |||
323 | static int af9033_sleep(struct dvb_frontend *fe) | ||
324 | { | ||
325 | struct af9033_state *state = fe->demodulator_priv; | ||
326 | int ret, i; | ||
327 | u8 tmp; | ||
328 | |||
329 | ret = af9033_wr_reg(state, 0x80004c, 1); | ||
330 | if (ret < 0) | ||
331 | goto err; | ||
332 | |||
333 | ret = af9033_wr_reg(state, 0x800000, 0); | ||
334 | if (ret < 0) | ||
335 | goto err; | ||
336 | |||
337 | for (i = 100, tmp = 1; i && tmp; i--) { | ||
338 | ret = af9033_rd_reg(state, 0x80004c, &tmp); | ||
339 | if (ret < 0) | ||
340 | goto err; | ||
341 | |||
342 | usleep_range(200, 10000); | ||
343 | } | ||
344 | |||
345 | pr_debug("%s: loop=%d", __func__, i); | ||
346 | |||
347 | if (i == 0) { | ||
348 | ret = -ETIMEDOUT; | ||
349 | goto err; | ||
350 | } | ||
351 | |||
352 | ret = af9033_wr_reg_mask(state, 0x80fb24, 0x08, 0x08); | ||
353 | if (ret < 0) | ||
354 | goto err; | ||
355 | |||
356 | /* prevent current leak (?) */ | ||
357 | if (state->cfg.ts_mode == AF9033_TS_MODE_SERIAL) { | ||
358 | /* enable parallel TS */ | ||
359 | ret = af9033_wr_reg_mask(state, 0x00d917, 0x00, 0x01); | ||
360 | if (ret < 0) | ||
361 | goto err; | ||
362 | |||
363 | ret = af9033_wr_reg_mask(state, 0x00d916, 0x01, 0x01); | ||
364 | if (ret < 0) | ||
365 | goto err; | ||
366 | } | ||
367 | |||
368 | return 0; | ||
369 | |||
370 | err: | ||
371 | pr_debug("%s: failed=%d\n", __func__, ret); | ||
372 | |||
373 | return ret; | ||
374 | } | ||
375 | |||
376 | static int af9033_get_tune_settings(struct dvb_frontend *fe, | ||
377 | struct dvb_frontend_tune_settings *fesettings) | ||
378 | { | ||
379 | fesettings->min_delay_ms = 800; | ||
380 | fesettings->step_size = 0; | ||
381 | fesettings->max_drift = 0; | ||
382 | |||
383 | return 0; | ||
384 | } | ||
385 | |||
386 | static int af9033_set_frontend(struct dvb_frontend *fe) | ||
387 | { | ||
388 | struct af9033_state *state = fe->demodulator_priv; | ||
389 | struct dtv_frontend_properties *c = &fe->dtv_property_cache; | ||
390 | int ret, i; | ||
391 | u8 tmp, buf[3], bandwidth_reg_val; | ||
392 | u32 if_frequency, freq_cw; | ||
393 | |||
394 | pr_debug("%s: frequency=%d bandwidth_hz=%d\n", __func__, c->frequency, | ||
395 | c->bandwidth_hz); | ||
396 | |||
397 | /* check bandwidth */ | ||
398 | switch (c->bandwidth_hz) { | ||
399 | case 6000000: | ||
400 | bandwidth_reg_val = 0x00; | ||
401 | break; | ||
402 | case 7000000: | ||
403 | bandwidth_reg_val = 0x01; | ||
404 | break; | ||
405 | case 8000000: | ||
406 | bandwidth_reg_val = 0x02; | ||
407 | break; | ||
408 | default: | ||
409 | pr_debug("%s: invalid bandwidth_hz\n", __func__); | ||
410 | ret = -EINVAL; | ||
411 | goto err; | ||
412 | } | ||
413 | |||
414 | /* program tuner */ | ||
415 | if (fe->ops.tuner_ops.set_params) | ||
416 | fe->ops.tuner_ops.set_params(fe); | ||
417 | |||
418 | /* program CFOE coefficients */ | ||
419 | if (c->bandwidth_hz != state->bandwidth_hz) { | ||
420 | for (i = 0; i < ARRAY_SIZE(coeff_lut); i++) { | ||
421 | if (coeff_lut[i].clock == state->cfg.clock && | ||
422 | coeff_lut[i].bandwidth_hz == c->bandwidth_hz) { | ||
423 | break; | ||
424 | } | ||
425 | } | ||
426 | ret = af9033_wr_regs(state, 0x800001, | ||
427 | coeff_lut[i].val, sizeof(coeff_lut[i].val)); | ||
428 | } | ||
429 | |||
430 | /* program frequency control */ | ||
431 | if (c->bandwidth_hz != state->bandwidth_hz) { | ||
432 | /* get used IF frequency */ | ||
433 | if (fe->ops.tuner_ops.get_if_frequency) | ||
434 | fe->ops.tuner_ops.get_if_frequency(fe, &if_frequency); | ||
435 | else | ||
436 | if_frequency = 0; | ||
437 | |||
438 | /* FIXME: we support only Zero-IF currently */ | ||
439 | if (if_frequency != 0) { | ||
440 | pr_debug("%s: only Zero-IF supported currently\n", | ||
441 | __func__); | ||
442 | |||
443 | ret = -ENODEV; | ||
444 | goto err; | ||
445 | } | ||
446 | |||
447 | freq_cw = 0; | ||
448 | buf[0] = (freq_cw >> 0) & 0xff; | ||
449 | buf[1] = (freq_cw >> 8) & 0xff; | ||
450 | buf[2] = (freq_cw >> 16) & 0x7f; | ||
451 | ret = af9033_wr_regs(state, 0x800029, buf, 3); | ||
452 | if (ret < 0) | ||
453 | goto err; | ||
454 | |||
455 | state->bandwidth_hz = c->bandwidth_hz; | ||
456 | } | ||
457 | |||
458 | ret = af9033_wr_reg_mask(state, 0x80f904, bandwidth_reg_val, 0x03); | ||
459 | if (ret < 0) | ||
460 | goto err; | ||
461 | |||
462 | ret = af9033_wr_reg(state, 0x800040, 0x00); | ||
463 | if (ret < 0) | ||
464 | goto err; | ||
465 | |||
466 | ret = af9033_wr_reg(state, 0x800047, 0x00); | ||
467 | if (ret < 0) | ||
468 | goto err; | ||
469 | |||
470 | ret = af9033_wr_reg_mask(state, 0x80f999, 0x00, 0x01); | ||
471 | if (ret < 0) | ||
472 | goto err; | ||
473 | |||
474 | if (c->frequency <= 230000000) | ||
475 | tmp = 0x00; /* VHF */ | ||
476 | else | ||
477 | tmp = 0x01; /* UHF */ | ||
478 | |||
479 | ret = af9033_wr_reg(state, 0x80004b, tmp); | ||
480 | if (ret < 0) | ||
481 | goto err; | ||
482 | |||
483 | ret = af9033_wr_reg(state, 0x800000, 0x00); | ||
484 | if (ret < 0) | ||
485 | goto err; | ||
486 | |||
487 | return 0; | ||
488 | |||
489 | err: | ||
490 | pr_debug("%s: failed=%d\n", __func__, ret); | ||
491 | |||
492 | return ret; | ||
493 | } | ||
494 | |||
495 | static int af9033_read_status(struct dvb_frontend *fe, fe_status_t *status) | ||
496 | { | ||
497 | struct af9033_state *state = fe->demodulator_priv; | ||
498 | int ret; | ||
499 | u8 tmp; | ||
500 | |||
501 | *status = 0; | ||
502 | |||
503 | /* radio channel status, 0=no result, 1=has signal, 2=no signal */ | ||
504 | ret = af9033_rd_reg(state, 0x800047, &tmp); | ||
505 | if (ret < 0) | ||
506 | goto err; | ||
507 | |||
508 | /* has signal */ | ||
509 | if (tmp == 0x01) | ||
510 | *status |= FE_HAS_SIGNAL; | ||
511 | |||
512 | if (tmp != 0x02) { | ||
513 | /* TPS lock */ | ||
514 | ret = af9033_rd_reg_mask(state, 0x80f5a9, &tmp, 0x01); | ||
515 | if (ret < 0) | ||
516 | goto err; | ||
517 | |||
518 | if (tmp) | ||
519 | *status |= FE_HAS_SIGNAL | FE_HAS_CARRIER | | ||
520 | FE_HAS_VITERBI; | ||
521 | |||
522 | /* full lock */ | ||
523 | ret = af9033_rd_reg_mask(state, 0x80f999, &tmp, 0x01); | ||
524 | if (ret < 0) | ||
525 | goto err; | ||
526 | |||
527 | if (tmp) | ||
528 | *status |= FE_HAS_SIGNAL | FE_HAS_CARRIER | | ||
529 | FE_HAS_VITERBI | FE_HAS_SYNC | | ||
530 | FE_HAS_LOCK; | ||
531 | } | ||
532 | |||
533 | return 0; | ||
534 | |||
535 | err: | ||
536 | pr_debug("%s: failed=%d\n", __func__, ret); | ||
537 | |||
538 | return ret; | ||
539 | } | ||
540 | |||
541 | static int af9033_read_snr(struct dvb_frontend *fe, u16 *snr) | ||
542 | { | ||
543 | *snr = 0; | ||
544 | |||
545 | return 0; | ||
546 | } | ||
547 | |||
548 | static int af9033_read_signal_strength(struct dvb_frontend *fe, u16 *strength) | ||
549 | { | ||
550 | struct af9033_state *state = fe->demodulator_priv; | ||
551 | int ret; | ||
552 | u8 strength2; | ||
553 | |||
554 | /* read signal strength of 0-100 scale */ | ||
555 | ret = af9033_rd_reg(state, 0x800048, &strength2); | ||
556 | if (ret < 0) | ||
557 | goto err; | ||
558 | |||
559 | /* scale value to 0x0000-0xffff */ | ||
560 | *strength = strength2 * 0xffff / 100; | ||
561 | |||
562 | return 0; | ||
563 | |||
564 | err: | ||
565 | pr_debug("%s: failed=%d\n", __func__, ret); | ||
566 | |||
567 | return ret; | ||
568 | } | ||
569 | |||
570 | static int af9033_read_ber(struct dvb_frontend *fe, u32 *ber) | ||
571 | { | ||
572 | *ber = 0; | ||
573 | |||
574 | return 0; | ||
575 | } | ||
576 | |||
577 | static int af9033_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks) | ||
578 | { | ||
579 | *ucblocks = 0; | ||
580 | |||
581 | return 0; | ||
582 | } | ||
583 | |||
584 | static int af9033_i2c_gate_ctrl(struct dvb_frontend *fe, int enable) | ||
585 | { | ||
586 | struct af9033_state *state = fe->demodulator_priv; | ||
587 | int ret; | ||
588 | |||
589 | pr_debug("%s: enable=%d\n", __func__, enable); | ||
590 | |||
591 | ret = af9033_wr_reg_mask(state, 0x00fa04, enable, 0x01); | ||
592 | if (ret < 0) | ||
593 | goto err; | ||
594 | |||
595 | return 0; | ||
596 | |||
597 | err: | ||
598 | pr_debug("%s: failed=%d\n", __func__, ret); | ||
599 | |||
600 | return ret; | ||
601 | } | ||
602 | |||
603 | static struct dvb_frontend_ops af9033_ops; | ||
604 | |||
605 | struct dvb_frontend *af9033_attach(const struct af9033_config *config, | ||
606 | struct i2c_adapter *i2c) | ||
607 | { | ||
608 | int ret; | ||
609 | struct af9033_state *state; | ||
610 | u8 buf[8]; | ||
611 | |||
612 | pr_debug("%s:\n", __func__); | ||
613 | |||
614 | /* allocate memory for the internal state */ | ||
615 | state = kzalloc(sizeof(struct af9033_state), GFP_KERNEL); | ||
616 | if (state == NULL) | ||
617 | goto err; | ||
618 | |||
619 | /* setup the state */ | ||
620 | state->i2c = i2c; | ||
621 | memcpy(&state->cfg, config, sizeof(struct af9033_config)); | ||
622 | |||
623 | /* firmware version */ | ||
624 | ret = af9033_rd_regs(state, 0x0083e9, &buf[0], 4); | ||
625 | if (ret < 0) | ||
626 | goto err; | ||
627 | |||
628 | ret = af9033_rd_regs(state, 0x804191, &buf[4], 4); | ||
629 | if (ret < 0) | ||
630 | goto err; | ||
631 | |||
632 | printk(KERN_INFO "af9033: firmware version: LINK=%d.%d.%d.%d " \ | ||
633 | "OFDM=%d.%d.%d.%d\n", buf[0], buf[1], buf[2], buf[3], | ||
634 | buf[4], buf[5], buf[6], buf[7]); | ||
635 | |||
636 | /* configure internal TS mode */ | ||
637 | switch (state->cfg.ts_mode) { | ||
638 | case AF9033_TS_MODE_PARALLEL: | ||
639 | state->ts_mode_parallel = true; | ||
640 | break; | ||
641 | case AF9033_TS_MODE_SERIAL: | ||
642 | state->ts_mode_serial = true; | ||
643 | break; | ||
644 | case AF9033_TS_MODE_USB: | ||
645 | /* usb mode for AF9035 */ | ||
646 | default: | ||
647 | break; | ||
648 | } | ||
649 | |||
650 | /* create dvb_frontend */ | ||
651 | memcpy(&state->fe.ops, &af9033_ops, sizeof(struct dvb_frontend_ops)); | ||
652 | state->fe.demodulator_priv = state; | ||
653 | |||
654 | return &state->fe; | ||
655 | |||
656 | err: | ||
657 | kfree(state); | ||
658 | return NULL; | ||
659 | } | ||
660 | EXPORT_SYMBOL(af9033_attach); | ||
661 | |||
662 | static struct dvb_frontend_ops af9033_ops = { | ||
663 | .delsys = { SYS_DVBT }, | ||
664 | .info = { | ||
665 | .name = "Afatech AF9033 (DVB-T)", | ||
666 | .frequency_min = 174000000, | ||
667 | .frequency_max = 862000000, | ||
668 | .frequency_stepsize = 250000, | ||
669 | .frequency_tolerance = 0, | ||
670 | .caps = FE_CAN_FEC_1_2 | | ||
671 | FE_CAN_FEC_2_3 | | ||
672 | FE_CAN_FEC_3_4 | | ||
673 | FE_CAN_FEC_5_6 | | ||
674 | FE_CAN_FEC_7_8 | | ||
675 | FE_CAN_FEC_AUTO | | ||
676 | FE_CAN_QPSK | | ||
677 | FE_CAN_QAM_16 | | ||
678 | FE_CAN_QAM_64 | | ||
679 | FE_CAN_QAM_AUTO | | ||
680 | FE_CAN_TRANSMISSION_MODE_AUTO | | ||
681 | FE_CAN_GUARD_INTERVAL_AUTO | | ||
682 | FE_CAN_HIERARCHY_AUTO | | ||
683 | FE_CAN_RECOVER | | ||
684 | FE_CAN_MUTE_TS | ||
685 | }, | ||
686 | |||
687 | .release = af9033_release, | ||
688 | |||
689 | .init = af9033_init, | ||
690 | .sleep = af9033_sleep, | ||
691 | |||
692 | .get_tune_settings = af9033_get_tune_settings, | ||
693 | .set_frontend = af9033_set_frontend, | ||
694 | |||
695 | .read_status = af9033_read_status, | ||
696 | .read_snr = af9033_read_snr, | ||
697 | .read_signal_strength = af9033_read_signal_strength, | ||
698 | .read_ber = af9033_read_ber, | ||
699 | .read_ucblocks = af9033_read_ucblocks, | ||
700 | |||
701 | .i2c_gate_ctrl = af9033_i2c_gate_ctrl, | ||
702 | }; | ||
703 | |||
704 | MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>"); | ||
705 | MODULE_DESCRIPTION("Afatech AF9033 DVB-T demodulator driver"); | ||
706 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/media/dvb/frontends/af9033.h b/drivers/media/dvb/frontends/af9033.h new file mode 100644 index 000000000000..af8c1e3e30d0 --- /dev/null +++ b/drivers/media/dvb/frontends/af9033.h | |||
@@ -0,0 +1,73 @@ | |||
1 | /* | ||
2 | * Afatech AF9033 demodulator driver | ||
3 | * | ||
4 | * Copyright (C) 2009 Antti Palosaari <crope@iki.fi> | ||
5 | * Copyright (C) 2012 Antti Palosaari <crope@iki.fi> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License as published by | ||
9 | * the Free Software Foundation; either version 2 of the License, or | ||
10 | * (at your option) any later version. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, | ||
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
15 | * GNU General Public License for more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU General Public License along | ||
18 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
19 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | ||
20 | */ | ||
21 | |||
22 | #ifndef AF9033_H | ||
23 | #define AF9033_H | ||
24 | |||
25 | struct af9033_config { | ||
26 | /* | ||
27 | * I2C address | ||
28 | */ | ||
29 | u8 i2c_addr; | ||
30 | |||
31 | /* | ||
32 | * clock Hz | ||
33 | * 12000000, 22000000, 24000000, 34000000, 32000000, 28000000, 26000000, | ||
34 | * 30000000, 36000000, 20480000, 16384000 | ||
35 | */ | ||
36 | u32 clock; | ||
37 | |||
38 | /* | ||
39 | * tuner | ||
40 | */ | ||
41 | #define AF9033_TUNER_TUA9001 0x27 /* Infineon TUA 9001 */ | ||
42 | #define AF9033_TUNER_FC0011 0x28 /* Fitipower FC0011 */ | ||
43 | u8 tuner; | ||
44 | |||
45 | /* | ||
46 | * TS settings | ||
47 | */ | ||
48 | #define AF9033_TS_MODE_USB 0 | ||
49 | #define AF9033_TS_MODE_PARALLEL 1 | ||
50 | #define AF9033_TS_MODE_SERIAL 2 | ||
51 | u8 ts_mode:2; | ||
52 | |||
53 | /* | ||
54 | * input spectrum inversion | ||
55 | */ | ||
56 | bool spec_inv; | ||
57 | }; | ||
58 | |||
59 | |||
60 | #if defined(CONFIG_DVB_AF9033) || \ | ||
61 | (defined(CONFIG_DVB_AF9033_MODULE) && defined(MODULE)) | ||
62 | extern struct dvb_frontend *af9033_attach(const struct af9033_config *config, | ||
63 | struct i2c_adapter *i2c); | ||
64 | #else | ||
65 | static inline struct dvb_frontend *af9033_attach( | ||
66 | const struct af9033_config *config, struct i2c_adapter *i2c) | ||
67 | { | ||
68 | printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); | ||
69 | return NULL; | ||
70 | } | ||
71 | #endif | ||
72 | |||
73 | #endif /* AF9033_H */ | ||
diff --git a/drivers/media/dvb/frontends/af9033_priv.h b/drivers/media/dvb/frontends/af9033_priv.h new file mode 100644 index 000000000000..2bf579d89a83 --- /dev/null +++ b/drivers/media/dvb/frontends/af9033_priv.h | |||
@@ -0,0 +1,242 @@ | |||
1 | /* | ||
2 | * Afatech AF9033 demodulator driver | ||
3 | * | ||
4 | * Copyright (C) 2009 Antti Palosaari <crope@iki.fi> | ||
5 | * Copyright (C) 2012 Antti Palosaari <crope@iki.fi> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License as published by | ||
9 | * the Free Software Foundation; either version 2 of the License, or | ||
10 | * (at your option) any later version. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, | ||
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
15 | * GNU General Public License for more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU General Public License along | ||
18 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
19 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | ||
20 | */ | ||
21 | |||
22 | #ifndef AF9033_PRIV_H | ||
23 | #define AF9033_PRIV_H | ||
24 | |||
25 | #include "dvb_frontend.h" | ||
26 | #include "af9033.h" | ||
27 | |||
28 | struct reg_val { | ||
29 | u32 reg; | ||
30 | u8 val; | ||
31 | }; | ||
32 | |||
33 | struct reg_val_mask { | ||
34 | u32 reg; | ||
35 | u8 val; | ||
36 | u8 mask; | ||
37 | }; | ||
38 | |||
39 | struct coeff { | ||
40 | u32 clock; | ||
41 | u32 bandwidth_hz; | ||
42 | u8 val[36]; | ||
43 | }; | ||
44 | |||
45 | struct clock_adc { | ||
46 | u32 clock; | ||
47 | u32 adc; | ||
48 | }; | ||
49 | |||
50 | /* Xtal clock vs. ADC clock lookup table */ | ||
51 | static const struct clock_adc clock_adc_lut[] = { | ||
52 | { 16384000, 20480000 }, | ||
53 | { 20480000, 20480000 }, | ||
54 | { 36000000, 20250000 }, | ||
55 | { 30000000, 20156250 }, | ||
56 | { 26000000, 20583333 }, | ||
57 | { 28000000, 20416667 }, | ||
58 | { 32000000, 20500000 }, | ||
59 | { 34000000, 20187500 }, | ||
60 | { 24000000, 20500000 }, | ||
61 | { 22000000, 20625000 }, | ||
62 | { 12000000, 20250000 }, | ||
63 | }; | ||
64 | |||
65 | /* pre-calculated coeff lookup table */ | ||
66 | static const struct coeff coeff_lut[] = { | ||
67 | /* 12.000 MHz */ | ||
68 | { 12000000, 8000000, { | ||
69 | 0x01, 0xce, 0x55, 0xc9, 0x00, 0xe7, 0x2a, 0xe4, 0x00, 0x73, | ||
70 | 0x99, 0x0f, 0x00, 0x73, 0x95, 0x72, 0x00, 0x73, 0x91, 0xd5, | ||
71 | 0x00, 0x39, 0xca, 0xb9, 0x00, 0xe7, 0x2a, 0xe4, 0x00, 0x73, | ||
72 | 0x95, 0x72, 0x37, 0x02, 0xce, 0x01 } | ||
73 | }, | ||
74 | { 12000000, 7000000, { | ||
75 | 0x01, 0x94, 0x8b, 0x10, 0x00, 0xca, 0x45, 0x88, 0x00, 0x65, | ||
76 | 0x25, 0xed, 0x00, 0x65, 0x22, 0xc4, 0x00, 0x65, 0x1f, 0x9b, | ||
77 | 0x00, 0x32, 0x91, 0x62, 0x00, 0xca, 0x45, 0x88, 0x00, 0x65, | ||
78 | 0x22, 0xc4, 0x88, 0x02, 0x95, 0x01 } | ||
79 | }, | ||
80 | { 12000000, 6000000, { | ||
81 | 0x01, 0x5a, 0xc0, 0x56, 0x00, 0xad, 0x60, 0x2b, 0x00, 0x56, | ||
82 | 0xb2, 0xcb, 0x00, 0x56, 0xb0, 0x15, 0x00, 0x56, 0xad, 0x60, | ||
83 | 0x00, 0x2b, 0x58, 0x0b, 0x00, 0xad, 0x60, 0x2b, 0x00, 0x56, | ||
84 | 0xb0, 0x15, 0xf4, 0x02, 0x5b, 0x01 } | ||
85 | }, | ||
86 | }; | ||
87 | |||
88 | static const struct reg_val ofsm_init[] = { | ||
89 | { 0x800051, 0x01 }, | ||
90 | { 0x800070, 0x0a }, | ||
91 | { 0x80007e, 0x04 }, | ||
92 | { 0x800081, 0x0a }, | ||
93 | { 0x80008a, 0x01 }, | ||
94 | { 0x80008e, 0x01 }, | ||
95 | { 0x800092, 0x06 }, | ||
96 | { 0x800099, 0x01 }, | ||
97 | { 0x80009f, 0xe1 }, | ||
98 | { 0x8000a0, 0xcf }, | ||
99 | { 0x8000a3, 0x01 }, | ||
100 | { 0x8000a5, 0x01 }, | ||
101 | { 0x8000a6, 0x01 }, | ||
102 | { 0x8000a9, 0x00 }, | ||
103 | { 0x8000aa, 0x01 }, | ||
104 | { 0x8000ab, 0x01 }, | ||
105 | { 0x8000b0, 0x01 }, | ||
106 | { 0x8000c0, 0x05 }, | ||
107 | { 0x8000c4, 0x19 }, | ||
108 | { 0x80f000, 0x0f }, | ||
109 | { 0x80f016, 0x10 }, | ||
110 | { 0x80f017, 0x04 }, | ||
111 | { 0x80f018, 0x05 }, | ||
112 | { 0x80f019, 0x04 }, | ||
113 | { 0x80f01a, 0x05 }, | ||
114 | { 0x80f021, 0x03 }, | ||
115 | { 0x80f022, 0x0a }, | ||
116 | { 0x80f023, 0x0a }, | ||
117 | { 0x80f02b, 0x00 }, | ||
118 | { 0x80f02c, 0x01 }, | ||
119 | { 0x80f064, 0x03 }, | ||
120 | { 0x80f065, 0xf9 }, | ||
121 | { 0x80f066, 0x03 }, | ||
122 | { 0x80f067, 0x01 }, | ||
123 | { 0x80f06f, 0xe0 }, | ||
124 | { 0x80f070, 0x03 }, | ||
125 | { 0x80f072, 0x0f }, | ||
126 | { 0x80f073, 0x03 }, | ||
127 | { 0x80f078, 0x00 }, | ||
128 | { 0x80f087, 0x00 }, | ||
129 | { 0x80f09b, 0x3f }, | ||
130 | { 0x80f09c, 0x00 }, | ||
131 | { 0x80f09d, 0x20 }, | ||
132 | { 0x80f09e, 0x00 }, | ||
133 | { 0x80f09f, 0x0c }, | ||
134 | { 0x80f0a0, 0x00 }, | ||
135 | { 0x80f130, 0x04 }, | ||
136 | { 0x80f132, 0x04 }, | ||
137 | { 0x80f144, 0x1a }, | ||
138 | { 0x80f146, 0x00 }, | ||
139 | { 0x80f14a, 0x01 }, | ||
140 | { 0x80f14c, 0x00 }, | ||
141 | { 0x80f14d, 0x00 }, | ||
142 | { 0x80f14f, 0x04 }, | ||
143 | { 0x80f158, 0x7f }, | ||
144 | { 0x80f15a, 0x00 }, | ||
145 | { 0x80f15b, 0x08 }, | ||
146 | { 0x80f15d, 0x03 }, | ||
147 | { 0x80f15e, 0x05 }, | ||
148 | { 0x80f163, 0x05 }, | ||
149 | { 0x80f166, 0x01 }, | ||
150 | { 0x80f167, 0x40 }, | ||
151 | { 0x80f168, 0x0f }, | ||
152 | { 0x80f17a, 0x00 }, | ||
153 | { 0x80f17b, 0x00 }, | ||
154 | { 0x80f183, 0x01 }, | ||
155 | { 0x80f19d, 0x40 }, | ||
156 | { 0x80f1bc, 0x36 }, | ||
157 | { 0x80f1bd, 0x00 }, | ||
158 | { 0x80f1cb, 0xa0 }, | ||
159 | { 0x80f1cc, 0x01 }, | ||
160 | { 0x80f204, 0x10 }, | ||
161 | { 0x80f214, 0x00 }, | ||
162 | { 0x80f40e, 0x0a }, | ||
163 | { 0x80f40f, 0x40 }, | ||
164 | { 0x80f410, 0x08 }, | ||
165 | { 0x80f55f, 0x0a }, | ||
166 | { 0x80f561, 0x15 }, | ||
167 | { 0x80f562, 0x20 }, | ||
168 | { 0x80f5df, 0xfb }, | ||
169 | { 0x80f5e0, 0x00 }, | ||
170 | { 0x80f5e3, 0x09 }, | ||
171 | { 0x80f5e4, 0x01 }, | ||
172 | { 0x80f5e5, 0x01 }, | ||
173 | { 0x80f5f8, 0x01 }, | ||
174 | { 0x80f5fd, 0x01 }, | ||
175 | { 0x80f600, 0x05 }, | ||
176 | { 0x80f601, 0x08 }, | ||
177 | { 0x80f602, 0x0b }, | ||
178 | { 0x80f603, 0x0e }, | ||
179 | { 0x80f604, 0x11 }, | ||
180 | { 0x80f605, 0x14 }, | ||
181 | { 0x80f606, 0x17 }, | ||
182 | { 0x80f607, 0x1f }, | ||
183 | { 0x80f60e, 0x00 }, | ||
184 | { 0x80f60f, 0x04 }, | ||
185 | { 0x80f610, 0x32 }, | ||
186 | { 0x80f611, 0x10 }, | ||
187 | { 0x80f707, 0xfc }, | ||
188 | { 0x80f708, 0x00 }, | ||
189 | { 0x80f709, 0x37 }, | ||
190 | { 0x80f70a, 0x00 }, | ||
191 | { 0x80f78b, 0x01 }, | ||
192 | { 0x80f80f, 0x40 }, | ||
193 | { 0x80f810, 0x54 }, | ||
194 | { 0x80f811, 0x5a }, | ||
195 | { 0x80f905, 0x01 }, | ||
196 | { 0x80fb06, 0x03 }, | ||
197 | { 0x80fd8b, 0x00 }, | ||
198 | }; | ||
199 | |||
200 | /* Infineon TUA 9001 tuner init | ||
201 | AF9033_TUNER_TUA9001 = 0x27 */ | ||
202 | static const struct reg_val tuner_init_tua9001[] = { | ||
203 | { 0x800046, 0x27 }, | ||
204 | { 0x800057, 0x00 }, | ||
205 | { 0x800058, 0x01 }, | ||
206 | { 0x80005f, 0x00 }, | ||
207 | { 0x800060, 0x00 }, | ||
208 | { 0x80006d, 0x00 }, | ||
209 | { 0x800071, 0x05 }, | ||
210 | { 0x800072, 0x02 }, | ||
211 | { 0x800074, 0x01 }, | ||
212 | { 0x800075, 0x03 }, | ||
213 | { 0x800076, 0x02 }, | ||
214 | { 0x800077, 0x00 }, | ||
215 | { 0x800078, 0x01 }, | ||
216 | { 0x800079, 0x00 }, | ||
217 | { 0x80007a, 0x7e }, | ||
218 | { 0x80007b, 0x3e }, | ||
219 | { 0x800093, 0x00 }, | ||
220 | { 0x800094, 0x01 }, | ||
221 | { 0x800095, 0x02 }, | ||
222 | { 0x800096, 0x01 }, | ||
223 | { 0x800098, 0x0a }, | ||
224 | { 0x80009b, 0x05 }, | ||
225 | { 0x80009c, 0x80 }, | ||
226 | { 0x8000b3, 0x00 }, | ||
227 | { 0x8000c1, 0x01 }, | ||
228 | { 0x8000c2, 0x00 }, | ||
229 | { 0x80f007, 0x00 }, | ||
230 | { 0x80f01f, 0x82 }, | ||
231 | { 0x80f020, 0x00 }, | ||
232 | { 0x80f029, 0x82 }, | ||
233 | { 0x80f02a, 0x00 }, | ||
234 | { 0x80f047, 0x00 }, | ||
235 | { 0x80f054, 0x00 }, | ||
236 | { 0x80f055, 0x00 }, | ||
237 | { 0x80f077, 0x01 }, | ||
238 | { 0x80f1e6, 0x00 }, | ||
239 | }; | ||
240 | |||
241 | #endif /* AF9033_PRIV_H */ | ||
242 | |||