diff options
author | David Wong <davidtlwong@gmail.com> | 2009-04-01 03:35:10 -0400 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2009-04-06 20:44:32 -0400 |
commit | f15da16d869be8be5ef991f8d042532c119310fa (patch) | |
tree | 764e5593a5e7caf5abb5deb24e0d15f10460b911 /drivers/media | |
parent | 81d1d09f926394c19a19ceeb139462908ac63a01 (diff) |
V4L/DVB (11398): Support for Legend Silicon LGS8913/LGS8GL5/LGS8GXX China DMB-TH digital demodulator
This patch contains the unified driver for Legend Silicon LGS8913 and
LGS8GL5. It should replace lgs8gl5.c in media/dvb/frontends in the future.
Signed-off-by: David T.L. Wong <davidtlwong@gmail.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media')
-rw-r--r-- | drivers/media/dvb/frontends/Kconfig | 7 | ||||
-rw-r--r-- | drivers/media/dvb/frontends/Makefile | 1 | ||||
-rw-r--r-- | drivers/media/dvb/frontends/lgs8gxx.c | 816 | ||||
-rw-r--r-- | drivers/media/dvb/frontends/lgs8gxx.h | 90 | ||||
-rw-r--r-- | drivers/media/dvb/frontends/lgs8gxx_priv.h | 70 |
5 files changed, 984 insertions, 0 deletions
diff --git a/drivers/media/dvb/frontends/Kconfig b/drivers/media/dvb/frontends/Kconfig index a486a7f81fa9..23e4cffeba38 100644 --- a/drivers/media/dvb/frontends/Kconfig +++ b/drivers/media/dvb/frontends/Kconfig | |||
@@ -513,6 +513,13 @@ config DVB_LGS8GL5 | |||
513 | help | 513 | help |
514 | A DMB-TH tuner module. Say Y when you want to support this frontend. | 514 | A DMB-TH tuner module. Say Y when you want to support this frontend. |
515 | 515 | ||
516 | config DVB_LGS8GXX | ||
517 | tristate "Legend Silicon LGS8913/LGS8GL5/LGS8GXX DMB-TH demodulator" | ||
518 | depends on DVB_CORE && I2C | ||
519 | default m if DVB_FE_CUSTOMISE | ||
520 | help | ||
521 | A DMB-TH tuner module. Say Y when you want to support this frontend. | ||
522 | |||
516 | comment "Tools to develop new frontends" | 523 | comment "Tools to develop new frontends" |
517 | 524 | ||
518 | config DVB_DUMMY_FE | 525 | config DVB_DUMMY_FE |
diff --git a/drivers/media/dvb/frontends/Makefile b/drivers/media/dvb/frontends/Makefile index 65a336aa1db6..bc2b00abd106 100644 --- a/drivers/media/dvb/frontends/Makefile +++ b/drivers/media/dvb/frontends/Makefile | |||
@@ -61,6 +61,7 @@ obj-$(CONFIG_DVB_TDA10048) += tda10048.o | |||
61 | obj-$(CONFIG_DVB_TUNER_CX24113) += cx24113.o | 61 | obj-$(CONFIG_DVB_TUNER_CX24113) += cx24113.o |
62 | obj-$(CONFIG_DVB_S5H1411) += s5h1411.o | 62 | obj-$(CONFIG_DVB_S5H1411) += s5h1411.o |
63 | obj-$(CONFIG_DVB_LGS8GL5) += lgs8gl5.o | 63 | obj-$(CONFIG_DVB_LGS8GL5) += lgs8gl5.o |
64 | obj-$(CONFIG_DVB_LGS8GXX) += lgs8gxx.o | ||
64 | obj-$(CONFIG_DVB_DUMMY_FE) += dvb_dummy_fe.o | 65 | obj-$(CONFIG_DVB_DUMMY_FE) += dvb_dummy_fe.o |
65 | obj-$(CONFIG_DVB_AF9013) += af9013.o | 66 | obj-$(CONFIG_DVB_AF9013) += af9013.o |
66 | obj-$(CONFIG_DVB_CX24116) += cx24116.o | 67 | obj-$(CONFIG_DVB_CX24116) += cx24116.o |
diff --git a/drivers/media/dvb/frontends/lgs8gxx.c b/drivers/media/dvb/frontends/lgs8gxx.c new file mode 100644 index 000000000000..f9785dfe735b --- /dev/null +++ b/drivers/media/dvb/frontends/lgs8gxx.c | |||
@@ -0,0 +1,816 @@ | |||
1 | /* | ||
2 | * Support for Legend Silicon DMB-TH demodulator | ||
3 | * LGS8913, LGS8GL5 | ||
4 | * experimental support LGS8G42, LGS8G52 | ||
5 | * | ||
6 | * Copyright (C) 2007,2008 David T.L. Wong <davidtlwong@gmail.com> | ||
7 | * Copyright (C) 2008 Sirius International (Hong Kong) Limited | ||
8 | * Timothy Lee <timothy.lee@siriushk.com> (for initial work on LGS8GL5) | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify | ||
11 | * it under the terms of the GNU General Public License as published by | ||
12 | * the Free Software Foundation; either version 2 of the License, or | ||
13 | * (at your option) any later version. | ||
14 | * | ||
15 | * This program is distributed in the hope that it will be useful, | ||
16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
18 | * GNU General Public License for more details. | ||
19 | * | ||
20 | * You should have received a copy of the GNU General Public License | ||
21 | * along with this program; if not, write to the Free Software | ||
22 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
23 | * | ||
24 | */ | ||
25 | |||
26 | #include <asm/div64.h> | ||
27 | |||
28 | #include "dvb_frontend.h" | ||
29 | |||
30 | #include "lgs8gxx.h" | ||
31 | #include "lgs8gxx_priv.h" | ||
32 | |||
33 | #define dprintk(args...) \ | ||
34 | do { \ | ||
35 | if (debug) \ | ||
36 | printk(KERN_DEBUG "lgs8gxx: " args); \ | ||
37 | } while (0) | ||
38 | |||
39 | static int debug; | ||
40 | static int fake_signal_str; | ||
41 | |||
42 | module_param(debug, int, 0644); | ||
43 | MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off)."); | ||
44 | |||
45 | module_param(fake_signal_str, int, 0644); | ||
46 | MODULE_PARM_DESC(fake_signal_str, "fake signal strength for LGS8913." | ||
47 | "Signal strength calculation is slow.(default:off)."); | ||
48 | |||
49 | /* LGS8GXX internal helper functions */ | ||
50 | |||
51 | static int lgs8gxx_write_reg(struct lgs8gxx_state *priv, u8 reg, u8 data) | ||
52 | { | ||
53 | int ret; | ||
54 | u8 buf[] = { reg, data }; | ||
55 | struct i2c_msg msg = { .flags = 0, .buf = buf, .len = 2 }; | ||
56 | |||
57 | msg.addr = priv->config->demod_address; | ||
58 | if (reg >= 0xC0) | ||
59 | msg.addr += 0x02; | ||
60 | |||
61 | if (debug >= 2) | ||
62 | printk(KERN_DEBUG "%s: reg=0x%02X, data=0x%02X\n", | ||
63 | __func__, reg, data); | ||
64 | |||
65 | ret = i2c_transfer(priv->i2c, &msg, 1); | ||
66 | |||
67 | if (ret != 1) | ||
68 | dprintk(KERN_DEBUG "%s: error reg=0x%x, data=0x%x, ret=%i\n", | ||
69 | __func__, reg, data, ret); | ||
70 | |||
71 | return (ret != 1) ? -1 : 0; | ||
72 | } | ||
73 | |||
74 | static int lgs8gxx_read_reg(struct lgs8gxx_state *priv, u8 reg, u8 *p_data) | ||
75 | { | ||
76 | int ret; | ||
77 | u8 dev_addr; | ||
78 | |||
79 | u8 b0[] = { reg }; | ||
80 | u8 b1[] = { 0 }; | ||
81 | struct i2c_msg msg[] = { | ||
82 | { .flags = 0, .buf = b0, .len = 1 }, | ||
83 | { .flags = I2C_M_RD, .buf = b1, .len = 1 }, | ||
84 | }; | ||
85 | |||
86 | dev_addr = priv->config->demod_address; | ||
87 | if (reg >= 0xC0) | ||
88 | dev_addr += 0x02; | ||
89 | msg[1].addr = msg[0].addr = dev_addr; | ||
90 | |||
91 | ret = i2c_transfer(priv->i2c, msg, 2); | ||
92 | if (ret != 2) { | ||
93 | dprintk(KERN_DEBUG "%s: error reg=0x%x, ret=%i\n", | ||
94 | __func__, reg, ret); | ||
95 | return -1; | ||
96 | } | ||
97 | |||
98 | *p_data = b1[0]; | ||
99 | if (debug >= 2) | ||
100 | printk(KERN_DEBUG "%s: reg=0x%02X, data=0x%02X\n", | ||
101 | __func__, reg, b1[0]); | ||
102 | return 0; | ||
103 | } | ||
104 | |||
105 | static int lgs8gxx_soft_reset(struct lgs8gxx_state *priv) | ||
106 | { | ||
107 | lgs8gxx_write_reg(priv, 0x02, 0x00); | ||
108 | msleep(1); | ||
109 | lgs8gxx_write_reg(priv, 0x02, 0x01); | ||
110 | msleep(100); | ||
111 | |||
112 | return 0; | ||
113 | } | ||
114 | |||
115 | static int lgs8gxx_set_ad_mode(struct lgs8gxx_state *priv) | ||
116 | { | ||
117 | const struct lgs8gxx_config *config = priv->config; | ||
118 | u8 if_conf; | ||
119 | |||
120 | if_conf = 0x10; /* AGC output on; */ | ||
121 | |||
122 | if_conf |= | ||
123 | ((config->ext_adc) ? 0x80 : 0x00) | | ||
124 | ((config->if_neg_center) ? 0x04 : 0x00) | | ||
125 | ((config->if_freq == 0) ? 0x08 : 0x00) | /* Baseband */ | ||
126 | ((config->ext_adc && config->adc_signed) ? 0x02 : 0x00) | | ||
127 | ((config->ext_adc && config->if_neg_edge) ? 0x01 : 0x00); | ||
128 | |||
129 | if (config->ext_adc && | ||
130 | (config->prod == LGS8GXX_PROD_LGS8G52)) { | ||
131 | lgs8gxx_write_reg(priv, 0xBA, 0x40); | ||
132 | } | ||
133 | |||
134 | lgs8gxx_write_reg(priv, 0x07, if_conf); | ||
135 | |||
136 | return 0; | ||
137 | } | ||
138 | |||
139 | static int lgs8gxx_set_if_freq(struct lgs8gxx_state *priv, u32 freq /*in kHz*/) | ||
140 | { | ||
141 | u64 val; | ||
142 | u32 v32; | ||
143 | u32 if_clk; | ||
144 | |||
145 | if_clk = priv->config->if_clk_freq; | ||
146 | |||
147 | val = freq; | ||
148 | if (freq != 0) { | ||
149 | val *= (u64)1 << 32; | ||
150 | if (if_clk != 0) | ||
151 | do_div(val, if_clk); | ||
152 | v32 = val & 0xFFFFFFFF; | ||
153 | dprintk("Set IF Freq to %dkHz\n", freq); | ||
154 | } else { | ||
155 | v32 = 0; | ||
156 | dprintk("Set IF Freq to baseband\n"); | ||
157 | } | ||
158 | dprintk("AFC_INIT_FREQ = 0x%08X\n", v32); | ||
159 | |||
160 | lgs8gxx_write_reg(priv, 0x09, 0xFF & (v32)); | ||
161 | lgs8gxx_write_reg(priv, 0x0A, 0xFF & (v32 >> 8)); | ||
162 | lgs8gxx_write_reg(priv, 0x0B, 0xFF & (v32 >> 16)); | ||
163 | lgs8gxx_write_reg(priv, 0x0C, 0xFF & (v32 >> 24)); | ||
164 | |||
165 | return 0; | ||
166 | } | ||
167 | |||
168 | static int lgs8gxx_set_mode_auto(struct lgs8gxx_state *priv) | ||
169 | { | ||
170 | u8 t; | ||
171 | |||
172 | if (priv->config->prod == LGS8GXX_PROD_LGS8913) | ||
173 | lgs8gxx_write_reg(priv, 0xC6, 0x01); | ||
174 | |||
175 | lgs8gxx_read_reg(priv, 0x7E, &t); | ||
176 | lgs8gxx_write_reg(priv, 0x7E, t | 0x01); | ||
177 | |||
178 | /* clear FEC self reset */ | ||
179 | lgs8gxx_read_reg(priv, 0xC5, &t); | ||
180 | lgs8gxx_write_reg(priv, 0xC5, t & 0xE0); | ||
181 | |||
182 | if (priv->config->prod == LGS8GXX_PROD_LGS8913) { | ||
183 | /* FEC auto detect */ | ||
184 | lgs8gxx_write_reg(priv, 0xC1, 0x03); | ||
185 | |||
186 | lgs8gxx_read_reg(priv, 0x7C, &t); | ||
187 | t = (t & 0x8C) | 0x03; | ||
188 | lgs8gxx_write_reg(priv, 0x7C, t); | ||
189 | } | ||
190 | |||
191 | |||
192 | if (priv->config->prod == LGS8GXX_PROD_LGS8913) { | ||
193 | /* BER test mode */ | ||
194 | lgs8gxx_read_reg(priv, 0xC3, &t); | ||
195 | t = (t & 0xEF) | 0x10; | ||
196 | lgs8gxx_write_reg(priv, 0xC3, t); | ||
197 | } | ||
198 | |||
199 | if (priv->config->prod == LGS8GXX_PROD_LGS8G52) | ||
200 | lgs8gxx_write_reg(priv, 0xD9, 0x40); | ||
201 | |||
202 | return 0; | ||
203 | } | ||
204 | |||
205 | static int lgs8gxx_set_mode_manual(struct lgs8gxx_state *priv) | ||
206 | { | ||
207 | int ret = 0; | ||
208 | u8 t; | ||
209 | |||
210 | /* turn off auto-detect; manual settings */ | ||
211 | lgs8gxx_write_reg(priv, 0x7E, 0); | ||
212 | if (priv->config->prod == LGS8GXX_PROD_LGS8913) | ||
213 | lgs8gxx_write_reg(priv, 0xC1, 0); | ||
214 | |||
215 | ret = lgs8gxx_read_reg(priv, 0xC5, &t); | ||
216 | t = (t & 0xE0) | 0x06; | ||
217 | lgs8gxx_write_reg(priv, 0xC5, t); | ||
218 | |||
219 | lgs8gxx_soft_reset(priv); | ||
220 | |||
221 | return 0; | ||
222 | } | ||
223 | |||
224 | static int lgs8gxx_is_locked(struct lgs8gxx_state *priv, u8 *locked) | ||
225 | { | ||
226 | int ret = 0; | ||
227 | u8 t; | ||
228 | |||
229 | ret = lgs8gxx_read_reg(priv, 0x4B, &t); | ||
230 | if (ret != 0) | ||
231 | return ret; | ||
232 | |||
233 | *locked = ((t & 0xC0) == 0xC0) ? 1 : 0; | ||
234 | return 0; | ||
235 | } | ||
236 | |||
237 | static int lgs8gxx_is_autodetect_finished(struct lgs8gxx_state *priv, | ||
238 | u8 *finished) | ||
239 | { | ||
240 | int ret = 0; | ||
241 | u8 t; | ||
242 | |||
243 | ret = lgs8gxx_read_reg(priv, 0xA4, &t); | ||
244 | if (ret != 0) | ||
245 | return ret; | ||
246 | |||
247 | *finished = ((t & 0x3) == 0x1) ? 1 : 0; | ||
248 | |||
249 | return 0; | ||
250 | } | ||
251 | |||
252 | static int lgs8gxx_autolock_gi(struct lgs8gxx_state *priv, u8 gi, u8 *locked) | ||
253 | { | ||
254 | int err; | ||
255 | u8 ad_fini = 0; | ||
256 | |||
257 | if (gi == GI_945) | ||
258 | dprintk("try GI 945\n"); | ||
259 | else if (gi == GI_595) | ||
260 | dprintk("try GI 595\n"); | ||
261 | else if (gi == GI_420) | ||
262 | dprintk("try GI 420\n"); | ||
263 | lgs8gxx_write_reg(priv, 0x04, gi); | ||
264 | lgs8gxx_soft_reset(priv); | ||
265 | msleep(50); | ||
266 | err = lgs8gxx_is_autodetect_finished(priv, &ad_fini); | ||
267 | if (err != 0) | ||
268 | return err; | ||
269 | if (ad_fini) { | ||
270 | err = lgs8gxx_is_locked(priv, locked); | ||
271 | if (err != 0) | ||
272 | return err; | ||
273 | } | ||
274 | |||
275 | return 0; | ||
276 | } | ||
277 | |||
278 | static int lgs8gxx_auto_detect(struct lgs8gxx_state *priv, | ||
279 | u8 *detected_param, u8 *gi) | ||
280 | { | ||
281 | int i, j; | ||
282 | int err = 0; | ||
283 | u8 locked = 0, tmp_gi; | ||
284 | |||
285 | dprintk("%s\n", __func__); | ||
286 | |||
287 | lgs8gxx_set_mode_auto(priv); | ||
288 | /* Guard Interval */ | ||
289 | lgs8gxx_write_reg(priv, 0x03, 00); | ||
290 | |||
291 | for (i = 0; i < 2; i++) { | ||
292 | for (j = 0; j < 2; j++) { | ||
293 | tmp_gi = GI_945; | ||
294 | err = lgs8gxx_autolock_gi(priv, GI_945, &locked); | ||
295 | if (err) | ||
296 | goto out; | ||
297 | if (locked) | ||
298 | goto locked; | ||
299 | } | ||
300 | for (j = 0; j < 2; j++) { | ||
301 | tmp_gi = GI_420; | ||
302 | err = lgs8gxx_autolock_gi(priv, GI_420, &locked); | ||
303 | if (err) | ||
304 | goto out; | ||
305 | if (locked) | ||
306 | goto locked; | ||
307 | } | ||
308 | tmp_gi = GI_595; | ||
309 | err = lgs8gxx_autolock_gi(priv, GI_595, &locked); | ||
310 | if (err) | ||
311 | goto out; | ||
312 | if (locked) | ||
313 | goto locked; | ||
314 | } | ||
315 | |||
316 | locked: | ||
317 | if ((err == 0) && (locked == 1)) { | ||
318 | u8 t; | ||
319 | |||
320 | lgs8gxx_read_reg(priv, 0xA2, &t); | ||
321 | *detected_param = t; | ||
322 | |||
323 | if (tmp_gi == GI_945) | ||
324 | dprintk("GI 945 locked\n"); | ||
325 | else if (tmp_gi == GI_595) | ||
326 | dprintk("GI 595 locked\n"); | ||
327 | else if (tmp_gi == GI_420) | ||
328 | dprintk("GI 420 locked\n"); | ||
329 | *gi = tmp_gi; | ||
330 | } | ||
331 | if (!locked) | ||
332 | err = -1; | ||
333 | |||
334 | out: | ||
335 | return err; | ||
336 | } | ||
337 | |||
338 | static void lgs8gxx_auto_lock(struct lgs8gxx_state *priv) | ||
339 | { | ||
340 | s8 err; | ||
341 | u8 gi = 0x2; | ||
342 | u8 detected_param = 0; | ||
343 | |||
344 | err = lgs8gxx_auto_detect(priv, &detected_param, &gi); | ||
345 | |||
346 | if (err != 0) { | ||
347 | dprintk("lgs8gxx_auto_detect failed\n"); | ||
348 | } | ||
349 | |||
350 | /* Apply detected parameters */ | ||
351 | if (priv->config->prod == LGS8GXX_PROD_LGS8913) { | ||
352 | u8 inter_leave_len = detected_param & TIM_MASK ; | ||
353 | inter_leave_len = (inter_leave_len == TIM_LONG) ? 0x60 : 0x40; | ||
354 | detected_param &= CF_MASK | SC_MASK | LGS_FEC_MASK; | ||
355 | detected_param |= inter_leave_len; | ||
356 | } | ||
357 | lgs8gxx_write_reg(priv, 0x7D, detected_param); | ||
358 | if (priv->config->prod == LGS8GXX_PROD_LGS8913) | ||
359 | lgs8gxx_write_reg(priv, 0xC0, detected_param); | ||
360 | /* lgs8gxx_soft_reset(priv); */ | ||
361 | |||
362 | /* Enter manual mode */ | ||
363 | lgs8gxx_set_mode_manual(priv); | ||
364 | |||
365 | switch (gi) { | ||
366 | case GI_945: | ||
367 | priv->curr_gi = 945; break; | ||
368 | case GI_595: | ||
369 | priv->curr_gi = 595; break; | ||
370 | case GI_420: | ||
371 | priv->curr_gi = 420; break; | ||
372 | default: | ||
373 | priv->curr_gi = 945; break; | ||
374 | } | ||
375 | } | ||
376 | |||
377 | static int lgs8gxx_set_mpeg_mode(struct lgs8gxx_state *priv, | ||
378 | u8 serial, u8 clk_pol, u8 clk_gated) | ||
379 | { | ||
380 | int ret = 0; | ||
381 | u8 t; | ||
382 | |||
383 | ret = lgs8gxx_read_reg(priv, 0xC2, &t); | ||
384 | if (ret != 0) | ||
385 | return ret; | ||
386 | |||
387 | t &= 0xF8; | ||
388 | t |= serial ? TS_SERIAL : TS_PARALLEL; | ||
389 | t |= clk_pol ? TS_CLK_INVERTED : TS_CLK_NORMAL; | ||
390 | t |= clk_gated ? TS_CLK_GATED : TS_CLK_FREERUN; | ||
391 | |||
392 | ret = lgs8gxx_write_reg(priv, 0xC2, t); | ||
393 | if (ret != 0) | ||
394 | return ret; | ||
395 | |||
396 | return 0; | ||
397 | } | ||
398 | |||
399 | |||
400 | /* LGS8913 demod frontend functions */ | ||
401 | |||
402 | static int lgs8913_init(struct lgs8gxx_state *priv) | ||
403 | { | ||
404 | u8 t; | ||
405 | |||
406 | /* LGS8913 specific */ | ||
407 | lgs8gxx_write_reg(priv, 0xc1, 0x3); | ||
408 | |||
409 | lgs8gxx_read_reg(priv, 0x7c, &t); | ||
410 | lgs8gxx_write_reg(priv, 0x7c, (t&0x8c) | 0x3); | ||
411 | |||
412 | /* LGS8913 specific */ | ||
413 | lgs8gxx_read_reg(priv, 0xc3, &t); | ||
414 | lgs8gxx_write_reg(priv, 0xc3, t&0x10); | ||
415 | |||
416 | |||
417 | return 0; | ||
418 | } | ||
419 | |||
420 | static int lgs8gxx_init(struct dvb_frontend *fe) | ||
421 | { | ||
422 | struct lgs8gxx_state *priv = | ||
423 | (struct lgs8gxx_state *)fe->demodulator_priv; | ||
424 | const struct lgs8gxx_config *config = priv->config; | ||
425 | u8 data = 0; | ||
426 | s8 err; | ||
427 | dprintk("%s\n", __func__); | ||
428 | |||
429 | lgs8gxx_read_reg(priv, 0, &data); | ||
430 | dprintk("reg 0 = 0x%02X\n", data); | ||
431 | |||
432 | /* Setup MPEG output format */ | ||
433 | err = lgs8gxx_set_mpeg_mode(priv, config->serial_ts, | ||
434 | config->ts_clk_pol, | ||
435 | config->ts_clk_gated); | ||
436 | if (err != 0) | ||
437 | return -EIO; | ||
438 | |||
439 | if (config->prod == LGS8GXX_PROD_LGS8913) | ||
440 | lgs8913_init(priv); | ||
441 | lgs8gxx_set_if_freq(priv, priv->config->if_freq); | ||
442 | if (config->prod != LGS8GXX_PROD_LGS8913) | ||
443 | lgs8gxx_set_ad_mode(priv); | ||
444 | |||
445 | return 0; | ||
446 | } | ||
447 | |||
448 | static void lgs8gxx_release(struct dvb_frontend *fe) | ||
449 | { | ||
450 | struct lgs8gxx_state *state = fe->demodulator_priv; | ||
451 | dprintk("%s\n", __func__); | ||
452 | |||
453 | kfree(state); | ||
454 | } | ||
455 | |||
456 | |||
457 | static int lgs8gxx_write(struct dvb_frontend *fe, u8 *buf, int len) | ||
458 | { | ||
459 | struct lgs8gxx_state *priv = fe->demodulator_priv; | ||
460 | |||
461 | if (len != 2) | ||
462 | return -EINVAL; | ||
463 | |||
464 | return lgs8gxx_write_reg(priv, buf[0], buf[1]); | ||
465 | } | ||
466 | |||
467 | static int lgs8gxx_set_fe(struct dvb_frontend *fe, | ||
468 | struct dvb_frontend_parameters *fe_params) | ||
469 | { | ||
470 | struct lgs8gxx_state *priv = fe->demodulator_priv; | ||
471 | |||
472 | dprintk("%s\n", __func__); | ||
473 | |||
474 | /* set frequency */ | ||
475 | if (fe->ops.tuner_ops.set_params) { | ||
476 | fe->ops.tuner_ops.set_params(fe, fe_params); | ||
477 | if (fe->ops.i2c_gate_ctrl) | ||
478 | fe->ops.i2c_gate_ctrl(fe, 0); | ||
479 | } | ||
480 | |||
481 | /* start auto lock */ | ||
482 | lgs8gxx_auto_lock(priv); | ||
483 | |||
484 | msleep(10); | ||
485 | |||
486 | return 0; | ||
487 | } | ||
488 | |||
489 | static int lgs8gxx_get_fe(struct dvb_frontend *fe, | ||
490 | struct dvb_frontend_parameters *fe_params) | ||
491 | { | ||
492 | struct lgs8gxx_state *priv = fe->demodulator_priv; | ||
493 | u8 t; | ||
494 | |||
495 | dprintk("%s\n", __func__); | ||
496 | |||
497 | /* TODO: get real readings from device */ | ||
498 | /* inversion status */ | ||
499 | fe_params->inversion = INVERSION_OFF; | ||
500 | |||
501 | /* bandwidth */ | ||
502 | fe_params->u.ofdm.bandwidth = BANDWIDTH_8_MHZ; | ||
503 | |||
504 | |||
505 | lgs8gxx_read_reg(priv, 0x7D, &t); | ||
506 | fe_params->u.ofdm.code_rate_HP = FEC_AUTO; | ||
507 | fe_params->u.ofdm.code_rate_LP = FEC_AUTO; | ||
508 | |||
509 | /* constellation */ | ||
510 | switch (t & SC_MASK) { | ||
511 | case SC_QAM64: | ||
512 | fe_params->u.ofdm.constellation = QAM_64; | ||
513 | break; | ||
514 | case SC_QAM32: | ||
515 | fe_params->u.ofdm.constellation = QAM_32; | ||
516 | break; | ||
517 | case SC_QAM16: | ||
518 | fe_params->u.ofdm.constellation = QAM_16; | ||
519 | break; | ||
520 | case SC_QAM4: | ||
521 | case SC_QAM4NR: | ||
522 | fe_params->u.ofdm.constellation = QPSK; | ||
523 | break; | ||
524 | default: | ||
525 | fe_params->u.ofdm.constellation = QAM_64; | ||
526 | } | ||
527 | |||
528 | /* transmission mode */ | ||
529 | fe_params->u.ofdm.transmission_mode = TRANSMISSION_MODE_AUTO; | ||
530 | |||
531 | /* guard interval */ | ||
532 | fe_params->u.ofdm.guard_interval = GUARD_INTERVAL_AUTO; | ||
533 | |||
534 | /* hierarchy */ | ||
535 | fe_params->u.ofdm.hierarchy_information = HIERARCHY_NONE; | ||
536 | |||
537 | return 0; | ||
538 | } | ||
539 | |||
540 | static | ||
541 | int lgs8gxx_get_tune_settings(struct dvb_frontend *fe, | ||
542 | struct dvb_frontend_tune_settings *fesettings) | ||
543 | { | ||
544 | /* FIXME: copy from tda1004x.c */ | ||
545 | fesettings->min_delay_ms = 800; | ||
546 | fesettings->step_size = 0; | ||
547 | fesettings->max_drift = 0; | ||
548 | return 0; | ||
549 | } | ||
550 | |||
551 | static int lgs8gxx_read_status(struct dvb_frontend *fe, fe_status_t *fe_status) | ||
552 | { | ||
553 | struct lgs8gxx_state *priv = fe->demodulator_priv; | ||
554 | s8 ret; | ||
555 | u8 t; | ||
556 | |||
557 | dprintk("%s\n", __func__); | ||
558 | |||
559 | ret = lgs8gxx_read_reg(priv, 0x4B, &t); | ||
560 | if (ret != 0) | ||
561 | return -EIO; | ||
562 | |||
563 | dprintk("Reg 0x4B: 0x%02X\n", t); | ||
564 | |||
565 | *fe_status = 0; | ||
566 | if (priv->config->prod == LGS8GXX_PROD_LGS8913) { | ||
567 | if ((t & 0x40) == 0x40) | ||
568 | *fe_status |= FE_HAS_SIGNAL | FE_HAS_CARRIER; | ||
569 | if ((t & 0x80) == 0x80) | ||
570 | *fe_status |= FE_HAS_VITERBI | FE_HAS_SYNC | | ||
571 | FE_HAS_LOCK; | ||
572 | } else { | ||
573 | if ((t & 0x80) == 0x80) | ||
574 | *fe_status |= FE_HAS_SIGNAL | FE_HAS_CARRIER | | ||
575 | FE_HAS_VITERBI | FE_HAS_SYNC | FE_HAS_LOCK; | ||
576 | } | ||
577 | |||
578 | /* success */ | ||
579 | dprintk("%s: fe_status=0x%x\n", __func__, *fe_status); | ||
580 | return 0; | ||
581 | } | ||
582 | |||
583 | static int lgs8gxx_read_signal_agc(struct lgs8gxx_state *priv, u16 *signal) | ||
584 | { | ||
585 | u16 v; | ||
586 | u8 agc_lvl[2], cat; | ||
587 | |||
588 | dprintk("%s()\n", __func__); | ||
589 | lgs8gxx_read_reg(priv, 0x3F, &agc_lvl[0]); | ||
590 | lgs8gxx_read_reg(priv, 0x3E, &agc_lvl[1]); | ||
591 | |||
592 | v = agc_lvl[0]; | ||
593 | v <<= 8; | ||
594 | v |= agc_lvl[1]; | ||
595 | |||
596 | dprintk("agc_lvl: 0x%04X\n", v); | ||
597 | |||
598 | if (v < 0x100) | ||
599 | cat = 0; | ||
600 | else if (v < 0x190) | ||
601 | cat = 5; | ||
602 | else if (v < 0x2A8) | ||
603 | cat = 4; | ||
604 | else if (v < 0x381) | ||
605 | cat = 3; | ||
606 | else if (v < 0x400) | ||
607 | cat = 2; | ||
608 | else if (v == 0x400) | ||
609 | cat = 1; | ||
610 | else | ||
611 | cat = 0; | ||
612 | |||
613 | *signal = cat; | ||
614 | |||
615 | return 0; | ||
616 | } | ||
617 | |||
618 | static int lgs8913_read_signal_strength(struct lgs8gxx_state *priv, u16 *signal) | ||
619 | { | ||
620 | u8 t; s8 ret; | ||
621 | s16 max_strength = 0; | ||
622 | u8 str; | ||
623 | u16 i, gi = priv->curr_gi; | ||
624 | |||
625 | dprintk("%s\n", __func__); | ||
626 | |||
627 | ret = lgs8gxx_read_reg(priv, 0x4B, &t); | ||
628 | if (ret != 0) | ||
629 | return -EIO; | ||
630 | |||
631 | if (fake_signal_str) { | ||
632 | if ((t & 0xC0) == 0xC0) { | ||
633 | dprintk("Fake signal strength as 50\n"); | ||
634 | *signal = 0x32; | ||
635 | } else | ||
636 | *signal = 0; | ||
637 | return 0; | ||
638 | } | ||
639 | |||
640 | dprintk("gi = %d\n", gi); | ||
641 | for (i = 0; i < gi; i++) { | ||
642 | |||
643 | if ((i & 0xFF) == 0) | ||
644 | lgs8gxx_write_reg(priv, 0x84, 0x03 & (i >> 8)); | ||
645 | lgs8gxx_write_reg(priv, 0x83, i & 0xFF); | ||
646 | |||
647 | lgs8gxx_read_reg(priv, 0x94, &str); | ||
648 | if (max_strength < str) | ||
649 | max_strength = str; | ||
650 | } | ||
651 | |||
652 | *signal = max_strength; | ||
653 | dprintk("%s: signal=0x%02X\n", __func__, *signal); | ||
654 | |||
655 | lgs8gxx_read_reg(priv, 0x95, &t); | ||
656 | dprintk("%s: AVG Noise=0x%02X\n", __func__, t); | ||
657 | |||
658 | return 0; | ||
659 | } | ||
660 | |||
661 | static int lgs8gxx_read_signal_strength(struct dvb_frontend *fe, u16 *signal) | ||
662 | { | ||
663 | struct lgs8gxx_state *priv = fe->demodulator_priv; | ||
664 | |||
665 | if (priv->config->prod == LGS8GXX_PROD_LGS8913) | ||
666 | return lgs8913_read_signal_strength(priv, signal); | ||
667 | else | ||
668 | return lgs8gxx_read_signal_agc(priv, signal); | ||
669 | } | ||
670 | |||
671 | static int lgs8gxx_read_snr(struct dvb_frontend *fe, u16 *snr) | ||
672 | { | ||
673 | struct lgs8gxx_state *priv = fe->demodulator_priv; | ||
674 | u8 t; | ||
675 | *snr = 0; | ||
676 | |||
677 | lgs8gxx_read_reg(priv, 0x95, &t); | ||
678 | dprintk("AVG Noise=0x%02X\n", t); | ||
679 | *snr = 256 - t; | ||
680 | *snr <<= 8; | ||
681 | dprintk("snr=0x%x\n", *snr); | ||
682 | |||
683 | return 0; | ||
684 | } | ||
685 | |||
686 | static int lgs8gxx_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks) | ||
687 | { | ||
688 | *ucblocks = 0; | ||
689 | dprintk("%s: ucblocks=0x%x\n", __func__, *ucblocks); | ||
690 | return 0; | ||
691 | } | ||
692 | |||
693 | static int lgs8gxx_read_ber(struct dvb_frontend *fe, u32 *ber) | ||
694 | { | ||
695 | struct lgs8gxx_state *priv = fe->demodulator_priv; | ||
696 | u8 r0, r1, r2, r3; | ||
697 | u32 total_cnt, err_cnt; | ||
698 | |||
699 | dprintk("%s\n", __func__); | ||
700 | |||
701 | lgs8gxx_write_reg(priv, 0xc6, 0x01); | ||
702 | lgs8gxx_write_reg(priv, 0xc6, 0x41); | ||
703 | lgs8gxx_write_reg(priv, 0xc6, 0x01); | ||
704 | |||
705 | msleep(200); | ||
706 | |||
707 | lgs8gxx_write_reg(priv, 0xc6, 0x81); | ||
708 | lgs8gxx_read_reg(priv, 0xd0, &r0); | ||
709 | lgs8gxx_read_reg(priv, 0xd1, &r1); | ||
710 | lgs8gxx_read_reg(priv, 0xd2, &r2); | ||
711 | lgs8gxx_read_reg(priv, 0xd3, &r3); | ||
712 | total_cnt = (r3 << 24) | (r2 << 16) | (r1 << 8) | (r0); | ||
713 | lgs8gxx_read_reg(priv, 0xd4, &r0); | ||
714 | lgs8gxx_read_reg(priv, 0xd5, &r1); | ||
715 | lgs8gxx_read_reg(priv, 0xd6, &r2); | ||
716 | lgs8gxx_read_reg(priv, 0xd7, &r3); | ||
717 | err_cnt = (r3 << 24) | (r2 << 16) | (r1 << 8) | (r0); | ||
718 | dprintk("error=%d total=%d\n", err_cnt, total_cnt); | ||
719 | |||
720 | if (total_cnt == 0) | ||
721 | *ber = 0; | ||
722 | else | ||
723 | *ber = err_cnt * 100 / total_cnt; | ||
724 | |||
725 | dprintk("%s: ber=0x%x\n", __func__, *ber); | ||
726 | return 0; | ||
727 | } | ||
728 | |||
729 | static int lgs8gxx_i2c_gate_ctrl(struct dvb_frontend *fe, int enable) | ||
730 | { | ||
731 | struct lgs8gxx_state *priv = fe->demodulator_priv; | ||
732 | |||
733 | if (priv->config->tuner_address == 0) | ||
734 | return 0; | ||
735 | if (enable) { | ||
736 | u8 v = 0x80 | priv->config->tuner_address; | ||
737 | return lgs8gxx_write_reg(priv, 0x01, v); | ||
738 | } | ||
739 | return lgs8gxx_write_reg(priv, 0x01, 0); | ||
740 | } | ||
741 | |||
742 | static struct dvb_frontend_ops lgs8gxx_ops = { | ||
743 | .info = { | ||
744 | .name = "Legend Silicon LGS8913/LGS8GXX DMB-TH", | ||
745 | .type = FE_OFDM, | ||
746 | .frequency_min = 474000000, | ||
747 | .frequency_max = 858000000, | ||
748 | .frequency_stepsize = 10000, | ||
749 | .caps = | ||
750 | FE_CAN_FEC_AUTO | | ||
751 | FE_CAN_QAM_AUTO | | ||
752 | FE_CAN_TRANSMISSION_MODE_AUTO | | ||
753 | FE_CAN_GUARD_INTERVAL_AUTO | ||
754 | }, | ||
755 | |||
756 | .release = lgs8gxx_release, | ||
757 | |||
758 | .init = lgs8gxx_init, | ||
759 | .write = lgs8gxx_write, | ||
760 | .i2c_gate_ctrl = lgs8gxx_i2c_gate_ctrl, | ||
761 | |||
762 | .set_frontend = lgs8gxx_set_fe, | ||
763 | .get_frontend = lgs8gxx_get_fe, | ||
764 | .get_tune_settings = lgs8gxx_get_tune_settings, | ||
765 | |||
766 | .read_status = lgs8gxx_read_status, | ||
767 | .read_ber = lgs8gxx_read_ber, | ||
768 | .read_signal_strength = lgs8gxx_read_signal_strength, | ||
769 | .read_snr = lgs8gxx_read_snr, | ||
770 | .read_ucblocks = lgs8gxx_read_ucblocks, | ||
771 | }; | ||
772 | |||
773 | struct dvb_frontend *lgs8gxx_attach(const struct lgs8gxx_config *config, | ||
774 | struct i2c_adapter *i2c) | ||
775 | { | ||
776 | struct lgs8gxx_state *priv = NULL; | ||
777 | u8 data = 0; | ||
778 | |||
779 | dprintk("%s()\n", __func__); | ||
780 | |||
781 | if (config == NULL || i2c == NULL) | ||
782 | return NULL; | ||
783 | |||
784 | priv = kzalloc(sizeof(struct lgs8gxx_state), GFP_KERNEL); | ||
785 | if (priv == NULL) | ||
786 | goto error_out; | ||
787 | |||
788 | priv->config = config; | ||
789 | priv->i2c = i2c; | ||
790 | |||
791 | /* check if the demod is there */ | ||
792 | if (lgs8gxx_read_reg(priv, 0, &data) != 0) { | ||
793 | dprintk("%s lgs8gxx not found at i2c addr 0x%02X\n", | ||
794 | __func__, priv->config->demod_address); | ||
795 | goto error_out; | ||
796 | } | ||
797 | |||
798 | lgs8gxx_read_reg(priv, 1, &data); | ||
799 | |||
800 | memcpy(&priv->frontend.ops, &lgs8gxx_ops, | ||
801 | sizeof(struct dvb_frontend_ops)); | ||
802 | priv->frontend.demodulator_priv = priv; | ||
803 | |||
804 | return &priv->frontend; | ||
805 | |||
806 | error_out: | ||
807 | dprintk("%s() error_out\n", __func__); | ||
808 | kfree(priv); | ||
809 | return NULL; | ||
810 | |||
811 | } | ||
812 | EXPORT_SYMBOL(lgs8gxx_attach); | ||
813 | |||
814 | MODULE_DESCRIPTION("Legend Silicon LGS8913/LGS8GXX DMB-TH demodulator driver"); | ||
815 | MODULE_AUTHOR("David T. L. Wong <davidtlwong@gmail.com>"); | ||
816 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/media/dvb/frontends/lgs8gxx.h b/drivers/media/dvb/frontends/lgs8gxx.h new file mode 100644 index 000000000000..321d366a8307 --- /dev/null +++ b/drivers/media/dvb/frontends/lgs8gxx.h | |||
@@ -0,0 +1,90 @@ | |||
1 | /* | ||
2 | * Support for Legend Silicon DMB-TH demodulator | ||
3 | * LGS8913, LGS8GL5 | ||
4 | * experimental support LGS8G42, LGS8G52 | ||
5 | * | ||
6 | * Copyright (C) 2007,2008 David T.L. Wong <davidtlwong@gmail.com> | ||
7 | * Copyright (C) 2008 Sirius International (Hong Kong) Limited | ||
8 | * Timothy Lee <timothy.lee@siriushk.com> (for initial work on LGS8GL5) | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify | ||
11 | * it under the terms of the GNU General Public License as published by | ||
12 | * the Free Software Foundation; either version 2 of the License, or | ||
13 | * (at your option) any later version. | ||
14 | * | ||
15 | * This program is distributed in the hope that it will be useful, | ||
16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
18 | * GNU General Public License for more details. | ||
19 | * | ||
20 | * You should have received a copy of the GNU General Public License | ||
21 | * along with this program; if not, write to the Free Software | ||
22 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
23 | * | ||
24 | */ | ||
25 | |||
26 | #ifndef __LGS8GXX_H__ | ||
27 | #define __LGS8GXX_H__ | ||
28 | |||
29 | #include <linux/dvb/frontend.h> | ||
30 | #include <linux/i2c.h> | ||
31 | |||
32 | #define LGS8GXX_PROD_LGS8913 0 | ||
33 | #define LGS8GXX_PROD_LGS8GL5 1 | ||
34 | #define LGS8GXX_PROD_LGS8G42 3 | ||
35 | #define LGS8GXX_PROD_LGS8G52 4 | ||
36 | #define LGS8GXX_PROD_LGS8G54 5 | ||
37 | |||
38 | struct lgs8gxx_config { | ||
39 | |||
40 | /* product type */ | ||
41 | u8 prod; | ||
42 | |||
43 | /* the demodulator's i2c address */ | ||
44 | u8 demod_address; | ||
45 | |||
46 | /* parallel or serial transport stream */ | ||
47 | u8 serial_ts; | ||
48 | |||
49 | /* transport stream polarity*/ | ||
50 | u8 ts_clk_pol; | ||
51 | |||
52 | /* transport stream clock gated by ts_valid */ | ||
53 | u8 ts_clk_gated; | ||
54 | |||
55 | /* A/D Clock frequency */ | ||
56 | u32 if_clk_freq; /* in kHz */ | ||
57 | |||
58 | /* IF frequency */ | ||
59 | u32 if_freq; /* in kHz */ | ||
60 | |||
61 | /*Use External ADC*/ | ||
62 | u8 ext_adc; | ||
63 | |||
64 | /*External ADC output two's complement*/ | ||
65 | u8 adc_signed; | ||
66 | |||
67 | /*Sample IF data at falling edge of IF_CLK*/ | ||
68 | u8 if_neg_edge; | ||
69 | |||
70 | /*IF use Negative center frequency*/ | ||
71 | u8 if_neg_center; | ||
72 | |||
73 | /* slave address and configuration of the tuner */ | ||
74 | u8 tuner_address; | ||
75 | }; | ||
76 | |||
77 | #if defined(CONFIG_DVB_LGS8GXX) || \ | ||
78 | (defined(CONFIG_DVB_LGS8GXX_MODULE) && defined(MODULE)) | ||
79 | extern struct dvb_frontend *lgs8gxx_attach(const struct lgs8gxx_config *config, | ||
80 | struct i2c_adapter *i2c); | ||
81 | #else | ||
82 | static inline | ||
83 | struct dvb_frontend *lgs8gxx_attach(const struct lgs8gxx_config *config, | ||
84 | struct i2c_adapter *i2c) { | ||
85 | printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); | ||
86 | return NULL; | ||
87 | } | ||
88 | #endif /* CONFIG_DVB_LGS8GXX */ | ||
89 | |||
90 | #endif /* __LGS8GXX_H__ */ | ||
diff --git a/drivers/media/dvb/frontends/lgs8gxx_priv.h b/drivers/media/dvb/frontends/lgs8gxx_priv.h new file mode 100644 index 000000000000..9776d30686dc --- /dev/null +++ b/drivers/media/dvb/frontends/lgs8gxx_priv.h | |||
@@ -0,0 +1,70 @@ | |||
1 | /* | ||
2 | * Support for Legend Silicon DMB-TH demodulator | ||
3 | * LGS8913, LGS8GL5 | ||
4 | * experimental support LGS8G42, LGS8G52 | ||
5 | * | ||
6 | * Copyright (C) 2007,2008 David T.L. Wong <davidtlwong@gmail.com> | ||
7 | * Copyright (C) 2008 Sirius International (Hong Kong) Limited | ||
8 | * Timothy Lee <timothy.lee@siriushk.com> (for initial work on LGS8GL5) | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify | ||
11 | * it under the terms of the GNU General Public License as published by | ||
12 | * the Free Software Foundation; either version 2 of the License, or | ||
13 | * (at your option) any later version. | ||
14 | * | ||
15 | * This program is distributed in the hope that it will be useful, | ||
16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
18 | * GNU General Public License for more details. | ||
19 | * | ||
20 | * You should have received a copy of the GNU General Public License | ||
21 | * along with this program; if not, write to the Free Software | ||
22 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
23 | * | ||
24 | */ | ||
25 | |||
26 | #ifndef LGS8913_PRIV_H | ||
27 | #define LGS8913_PRIV_H | ||
28 | |||
29 | struct lgs8gxx_state { | ||
30 | struct i2c_adapter *i2c; | ||
31 | /* configuration settings */ | ||
32 | const struct lgs8gxx_config *config; | ||
33 | struct dvb_frontend frontend; | ||
34 | u16 curr_gi; /* current guard interval */ | ||
35 | }; | ||
36 | |||
37 | #define SC_MASK 0x1C /* Sub-Carrier Modulation Mask */ | ||
38 | #define SC_QAM64 0x10 /* 64QAM modulation */ | ||
39 | #define SC_QAM32 0x0C /* 32QAM modulation */ | ||
40 | #define SC_QAM16 0x08 /* 16QAM modulation */ | ||
41 | #define SC_QAM4NR 0x04 /* 4QAM modulation */ | ||
42 | #define SC_QAM4 0x00 /* 4QAM modulation */ | ||
43 | |||
44 | #define LGS_FEC_MASK 0x03 /* FEC Rate Mask */ | ||
45 | #define LGS_FEC_0_4 0x00 /* FEC Rate 0.4 */ | ||
46 | #define LGS_FEC_0_6 0x01 /* FEC Rate 0.6 */ | ||
47 | #define LGS_FEC_0_8 0x02 /* FEC Rate 0.8 */ | ||
48 | |||
49 | #define TIM_MASK 0x20 /* Time Interleave Length Mask */ | ||
50 | #define TIM_LONG 0x00 /* Time Interleave Length = 720 */ | ||
51 | #define TIM_MIDDLE 0x20 /* Time Interleave Length = 240 */ | ||
52 | |||
53 | #define CF_MASK 0x80 /* Control Frame Mask */ | ||
54 | #define CF_EN 0x80 /* Control Frame On */ | ||
55 | |||
56 | #define GI_MASK 0x03 /* Guard Interval Mask */ | ||
57 | #define GI_420 0x00 /* 1/9 Guard Interval */ | ||
58 | #define GI_595 0x01 /* */ | ||
59 | #define GI_945 0x02 /* 1/4 Guard Interval */ | ||
60 | |||
61 | |||
62 | #define TS_PARALLEL 0x00 /* Parallel TS Output a.k.a. SPI */ | ||
63 | #define TS_SERIAL 0x01 /* Serial TS Output a.k.a. SSI */ | ||
64 | #define TS_CLK_NORMAL 0x00 /* MPEG Clock Normal */ | ||
65 | #define TS_CLK_INVERTED 0x02 /* MPEG Clock Inverted */ | ||
66 | #define TS_CLK_GATED 0x00 /* MPEG clock gated */ | ||
67 | #define TS_CLK_FREERUN 0x04 /* MPEG clock free running*/ | ||
68 | |||
69 | |||
70 | #endif | ||