1 /* TODO: clean up/fix CC code */
3 #ifdef HAVE_XORG_CONFIG_H
4 #include <xorg-config.h>
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 */
21 #define BTVERSION (bt->id>>4)
23 #define H(X) ( ((X)>>8) & 0xFF )
24 #define L(X) ( (X) & 0xFF )
26 #define LIMIT(X,A,B) (((X)<(A)) ? (A) : ((X)>(B)) ? (B) : (X) )
28 /* Bt829 family chip ID's */
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 */
71 btread(BT829Ptr bt
, CARD8 reg
)
75 I2C_WriteRead(&(bt
->d
), ®
, 1, &v
, 1);
81 btwrite(BT829Ptr bt
, CARD8 reg
, CARD8 val
)
87 I2C_WriteRead(&(bt
->d
), data
, 2, NULL
, 0);
94 btwrite_status(BT829Ptr bt
)
96 btwrite(bt
, STATUS
, 0x00); /* clear */
100 btwrite_iform(BT829Ptr bt
)
104 switch (bt
->format
) {
106 case BT829_NTSC_JAPAN
:
108 case BT829_PAL_N_COMB
: /* gatos says xtsel = 2 */
116 default: /* shouldn't get here */
117 xtsel
= 3; /* hardware default */
121 btwrite(bt
, IFORM
, (bt
->mux
<< 5) | (xtsel
<< 3) | bt
->format
);
125 btwrite_tdec(BT829Ptr bt
)
131 btwrite_crop(BT829Ptr bt
)
133 btwrite(bt
, CROP
, (H(bt
->vdelay
) << 6) | (H(bt
->vactive
) << 4) |
134 (H(bt
->hdelay
) << 2) | H(bt
->width
));
138 btwrite_vdelay_lo(BT829Ptr bt
)
140 btwrite(bt
, VDELAY_LO
, L(bt
->vdelay
));
144 btwrite_vactive_lo(BT829Ptr bt
)
146 btwrite(bt
, VACTIVE_LO
, L(bt
->vactive
));
150 btwrite_hdelay_lo(BT829Ptr bt
)
152 btwrite(bt
, HDELAY_LO
, L(bt
->hdelay
));
156 btwrite_hactive_lo(BT829Ptr bt
)
158 btwrite(bt
, HACTIVE_LO
, L(bt
->width
));
162 btwrite_hscale_hi(BT829Ptr bt
)
164 btwrite(bt
, HSCALE_HI
, H(bt
->hscale
));
168 btwrite_hscale_lo(BT829Ptr bt
)
170 btwrite(bt
, HSCALE_LO
, L(bt
->hscale
));
174 btwrite_bright(BT829Ptr bt
)
176 btwrite(bt
, BRIGHT
, bt
->brightness
);
180 btwrite_control(BT829Ptr bt
)
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 */
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
->
194 btwrite_contrast_lo(BT829Ptr bt
)
196 btwrite(bt
, CONTRAST_LO
, L(bt
->contrast
));
200 btwrite_sat_u_lo(BT829Ptr bt
)
202 btwrite(bt
, SAT_U_LO
, L(bt
->sat_u
));
206 btwrite_sat_v_lo(BT829Ptr bt
)
208 btwrite(bt
, SAT_V_LO
, L(bt
->sat_v
));
212 btwrite_hue(BT829Ptr bt
)
214 btwrite(bt
, HUE
, bt
->hue
);
218 btwrite_scloop(BT829Ptr bt
)
220 if (BTVERSION
>= BT827
) {
221 btwrite(bt
, SCLOOP
, (bt
->format
== BT829_SECAM
) ? 0x10 : 0x00 /* QCIF or AUTO */
227 btwrite_wc_up(BT829Ptr bt
)
229 if (BTVERSION
>= BT827
) {
235 btwrite_oform(BT829Ptr bt
)
237 btwrite(bt
, OFORM
, (bt
->code
<< 3) | (bt
->len
<< 2) | 0x02 /* RANGE = 0, CORE = 0, VBI_FRAME = 0, OES = 2 (default) */
242 btwrite_vscale_hi(BT829Ptr bt
)
244 btwrite(bt
, VSCALE_HI
, H(bt
->vscale
) | 0x60 /* YCOMB = 0, COMB = 1, INT = 1 (default) */
249 btwrite_vscale_lo(BT829Ptr bt
)
251 btwrite(bt
, VSCALE_LO
, L(bt
->vscale
));
254 /* TEST should not be written to */
257 btwrite_vpole(BT829Ptr bt
)
259 btwrite(bt
, VPOLE
, (bt
->out_en
<< 7));
262 /* IDCODE is read only */
265 btwrite_adelay(BT829Ptr bt
)
267 switch (bt
->format
) {
269 case BT829_NTSC_JAPAN
:
271 btwrite(bt
, ADELAY
, 104);
276 case BT829_PAL_N_COMB
:
277 btwrite(bt
, ADELAY
, 127);
279 default: /* shouldn't get here */
280 btwrite(bt
, ADELAY
, 104); /* hardware default */
286 btwrite_bdelay(BT829Ptr bt
)
288 switch (bt
->format
) {
290 case BT829_NTSC_JAPAN
:
292 btwrite(bt
, BDELAY
, 93);
296 case BT829_PAL_N_COMB
:
297 btwrite(bt
, BDELAY
, 114);
300 btwrite(bt
, BDELAY
, 160);
302 default: /* shouldn't get here */
303 btwrite(bt
, BDELAY
, 93); /* hardware default */
309 btwrite_adc(BT829Ptr bt
)
311 btwrite(bt
, ADC
, bt
->mux
== bt
->svideo_mux
? 0x80 : 0x82); /* CSLEEP = 0 or 1 */
315 btwrite_vtc(BT829Ptr bt
)
317 int vfilt
= 0; /* hardware default */
319 if (BTVERSION
> BT827
) { /* gatos says >= BT827 */
320 switch (bt
->format
) {
322 case BT829_NTSC_JAPAN
:
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 */
330 vfilt
= 3; /* gatos says <= 60 */
335 if (bt
->width
<= 384)
337 if (bt
->width
<= 192)
342 default: /* shouldn't get here */
343 break; /* use hardware default */
345 btwrite(bt
, VTC
, (bt
->vbien
<< 4) | (bt
->vbifmt
<< 3) | vfilt
);
350 btwrite_cc_status(BT829Ptr bt
)
351 { /* CC_STATUS *//* FIXME: ATI specific */
352 if (BTVERSION
>= BT827
) {
354 btwrite(bt
, CC_STATUS
, 0x00);
355 /* 0x40 is activate to set the CCVALID line. Not required yet */
357 btwrite(bt
, CC_STATUS
, (bt
->ccmode
<< 4) | 0x40);
361 /* CC_DATA is read only */
364 btwrite_wc_dn(BT829Ptr bt
)
366 if (BTVERSION
>= BT827
) {
372 bt_reset(BT829Ptr bt
)
374 btwrite(bt
, SRESET
, 0x0); /* Reset all registers */
378 btwrite_p_io(BT829Ptr bt
)
380 if (BTVERSION
>= BT827
) {
381 btwrite(bt
, P_IO
, bt
->p_io
);
386 * Deal with dependencies
389 propagate_changes(BT829Ptr bt
)
391 CARD16 hdelay
, unscaled_hdelay
, vdelay
, hscale
, vscale
;
394 switch (bt
->format
) {
396 case BT829_NTSC_JAPAN
:
401 unscaled_hdelay
= 135;
405 vdelay
= (bt
->tunertype
== 5) ? 34 : 22;
408 unscaled_hdelay
= 186;
414 unscaled_hdelay
= 186;
416 case BT829_PAL_N_COMB
:
417 vdelay
= (bt
->tunertype
== 5) ? 34 : 22; /* windows says 22 */
418 htotal
= 754; /* gatos and windows say 922 */
420 unscaled_hdelay
= 135; /* gatos and windows say 186 */
422 default: /* shouldn't get here */
423 vdelay
= 22; /* hardware default */
425 vactive
= 480; /* hardware default */
426 unscaled_hdelay
= 135;
430 bt
->htotal
= htotal
; /* Used for error checking in bt829_SetCaptSize */
432 hscale
= 4096 * htotal
/ (bt
->width
+ 2 * HCROP
) - 4096;
434 (HCROP
+ (bt
->width
+ 2 * HCROP
) * unscaled_hdelay
/ htotal
) & 0x3FE;
436 vactive
= vactive
- 2 * VCROP
;
437 vdelay
= vdelay
+ VCROP
;
438 vscale
= (0x10000 - (512 * vactive
/ bt
->height
- 512)) & 0x1FFF;
440 if ((hdelay
!= bt
->hdelay
) || (vdelay
!= bt
->vdelay
) ||
441 (vactive
!= bt
->vactive
) || (hscale
!= bt
->hscale
) ||
442 (vscale
!= bt
->vscale
)) {
445 bt
->vactive
= vactive
;
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
);
455 btwrite_vscale_hi(bt
);
456 btwrite_vscale_lo(bt
);
461 write_all(BT829Ptr bt
)
464 propagate_changes(bt
); /* ensure consistency */
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
);
476 btwrite_contrast_lo(bt
);
477 btwrite_sat_u_lo(bt
);
478 btwrite_sat_v_lo(bt
);
483 btwrite_vscale_hi(bt
);
484 btwrite_vscale_lo(bt
);
490 /* btwrite_cc_status(bt); *//* FIXME: CC code needs cleaning */
499 bt829_Detect(I2CBusPtr b
, I2CSlaveAddr addr
)
504 bt
= calloc(1, sizeof(BT829Rec
));
507 bt
->d
.DevName
= strdup("BT829 video decoder");
508 bt
->d
.SlaveAddr
= addr
;
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
;
516 if (!I2C_WriteRead(&(bt
->d
), NULL
, 0, &a
, 1)) {
521 bt
->id
= btread(bt
, IDCODE
);
524 bt
->d
.DevName
= calloc(200, sizeof(char));
527 sprintf(bt
->d
.DevName
, "bt815a video decoder, revision %d",
531 sprintf(bt
->d
.DevName
, "bt817a video decoder, revision %d",
535 sprintf(bt
->d
.DevName
, "bt819a video decoder, revision %d",
539 sprintf(bt
->d
.DevName
, "bt827a/b video decoder, revision %d",
543 sprintf(bt
->d
.DevName
, "bt829a/b video decoder, revision %d",
547 sprintf(bt
->d
.DevName
,
548 "bt8xx/unknown video decoder version %d, revision %d",
549 bt
->id
>> 4, bt
->id
& 0xf);
553 /* set default parameters */
554 if (!I2CDevInit(&(bt
->d
))) {
561 bt
->brightness
= 0; /* hardware default */
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 */
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 */
584 bt
->htotal
= 754; /* NTSC */
585 bt
->svideo_mux
= 0; /* no s-video */
591 bt829_ATIInit(BT829Ptr bt
)
597 bt
->svideo_mux
= BT829_MUX1
;
605 bt829_SetFormat(BT829Ptr bt
, CARD8 format
)
607 if ((format
< 1) || (format
> 7))
609 if ((BTVERSION
<= BT819
) && (format
!= BT829_NTSC
) && (format
!= BT829_PAL
))
611 if (format
== bt
->format
)
614 propagate_changes(bt
);
624 bt829_SetMux(BT829Ptr bt
, CARD8 mux
)
626 if ((mux
< 1) || (mux
> 3))
631 /* propagate_changes(bt); *//* no dependencies */
639 bt829_SetBrightness(BT829Ptr bt
, int brightness
)
641 brightness
= LIMIT(brightness
, -1000, 999); /* ensure -128 <= brightness <= 127 below */
642 brightness
= (128 * brightness
) / 1000;
643 if (brightness
== bt
->brightness
)
645 bt
->brightness
= brightness
;
646 /* propagate_changes(bt); *//* no dependencies */
651 bt829_SetContrast(BT829Ptr bt
, int contrast
)
653 contrast
= LIMIT(contrast
, -1000, 1000);
654 contrast
= (216 * (contrast
+ 1000)) / 1000;
655 if (contrast
== bt
->contrast
)
657 bt
->contrast
= contrast
;
658 /* propagate_changes(bt); *//* no dependencies */
660 btwrite_contrast_lo(bt
);
664 bt829_SetSaturation(BT829Ptr bt
, int saturation
)
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
))
675 /* propagate_changes(bt); *//* no dependencies */
677 btwrite_sat_u_lo(bt
);
678 btwrite_sat_v_lo(bt
);
682 bt829_SetTint(BT829Ptr bt
, int hue
)
684 hue
= LIMIT(hue
, -1000, 999); /* ensure -128 <= hue <= 127 below */
685 hue
= (128 * hue
) / 1000;
689 /* propagate_changes(bt); *//* no dependencies */
694 bt829_SetCaptSize(BT829Ptr bt
, int width
, int height
)
696 if ((width
> bt
->htotal
- 2 * HCROP
) ||
697 (16 * width
< bt
->htotal
- 32 * HCROP
))
699 if ((height
> bt
->vactive
) || (16 * height
< bt
->vactive
))
701 if ((width
== bt
->width
) && (height
== bt
->height
))
705 propagate_changes(bt
);
707 btwrite_hactive_lo(bt
);
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 */
727 bt829_SetOUT_EN(BT829Ptr bt
, BOOL out_en
)
729 out_en
= (out_en
!= 0);
730 if (out_en
== bt
->out_en
)
733 /* propagate_changes(bt); *//* no dependencies */
738 bt829_SetP_IO(BT829Ptr bt
, CARD8 p_io
)
740 if (p_io
== bt
->p_io
)
743 /* propagate_changes(bt); *//* no dependencies */
747 #define BTREAD(R) btread(bt,(R))
752 bt829_getCCdata(BT829Ptr bt
, struct CCdata
*data
)
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))
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));
772 btwrite(bt
, STATUS
, 0x00); /* Reset CCVALID status bit */
778 /* ------------------------------------------------------------------------ */
779 /* Debug and report routines */
781 #define DUMPREG(REG) \
782 xf86DrvMsg(bt->d.pI2CBus->scrnIndex,X_INFO," %-12s (0x%02X) = 0x%02X\n", \
783 #REG,REG,BTREAD(REG))
785 /*static void bt829_dumpregs(BT829Ptr bt)
799 DUMPREG(CONTRAST_LO);
803 if (BTVERSION >= BT827) {
815 if (BTVERSION >= BT827) {