Commit | Line | Data |
---|---|---|
a09e091a JB |
1 | /* TODO: clean up/fix CC code */ |
2 | ||
3 | #ifdef HAVE_XORG_CONFIG_H | |
4 | #include <xorg-config.h> | |
5 | #endif | |
6 | ||
7 | #include <stdlib.h> | |
8 | #include <string.h> | |
9 | #include <stdio.h> | |
10 | ||
11 | #include "xf86.h" | |
12 | #include "xf86i2c.h" | |
13 | #include "bt829.h" | |
14 | #include "i2c_def.h" | |
15 | ||
16 | /* Changing the following settings (especially VCROP) may */ | |
17 | /* require modifying code that calls this driver. */ | |
18 | #define HCROP 0 /* amount to crop from the left and right edges */ | |
19 | #define VCROP 0 /* amount to crop from the top and bottom edges */ | |
20 | ||
21 | #define BTVERSION (bt->id>>4) | |
22 | ||
23 | #define H(X) ( ((X)>>8) & 0xFF ) | |
24 | #define L(X) ( (X) & 0xFF ) | |
25 | ||
26 | #define LIMIT(X,A,B) (((X)<(A)) ? (A) : ((X)>(B)) ? (B) : (X) ) | |
27 | ||
28 | /* Bt829 family chip ID's */ | |
29 | #define BT815 0x02 | |
30 | #define BT817 0x06 | |
31 | #define BT819 0x07 | |
32 | #define BT827 0x0C | |
33 | #define BT829 0x0E | |
34 | ||
35 | /* Bt829 registers */ | |
36 | #define STATUS 0x00 /* Device Status */ | |
37 | #define IFORM 0x01 /* Input Format */ | |
38 | #define TDEC 0x02 /* Temporal Decimation */ | |
39 | #define CROP 0x03 /* MSB Cropping */ | |
40 | #define VDELAY_LO 0x04 /* Vertical Delay */ | |
41 | #define VACTIVE_LO 0x05 /* Vertical Active */ | |
42 | #define HDELAY_LO 0x06 /* Horizontal Delay */ | |
43 | #define HACTIVE_LO 0x07 /* Horizontal Active */ | |
44 | #define HSCALE_HI 0x08 /* Horizontal Scaling */ | |
45 | #define HSCALE_LO 0x09 /* Horizontal Scaling */ | |
46 | #define BRIGHT 0x0A /* Brightness Control */ | |
47 | #define CONTROL 0x0B /* Miscellaneous Control */ | |
48 | #define CONTRAST_LO 0x0C /* Luma Gain (Contrast) */ | |
49 | #define SAT_U_LO 0x0D /* Chroma (U) Gain (Saturation) */ | |
50 | #define SAT_V_LO 0x0E /* Chroma (V) Gain (Saturation) */ | |
51 | #define HUE 0x0F /* Hue Control */ | |
52 | #define SCLOOP 0x10 /* SC Loop Control */ | |
53 | #define WC_UP 0x11 /* White Crush Up Count */ | |
54 | #define OFORM 0x12 /* Output Format */ | |
55 | #define VSCALE_HI 0x13 /* Vertical Scaling */ | |
56 | #define VSCALE_LO 0x14 /* Vertical Scaling */ | |
57 | #define TEST 0x15 /* Test Control */ | |
58 | #define VPOLE 0x16 /* Video Timing Polarity */ | |
59 | #define IDCODE 0x17 /* ID Code */ | |
60 | #define ADELAY 0x18 /* AGC Delay */ | |
61 | #define BDELAY 0x19 /* Burst Gate Delay */ | |
62 | #define ADC 0x1A /* ADC Interface */ | |
63 | #define VTC 0x1B /* Video Timing Control */ | |
64 | #define CC_STATUS 0x1C /* Extended Data Services/Closed Capt Status */ | |
65 | #define CC_DATA 0x1D /* Extended Data Services/Closed Capt Data */ | |
66 | #define WC_DN 0x1E /* White Crush Down Count */ | |
67 | #define SRESET 0x1F /* Software Reset */ | |
68 | #define P_IO 0x3F /* Programmable I/O */ | |
69 | ||
70 | static CARD8 | |
71 | btread(BT829Ptr bt, CARD8 reg) | |
72 | { | |
73 | CARD8 v; | |
74 | ||
75 | I2C_WriteRead(&(bt->d), ®, 1, &v, 1); | |
76 | ||
77 | return v; | |
78 | } | |
79 | ||
80 | static void | |
81 | btwrite(BT829Ptr bt, CARD8 reg, CARD8 val) | |
82 | { | |
83 | CARD8 data[2]; | |
84 | ||
85 | data[0] = reg; | |
86 | data[1] = val; | |
87 | I2C_WriteRead(&(bt->d), data, 2, NULL, 0); | |
88 | } | |
89 | ||
90 | /* | |
91 | * Register access | |
92 | */ | |
93 | static void | |
94 | btwrite_status(BT829Ptr bt) | |
95 | { /* STATUS */ | |
96 | btwrite(bt, STATUS, 0x00); /* clear */ | |
97 | } | |
98 | ||
99 | static void | |
100 | btwrite_iform(BT829Ptr bt) | |
101 | { /* IFORM */ | |
102 | int xtsel; | |
103 | ||
104 | switch (bt->format) { | |
105 | case BT829_NTSC: | |
106 | case BT829_NTSC_JAPAN: | |
107 | case BT829_PAL_M: | |
108 | case BT829_PAL_N_COMB: /* gatos says xtsel = 2 */ | |
109 | xtsel = 1; | |
110 | break; | |
111 | case BT829_PAL: | |
112 | case BT829_PAL_N: | |
113 | case BT829_SECAM: | |
114 | xtsel = 2; | |
115 | break; | |
116 | default: /* shouldn't get here */ | |
117 | xtsel = 3; /* hardware default */ | |
118 | break; | |
119 | } | |
120 | ||
121 | btwrite(bt, IFORM, (bt->mux << 5) | (xtsel << 3) | bt->format); | |
122 | } | |
123 | ||
124 | static void | |
125 | btwrite_tdec(BT829Ptr bt) | |
126 | { /* TDEC */ | |
127 | /* use default */ | |
128 | } | |
129 | ||
130 | static void | |
131 | btwrite_crop(BT829Ptr bt) | |
132 | { /* CROP */ | |
133 | btwrite(bt, CROP, (H(bt->vdelay) << 6) | (H(bt->vactive) << 4) | | |
134 | (H(bt->hdelay) << 2) | H(bt->width)); | |
135 | } | |
136 | ||
137 | static void | |
138 | btwrite_vdelay_lo(BT829Ptr bt) | |
139 | { /* VDELAY_LO */ | |
140 | btwrite(bt, VDELAY_LO, L(bt->vdelay)); | |
141 | } | |
142 | ||
143 | static void | |
144 | btwrite_vactive_lo(BT829Ptr bt) | |
145 | { /* VACTIVE_LO */ | |
146 | btwrite(bt, VACTIVE_LO, L(bt->vactive)); | |
147 | } | |
148 | ||
149 | static void | |
150 | btwrite_hdelay_lo(BT829Ptr bt) | |
151 | { /* HDELAY_LO */ | |
152 | btwrite(bt, HDELAY_LO, L(bt->hdelay)); | |
153 | } | |
154 | ||
155 | static void | |
156 | btwrite_hactive_lo(BT829Ptr bt) | |
157 | { /* HACTIVE_LO */ | |
158 | btwrite(bt, HACTIVE_LO, L(bt->width)); | |
159 | } | |
160 | ||
161 | static void | |
162 | btwrite_hscale_hi(BT829Ptr bt) | |
163 | { /* HSCALE_HI */ | |
164 | btwrite(bt, HSCALE_HI, H(bt->hscale)); | |
165 | } | |
166 | ||
167 | static void | |
168 | btwrite_hscale_lo(BT829Ptr bt) | |
169 | { /* HSCALE_LO */ | |
170 | btwrite(bt, HSCALE_LO, L(bt->hscale)); | |
171 | } | |
172 | ||
173 | static void | |
174 | btwrite_bright(BT829Ptr bt) | |
175 | { /* BRIGHT */ | |
176 | btwrite(bt, BRIGHT, bt->brightness); | |
177 | } | |
178 | ||
179 | static void | |
180 | btwrite_control(BT829Ptr bt) | |
181 | { /* CONTROL */ | |
182 | int ldec; | |
183 | ||
184 | /* The data sheet says ldec should always be 0 for SECAM */ | |
185 | /* but the picture quality is better with ldec = 1 */ | |
186 | ldec = (bt->width > 360); /* gatos says 384 */ | |
187 | ||
188 | btwrite(bt, CONTROL, ((bt->mux == bt->svideo_mux) ? 0xC0 : 0x00) | /* LNOTCH and COMP */ | |
189 | (ldec << 5) | (H(bt->contrast) << 2) | (H(bt->sat_u) << 1) | H(bt-> | |
190 | sat_v)); | |
191 | } | |
192 | ||
193 | static void | |
194 | btwrite_contrast_lo(BT829Ptr bt) | |
195 | { /* CONTRAST_LO */ | |
196 | btwrite(bt, CONTRAST_LO, L(bt->contrast)); | |
197 | } | |
198 | ||
199 | static void | |
200 | btwrite_sat_u_lo(BT829Ptr bt) | |
201 | { /* SAT_U_LO */ | |
202 | btwrite(bt, SAT_U_LO, L(bt->sat_u)); | |
203 | } | |
204 | ||
205 | static void | |
206 | btwrite_sat_v_lo(BT829Ptr bt) | |
207 | { /* SAT_V_LO */ | |
208 | btwrite(bt, SAT_V_LO, L(bt->sat_v)); | |
209 | } | |
210 | ||
211 | static void | |
212 | btwrite_hue(BT829Ptr bt) | |
213 | { /* HUE */ | |
214 | btwrite(bt, HUE, bt->hue); | |
215 | } | |
216 | ||
217 | static void | |
218 | btwrite_scloop(BT829Ptr bt) | |
219 | { /* SCLOOP */ | |
220 | if (BTVERSION >= BT827) { | |
221 | btwrite(bt, SCLOOP, (bt->format == BT829_SECAM) ? 0x10 : 0x00 /* QCIF or AUTO */ | |
222 | ); | |
223 | } | |
224 | } | |
225 | ||
226 | static void | |
227 | btwrite_wc_up(BT829Ptr bt) | |
228 | { /* WC_UP */ | |
229 | if (BTVERSION >= BT827) { | |
230 | /* use default */ | |
231 | } | |
232 | } | |
233 | ||
234 | static void | |
235 | btwrite_oform(BT829Ptr bt) | |
236 | { /* OFORM */ | |
237 | btwrite(bt, OFORM, (bt->code << 3) | (bt->len << 2) | 0x02 /* RANGE = 0, CORE = 0, VBI_FRAME = 0, OES = 2 (default) */ | |
238 | ); | |
239 | } | |
240 | ||
241 | static void | |
242 | btwrite_vscale_hi(BT829Ptr bt) | |
243 | { /* VSCALE_HI */ | |
244 | btwrite(bt, VSCALE_HI, H(bt->vscale) | 0x60 /* YCOMB = 0, COMB = 1, INT = 1 (default) */ | |
245 | ); | |
246 | } | |
247 | ||
248 | static void | |
249 | btwrite_vscale_lo(BT829Ptr bt) | |
250 | { /* VSCALE_LO */ | |
251 | btwrite(bt, VSCALE_LO, L(bt->vscale)); | |
252 | } | |
253 | ||
254 | /* TEST should not be written to */ | |
255 | ||
256 | static void | |
257 | btwrite_vpole(BT829Ptr bt) | |
258 | { /* VPOLE */ | |
259 | btwrite(bt, VPOLE, (bt->out_en << 7)); | |
260 | } | |
261 | ||
262 | /* IDCODE is read only */ | |
263 | ||
264 | static void | |
265 | btwrite_adelay(BT829Ptr bt) | |
266 | { /* ADELAY */ | |
267 | switch (bt->format) { | |
268 | case BT829_NTSC: | |
269 | case BT829_NTSC_JAPAN: | |
270 | case BT829_PAL_M: | |
271 | btwrite(bt, ADELAY, 104); | |
272 | break; | |
273 | case BT829_PAL: | |
274 | case BT829_PAL_N: | |
275 | case BT829_SECAM: | |
276 | case BT829_PAL_N_COMB: | |
277 | btwrite(bt, ADELAY, 127); | |
278 | break; | |
279 | default: /* shouldn't get here */ | |
280 | btwrite(bt, ADELAY, 104); /* hardware default */ | |
281 | break; | |
282 | } | |
283 | } | |
284 | ||
285 | static void | |
286 | btwrite_bdelay(BT829Ptr bt) | |
287 | { /* BDELAY */ | |
288 | switch (bt->format) { | |
289 | case BT829_NTSC: | |
290 | case BT829_NTSC_JAPAN: | |
291 | case BT829_PAL_M: | |
292 | btwrite(bt, BDELAY, 93); | |
293 | break; | |
294 | case BT829_PAL: | |
295 | case BT829_PAL_N: | |
296 | case BT829_PAL_N_COMB: | |
297 | btwrite(bt, BDELAY, 114); | |
298 | break; | |
299 | case BT829_SECAM: | |
300 | btwrite(bt, BDELAY, 160); | |
301 | break; | |
302 | default: /* shouldn't get here */ | |
303 | btwrite(bt, BDELAY, 93); /* hardware default */ | |
304 | break; | |
305 | } | |
306 | } | |
307 | ||
308 | static void | |
309 | btwrite_adc(BT829Ptr bt) | |
310 | { /* ADC */ | |
311 | btwrite(bt, ADC, bt->mux == bt->svideo_mux ? 0x80 : 0x82); /* CSLEEP = 0 or 1 */ | |
312 | } | |
313 | ||
314 | static void | |
315 | btwrite_vtc(BT829Ptr bt) | |
316 | { /* VTC */ | |
317 | int vfilt = 0; /* hardware default */ | |
318 | ||
319 | if (BTVERSION > BT827) { /* gatos says >= BT827 */ | |
320 | switch (bt->format) { | |
321 | case BT829_NTSC: | |
322 | case BT829_NTSC_JAPAN: | |
323 | case BT829_PAL_M: | |
324 | case BT829_PAL_N_COMB: /* gatos groups with BT829_PAL */ | |
325 | if (bt->width <= 360) | |
326 | vfilt = 1; /* gatos says <= 240 */ | |
327 | if (bt->width <= 180) | |
328 | vfilt = 2; /* gatos says <= 120 */ | |
329 | if (bt->width <= 90) | |
330 | vfilt = 3; /* gatos says <= 60 */ | |
331 | break; | |
332 | case BT829_PAL: | |
333 | case BT829_PAL_N: | |
334 | case BT829_SECAM: | |
335 | if (bt->width <= 384) | |
336 | vfilt = 1; | |
337 | if (bt->width <= 192) | |
338 | vfilt = 2; | |
339 | if (bt->width <= 96) | |
340 | vfilt = 3; | |
341 | break; | |
342 | default: /* shouldn't get here */ | |
343 | break; /* use hardware default */ | |
344 | } | |
345 | btwrite(bt, VTC, (bt->vbien << 4) | (bt->vbifmt << 3) | vfilt); | |
346 | } | |
347 | } | |
348 | ||
349 | static void | |
350 | btwrite_cc_status(BT829Ptr bt) | |
351 | { /* CC_STATUS *//* FIXME: ATI specific */ | |
352 | if (BTVERSION >= BT827) { | |
353 | if (bt->ccmode == 0) | |
354 | btwrite(bt, CC_STATUS, 0x00); | |
355 | /* 0x40 is activate to set the CCVALID line. Not required yet */ | |
356 | else | |
357 | btwrite(bt, CC_STATUS, (bt->ccmode << 4) | 0x40); | |
358 | } | |
359 | } | |
360 | ||
361 | /* CC_DATA is read only */ | |
362 | ||
363 | static void | |
364 | btwrite_wc_dn(BT829Ptr bt) | |
365 | { /* WC_DN */ | |
366 | if (BTVERSION >= BT827) { | |
367 | /* use default */ | |
368 | } | |
369 | } | |
370 | ||
371 | static void | |
372 | bt_reset(BT829Ptr bt) | |
373 | { /* SRESET */ | |
374 | btwrite(bt, SRESET, 0x0); /* Reset all registers */ | |
375 | } | |
376 | ||
377 | static void | |
378 | btwrite_p_io(BT829Ptr bt) | |
379 | { /* P_IO */ | |
380 | if (BTVERSION >= BT827) { | |
381 | btwrite(bt, P_IO, bt->p_io); | |
382 | } | |
383 | } | |
384 | ||
385 | /* | |
386 | * Deal with dependencies | |
387 | */ | |
388 | static void | |
389 | propagate_changes(BT829Ptr bt) | |
390 | { | |
391 | CARD16 hdelay, unscaled_hdelay, vdelay, hscale, vscale; | |
392 | int htotal, vactive; | |
393 | ||
394 | switch (bt->format) { | |
395 | case BT829_NTSC: | |
396 | case BT829_NTSC_JAPAN: | |
397 | case BT829_PAL_M: | |
398 | vdelay = 22; | |
399 | htotal = 754; | |
400 | vactive = 480; | |
401 | unscaled_hdelay = 135; | |
402 | break; | |
403 | case BT829_PAL: | |
404 | case BT829_PAL_N: | |
405 | vdelay = (bt->tunertype == 5) ? 34 : 22; | |
406 | htotal = 922; | |
407 | vactive = 576; | |
408 | unscaled_hdelay = 186; | |
409 | break; | |
410 | case BT829_SECAM: | |
411 | vdelay = 34; | |
412 | htotal = 922; | |
413 | vactive = 576; | |
414 | unscaled_hdelay = 186; | |
415 | break; | |
416 | case BT829_PAL_N_COMB: | |
417 | vdelay = (bt->tunertype == 5) ? 34 : 22; /* windows says 22 */ | |
418 | htotal = 754; /* gatos and windows say 922 */ | |
419 | vactive = 576; | |
420 | unscaled_hdelay = 135; /* gatos and windows say 186 */ | |
421 | break; | |
422 | default: /* shouldn't get here */ | |
423 | vdelay = 22; /* hardware default */ | |
424 | htotal = 754; | |
425 | vactive = 480; /* hardware default */ | |
426 | unscaled_hdelay = 135; | |
427 | break; | |
428 | } | |
429 | ||
430 | bt->htotal = htotal; /* Used for error checking in bt829_SetCaptSize */ | |
431 | ||
432 | hscale = 4096 * htotal / (bt->width + 2 * HCROP) - 4096; | |
433 | hdelay = | |
434 | (HCROP + (bt->width + 2 * HCROP) * unscaled_hdelay / htotal) & 0x3FE; | |
435 | ||
436 | vactive = vactive - 2 * VCROP; | |
437 | vdelay = vdelay + VCROP; | |
438 | vscale = (0x10000 - (512 * vactive / bt->height - 512)) & 0x1FFF; | |
439 | ||
440 | if ((hdelay != bt->hdelay) || (vdelay != bt->vdelay) || | |
441 | (vactive != bt->vactive) || (hscale != bt->hscale) || | |
442 | (vscale != bt->vscale)) { | |
443 | bt->hdelay = hdelay; | |
444 | bt->vdelay = vdelay; | |
445 | bt->vactive = vactive; | |
446 | bt->hscale = hscale; | |
447 | bt->vscale = vscale; | |
448 | btwrite_crop(bt); | |
449 | btwrite_vdelay_lo(bt); | |
450 | btwrite_vactive_lo(bt); | |
451 | btwrite_hdelay_lo(bt); | |
452 | btwrite_hscale_hi(bt); | |
453 | btwrite_hscale_lo(bt); | |
454 | btwrite_control(bt); | |
455 | btwrite_vscale_hi(bt); | |
456 | btwrite_vscale_lo(bt); | |
457 | } | |
458 | } | |
459 | ||
460 | static void | |
461 | write_all(BT829Ptr bt) | |
462 | { | |
463 | bt_reset(bt); | |
464 | propagate_changes(bt); /* ensure consistency */ | |
465 | btwrite_iform(bt); | |
466 | btwrite_tdec(bt); | |
467 | btwrite_crop(bt); | |
468 | btwrite_vdelay_lo(bt); | |
469 | btwrite_vactive_lo(bt); | |
470 | btwrite_hdelay_lo(bt); | |
471 | btwrite_hactive_lo(bt); | |
472 | btwrite_hscale_hi(bt); | |
473 | btwrite_hscale_lo(bt); | |
474 | btwrite_bright(bt); | |
475 | btwrite_control(bt); | |
476 | btwrite_contrast_lo(bt); | |
477 | btwrite_sat_u_lo(bt); | |
478 | btwrite_sat_v_lo(bt); | |
479 | btwrite_hue(bt); | |
480 | btwrite_scloop(bt); | |
481 | btwrite_wc_up(bt); | |
482 | btwrite_oform(bt); | |
483 | btwrite_vscale_hi(bt); | |
484 | btwrite_vscale_lo(bt); | |
485 | btwrite_vpole(bt); | |
486 | btwrite_adelay(bt); | |
487 | btwrite_bdelay(bt); | |
488 | btwrite_adc(bt); | |
489 | btwrite_vtc(bt); | |
490 | /* btwrite_cc_status(bt); *//* FIXME: CC code needs cleaning */ | |
491 | btwrite_wc_dn(bt); | |
492 | btwrite_p_io(bt); | |
493 | } | |
494 | ||
495 | /* | |
496 | * Public functions | |
497 | */ | |
498 | BT829Ptr | |
499 | bt829_Detect(I2CBusPtr b, I2CSlaveAddr addr) | |
500 | { | |
501 | BT829Ptr bt; | |
502 | I2CByte a; | |
503 | ||
504 | bt = calloc(1, sizeof(BT829Rec)); | |
505 | if (bt == NULL) | |
506 | return NULL; | |
507 | bt->d.DevName = strdup("BT829 video decoder"); | |
508 | bt->d.SlaveAddr = addr; | |
509 | bt->d.pI2CBus = b; | |
510 | bt->d.NextDev = NULL; | |
511 | bt->d.StartTimeout = b->StartTimeout; | |
512 | bt->d.BitTimeout = b->BitTimeout; | |
513 | bt->d.AcknTimeout = b->AcknTimeout; | |
514 | bt->d.ByteTimeout = b->ByteTimeout; | |
515 | ||
516 | if (!I2C_WriteRead(&(bt->d), NULL, 0, &a, 1)) { | |
517 | free(bt); | |
518 | return NULL; | |
519 | } | |
520 | ||
521 | bt->id = btread(bt, IDCODE); | |
522 | ||
523 | free(bt->d.DevName); | |
524 | bt->d.DevName = calloc(200, sizeof(char)); | |
525 | switch (BTVERSION) { | |
526 | case BT815: | |
527 | sprintf(bt->d.DevName, "bt815a video decoder, revision %d", | |
528 | bt->id & 0xf); | |
529 | break; | |
530 | case BT817: | |
531 | sprintf(bt->d.DevName, "bt817a video decoder, revision %d", | |
532 | bt->id & 0xf); | |
533 | break; | |
534 | case BT819: | |
535 | sprintf(bt->d.DevName, "bt819a video decoder, revision %d", | |
536 | bt->id & 0xf); | |
537 | break; | |
538 | case BT827: | |
539 | sprintf(bt->d.DevName, "bt827a/b video decoder, revision %d", | |
540 | bt->id & 0xf); | |
541 | break; | |
542 | case BT829: | |
543 | sprintf(bt->d.DevName, "bt829a/b video decoder, revision %d", | |
544 | bt->id & 0xf); | |
545 | break; | |
546 | default: | |
547 | sprintf(bt->d.DevName, | |
548 | "bt8xx/unknown video decoder version %d, revision %d", | |
549 | bt->id >> 4, bt->id & 0xf); | |
550 | break; | |
551 | } | |
552 | ||
553 | /* set default parameters */ | |
554 | if (!I2CDevInit(&(bt->d))) { | |
555 | free(bt); | |
556 | return NULL; | |
557 | } | |
558 | ||
559 | bt->tunertype = 1; | |
560 | ||
561 | bt->brightness = 0; /* hardware default */ | |
562 | bt->ccmode = 0; | |
563 | bt->code = 0; /* hardware default */ | |
564 | bt->contrast = 216; /* hardware default */ | |
565 | bt->format = BT829_NTSC; | |
566 | bt->height = 480; /* hardware default for vactive */ | |
567 | bt->hue = 0; /* hardware default */ | |
568 | bt->len = 1; /* hardware default */ | |
569 | bt->mux = BT829_MUX0; /* hardware default */ | |
570 | bt->out_en = 0; /* hardware default */ | |
571 | bt->p_io = 0; /* hardware default */ | |
572 | bt->sat_u = 254; /* hardware default */ | |
573 | bt->sat_v = 180; /* hardware default */ | |
574 | bt->vbien = 0; /* hardware default */ | |
575 | bt->vbifmt = 0; /* hardware default */ | |
576 | bt->width = 640; /* hardware default for hactive */ | |
577 | ||
578 | bt->hdelay = 120; /* hardware default */ | |
579 | bt->hscale = 684; /* hardware default */ | |
580 | bt->vactive = 480; /* hardware default */ | |
581 | bt->vdelay = 22; /* hardware default */ | |
582 | bt->vscale = 0; /* hardware default */ | |
583 | ||
584 | bt->htotal = 754; /* NTSC */ | |
585 | bt->svideo_mux = 0; /* no s-video */ | |
586 | ||
587 | return bt; | |
588 | } | |
589 | ||
590 | int | |
591 | bt829_ATIInit(BT829Ptr bt) | |
592 | { | |
593 | bt->code = 1; | |
594 | bt->len = 0; | |
595 | bt->vbien = 1; | |
596 | bt->vbifmt = 1; | |
597 | bt->svideo_mux = BT829_MUX1; | |
598 | ||
599 | write_all(bt); | |
600 | ||
601 | return 0; | |
602 | } | |
603 | ||
604 | int | |
605 | bt829_SetFormat(BT829Ptr bt, CARD8 format) | |
606 | { | |
607 | if ((format < 1) || (format > 7)) | |
608 | return -1; | |
609 | if ((BTVERSION <= BT819) && (format != BT829_NTSC) && (format != BT829_PAL)) | |
610 | return -1; | |
611 | if (format == bt->format) | |
612 | return 0; | |
613 | bt->format = format; | |
614 | propagate_changes(bt); | |
615 | btwrite_iform(bt); | |
616 | btwrite_scloop(bt); | |
617 | btwrite_adelay(bt); | |
618 | btwrite_bdelay(bt); | |
619 | btwrite_vtc(bt); | |
620 | return 0; | |
621 | } | |
622 | ||
623 | int | |
624 | bt829_SetMux(BT829Ptr bt, CARD8 mux) | |
625 | { | |
626 | if ((mux < 1) || (mux > 3)) | |
627 | return -1; | |
628 | if (mux == bt->mux) | |
629 | return 0; | |
630 | bt->mux = mux; | |
631 | /* propagate_changes(bt); *//* no dependencies */ | |
632 | btwrite_iform(bt); | |
633 | btwrite_control(bt); | |
634 | btwrite_adc(bt); | |
635 | return 0; | |
636 | } | |
637 | ||
638 | void | |
639 | bt829_SetBrightness(BT829Ptr bt, int brightness) | |
640 | { | |
641 | brightness = LIMIT(brightness, -1000, 999); /* ensure -128 <= brightness <= 127 below */ | |
642 | brightness = (128 * brightness) / 1000; | |
643 | if (brightness == bt->brightness) | |
644 | return; | |
645 | bt->brightness = brightness; | |
646 | /* propagate_changes(bt); *//* no dependencies */ | |
647 | btwrite_bright(bt); | |
648 | } | |
649 | ||
650 | void | |
651 | bt829_SetContrast(BT829Ptr bt, int contrast) | |
652 | { | |
653 | contrast = LIMIT(contrast, -1000, 1000); | |
654 | contrast = (216 * (contrast + 1000)) / 1000; | |
655 | if (contrast == bt->contrast) | |
656 | return; | |
657 | bt->contrast = contrast; | |
658 | /* propagate_changes(bt); *//* no dependencies */ | |
659 | btwrite_control(bt); | |
660 | btwrite_contrast_lo(bt); | |
661 | } | |
662 | ||
663 | void | |
664 | bt829_SetSaturation(BT829Ptr bt, int saturation) | |
665 | { | |
666 | CARD16 sat_u, sat_v; | |
667 | ||
668 | saturation = LIMIT(saturation, -1000, 1000); | |
669 | sat_u = (254 * (saturation + 1000)) / 1000; | |
670 | sat_v = (180 * (saturation + 1000)) / 1000; | |
671 | if ((sat_u == bt->sat_u) && (sat_v == bt->sat_v)) | |
672 | return; | |
673 | bt->sat_u = sat_u; | |
674 | bt->sat_v = sat_v; | |
675 | /* propagate_changes(bt); *//* no dependencies */ | |
676 | btwrite_control(bt); | |
677 | btwrite_sat_u_lo(bt); | |
678 | btwrite_sat_v_lo(bt); | |
679 | } | |
680 | ||
681 | void | |
682 | bt829_SetTint(BT829Ptr bt, int hue) | |
683 | { | |
684 | hue = LIMIT(hue, -1000, 999); /* ensure -128 <= hue <= 127 below */ | |
685 | hue = (128 * hue) / 1000; | |
686 | if (hue == bt->hue) | |
687 | return; | |
688 | bt->hue = hue; | |
689 | /* propagate_changes(bt); *//* no dependencies */ | |
690 | btwrite_hue(bt); | |
691 | } | |
692 | ||
693 | int | |
694 | bt829_SetCaptSize(BT829Ptr bt, int width, int height) | |
695 | { | |
696 | if ((width > bt->htotal - 2 * HCROP) || | |
697 | (16 * width < bt->htotal - 32 * HCROP)) | |
698 | return -1; | |
699 | if ((height > bt->vactive) || (16 * height < bt->vactive)) | |
700 | return -1; | |
701 | if ((width == bt->width) && (height == bt->height)) | |
702 | return 0; | |
703 | bt->width = width; | |
704 | bt->height = height; | |
705 | propagate_changes(bt); | |
706 | btwrite_crop(bt); | |
707 | btwrite_hactive_lo(bt); | |
708 | btwrite_control(bt); | |
709 | btwrite_vtc(bt); | |
710 | return 0; | |
711 | } | |
712 | ||
713 | int | |
714 | bt829_SetCC(BT829Ptr bt) | |
715 | { /* FIXME: should take ccmode as a parameter */ | |
716 | if (BTVERSION < BT827) | |
717 | return -1; /* can't do it */ | |
718 | /* propagate_changes(bt); *//* no dependencies */ | |
719 | btwrite_cc_status(bt); | |
720 | /* we write to STATUS to reset the CCVALID flag */ | |
721 | if (bt->ccmode != 0) | |
722 | btwrite_status(bt); | |
723 | return 0; | |
724 | } | |
725 | ||
726 | void | |
727 | bt829_SetOUT_EN(BT829Ptr bt, BOOL out_en) | |
728 | { | |
729 | out_en = (out_en != 0); | |
730 | if (out_en == bt->out_en) | |
731 | return; | |
732 | bt->out_en = out_en; | |
733 | /* propagate_changes(bt); *//* no dependencies */ | |
734 | btwrite_vpole(bt); | |
735 | } | |
736 | ||
737 | void | |
738 | bt829_SetP_IO(BT829Ptr bt, CARD8 p_io) | |
739 | { | |
740 | if (p_io == bt->p_io) | |
741 | return; | |
742 | bt->p_io = p_io; | |
743 | /* propagate_changes(bt); *//* no dependencies */ | |
744 | btwrite_p_io(bt); | |
745 | } | |
746 | ||
747 | #define BTREAD(R) btread(bt,(R)) | |
748 | ||
749 | #if 0 | |
750 | ||
751 | void | |
752 | bt829_getCCdata(BT829Ptr bt, struct CCdata *data) | |
753 | { | |
754 | CARD8 status; | |
755 | ||
756 | data->num_valid = 0; | |
757 | /* wait for buffer to be half full (means 8/16 bytes) | |
758 | * either 4 (one of CC/EDS) or 2 (both CC/EDS) frames */ | |
759 | if (!(BTREAD(STATUS) & 0x04)) | |
760 | return; /* could comment this line */ | |
761 | for (; data->num_valid < CC_FIFO_SIZE; data->num_valid++) { | |
762 | status = BTREAD(CC_STATUS); | |
763 | if (!(status & 0x04)) | |
764 | break; | |
765 | data->data[data->num_valid] = BTREAD(CC_DATA) & 0x7f; | |
766 | /* stripped high bit (parity) */ | |
767 | data->status[data->num_valid] = (CCS_EDS * ((status & 0x02) >> 1)) | | |
768 | (CCS_HIGH * (status & 0x01)) | | |
769 | (CCS_OVER * ((status & 0x08) >> 3)) | | |
770 | (CCS_PAR * ((status & 0x80) >> 7)); | |
771 | } | |
772 | btwrite(bt, STATUS, 0x00); /* Reset CCVALID status bit */ | |
773 | return; | |
774 | } | |
775 | ||
776 | #endif | |
777 | ||
778 | /* ------------------------------------------------------------------------ */ | |
779 | /* Debug and report routines */ | |
780 | ||
781 | #define DUMPREG(REG) \ | |
782 | xf86DrvMsg(bt->d.pI2CBus->scrnIndex,X_INFO," %-12s (0x%02X) = 0x%02X\n", \ | |
783 | #REG,REG,BTREAD(REG)) | |
784 | ||
785 | /*static void bt829_dumpregs(BT829Ptr bt) | |
786 | { | |
787 | DUMPREG(STATUS); | |
788 | DUMPREG(IFORM); | |
789 | DUMPREG(TDEC); | |
790 | DUMPREG(CROP); | |
791 | DUMPREG(VDELAY_LO); | |
792 | DUMPREG(VACTIVE_LO); | |
793 | DUMPREG(HDELAY_LO); | |
794 | DUMPREG(HACTIVE_LO); | |
795 | DUMPREG(HSCALE_HI); | |
796 | DUMPREG(HSCALE_LO); | |
797 | DUMPREG(BRIGHT); | |
798 | DUMPREG(CONTROL); | |
799 | DUMPREG(CONTRAST_LO); | |
800 | DUMPREG(SAT_U_LO); | |
801 | DUMPREG(SAT_V_LO); | |
802 | DUMPREG(HUE); | |
803 | if (BTVERSION >= BT827) { | |
804 | DUMPREG(SCLOOP); | |
805 | DUMPREG(WC_UP) ; } | |
806 | DUMPREG(OFORM); | |
807 | DUMPREG(VSCALE_HI); | |
808 | DUMPREG(VSCALE_LO); | |
809 | DUMPREG(TEST); | |
810 | DUMPREG(VPOLE); | |
811 | DUMPREG(IDCODE); | |
812 | DUMPREG(ADELAY); | |
813 | DUMPREG(BDELAY); | |
814 | DUMPREG(ADC); | |
815 | if (BTVERSION >= BT827) { | |
816 | DUMPREG(VTC); | |
817 | DUMPREG(CC_STATUS); | |
818 | DUMPREG(CC_DATA); | |
819 | DUMPREG(WC_DN); | |
820 | DUMPREG(P_IO) ; } | |
821 | }*/ |