1 /******************************************************************************
5 / Description: ATI Rage Theater Video Decoder interface.
7 / Copyright 2001, Carlos Hasan
9 *******************************************************************************/
13 #include "Theater200.h"
14 #include "TheatreReg.h"
15 #include "lendian_bitfield.h"
21 const char* DEFAULT_MICROC_PATH
= "/boot/home/config/settings/Media/RageTheater200/ativmc20.cod";
22 const char* DEFAULT_MICROC_TYPE
= "BINARY";
24 CTheater200::CTheater200(CRadeon
& radeon
, int device
)
25 :CTheater(radeon
, device
),
26 fMode(MODE_UNINITIALIZED
),
31 PRINT(("CTheater200::CTheater200()\n"));
33 fMode
= MODE_UNINITIALIZED
;
35 if( fPort
.InitCheck() == B_OK
) {
36 radeon_video_tuner tuner
;
37 radeon_video_decoder video
;
39 radeon
.GetMMParameters(tuner
, video
, fClock
,
40 fTunerPort
, fCompositePort
, fSVideoPort
);
42 if (fClock
!= C_RADEON_VIDEO_CLOCK_29_49892_MHZ
&&
43 fClock
!= C_RADEON_VIDEO_CLOCK_27_00000_MHZ
)
44 PRINT(("CTheater200::CTheater200() - Unsupported crystal clock!\n"));
46 // fDevice = fPort.FindVIPDevice( C_THEATER200_VIP_DEVICE_ID );
50 if( InitCheck() != B_OK
)
51 PRINT(("CTheater200::CTheater200() - Rage Theater not found!\n"));
57 CTheater200::~CTheater200()
59 PRINT(("CTheater200::~CTheater200()\n"));
61 if( InitCheck() == B_OK
)
62 SetEnable(false, false);
66 status_t
CTheater200::InitCheck() const
70 res
= fPort
.InitCheck();
73 PRINT(("CTheater200::InitCheck() fPort Failed\n"));
77 res
= (fDevice
>= C_VIP_PORT_DEVICE_0
&& fDevice
<= C_VIP_PORT_DEVICE_3
) ? B_OK
: B_ERROR
;
80 PRINT(("CTheater200::InitCheck() Invalid VIP Channel\n"));
84 if (fMode
!= MODE_INITIALIZED_FOR_TV_IN
);
87 PRINT(("CTheater200::InitCheck() Sucess\n"));
91 void CTheater200::Reset()
93 PRINT(("CTheater200::Reset()\n"));
102 status_t
CTheater200::DSPLoadMicrocode(char* micro_path
, char* micro_type
, struct rt200_microc_data
* microc_datap
)
105 struct rt200_microc_head
* microc_headp
= µc_datap
->microc_head
;
106 struct rt200_microc_seg
* seg_list
= NULL
;
107 struct rt200_microc_seg
* curr_seg
= NULL
;
108 struct rt200_microc_seg
* prev_seg
= NULL
;
111 if (micro_path
== NULL
)
114 if (micro_type
== NULL
)
117 file
= fopen(micro_path
, "r");
119 PRINT(("Cannot open microcode file\n"));
123 if (!strcmp(micro_type
, "BINARY"))
125 if (fread(microc_headp
, sizeof(struct rt200_microc_head
), 1, file
) != 1)
127 PRINT(("Cannot read header from file: %s\n", micro_path
));
131 PRINT(("Microcode: num_seg: %x\n", microc_headp
->num_seg
));
133 if (microc_headp
->num_seg
== 0)
136 for (i
= 0; i
< microc_headp
->num_seg
; i
++)
140 curr_seg
= (struct rt200_microc_seg
*) malloc(sizeof(struct rt200_microc_seg
));
141 if (curr_seg
== NULL
)
143 PRINT(("Cannot allocate memory\n"));
147 ret
= fread(&curr_seg
->num_bytes
, 4, 1, file
);
148 ret
+= fread(&curr_seg
->download_dst
, 4, 1, file
);
149 ret
+= fread(&curr_seg
->crc_val
, 4, 1, file
);
152 PRINT(("Cannot read segment from microcode file: %s\n", micro_path
));
156 curr_seg
->data
= (unsigned char*) malloc(curr_seg
->num_bytes
);
157 if (curr_seg
->data
== NULL
)
159 PRINT(("cannot allocate memory\n"));
163 PRINT(("Microcode: segment number: %x\n", i
));
164 PRINT(("Microcode: curr_seg->num_bytes: %x\n", curr_seg
->num_bytes
));
165 PRINT(("Microcode: curr_seg->download_dst: %x\n", curr_seg
->download_dst
));
166 PRINT(("Microcode: curr_seg->crc_val: %x\n", curr_seg
->crc_val
));
170 prev_seg
->next
= curr_seg
;
171 curr_seg
->next
= NULL
;
175 seg_list
= prev_seg
= curr_seg
;
182 if ( fread(curr_seg
->data
, curr_seg
->num_bytes
, 1, file
) != 1 )
184 PRINT(("Cannot read segment data\n"));
188 curr_seg
= curr_seg
->next
;
191 else if (!strcmp(micro_type
, "ASCII"))
193 char tmp1
[12], tmp2
[12], tmp3
[12], tmp4
[12];
196 if ((fgets(tmp1
, 12, file
) != NULL
) &&
197 (fgets(tmp2
, 12, file
) != NULL
) &&
198 (fgets(tmp3
, 12, file
) != NULL
) &&
199 fgets(tmp4
, 12, file
) != NULL
)
201 microc_headp
->device_id
= strtoul(tmp1
, NULL
, 16);
202 microc_headp
->vendor_id
= strtoul(tmp2
, NULL
, 16);
203 microc_headp
->revision_id
= strtoul(tmp3
, NULL
, 16);
204 microc_headp
->num_seg
= strtoul(tmp4
, NULL
, 16);
208 PRINT(("Cannot read header from file: %s\n", micro_path
));
212 PRINT(("Microcode: num_seg: %x\n", microc_headp
->num_seg
));
214 if (microc_headp
->num_seg
== 0)
217 for (i
= 0; i
< microc_headp
->num_seg
; i
++)
219 curr_seg
= (struct rt200_microc_seg
*) malloc(sizeof(struct rt200_microc_seg
));
220 if (curr_seg
== NULL
)
222 PRINT(("Cannot allocate memory\n"));
226 if (fgets(tmp1
, 12, file
) != NULL
&&
227 fgets(tmp2
, 12, file
) != NULL
&&
228 fgets(tmp3
, 12, file
) != NULL
)
230 curr_seg
->num_bytes
= strtoul(tmp1
, NULL
, 16);
231 curr_seg
->download_dst
= strtoul(tmp2
, NULL
, 16);
232 curr_seg
->crc_val
= strtoul(tmp3
, NULL
, 16);
236 PRINT(("Cannot read segment from microcode file: %s\n", micro_path
));
240 curr_seg
->data
= (unsigned char*) malloc(curr_seg
->num_bytes
);
241 if (curr_seg
->data
== NULL
)
243 PRINT(("cannot allocate memory\n"));
247 PRINT(("Microcode: segment number: %x\n", i
));
248 PRINT(("Microcode: curr_seg->num_bytes: %x\n", curr_seg
->num_bytes
));
249 PRINT(("Microcode: curr_seg->download_dst: %x\n", curr_seg
->download_dst
));
250 PRINT(("Microcode: curr_seg->crc_val: %x\n", curr_seg
->crc_val
));
254 curr_seg
->next
= NULL
;
255 prev_seg
->next
= curr_seg
;
259 seg_list
= prev_seg
= curr_seg
;
265 for ( i
= 0; i
< curr_seg
->num_bytes
; i
+=4)
268 if ( fgets(tmp1
, 12, file
) == NULL
)
270 PRINT(("Cannot read from file\n"));
273 ltmp
= strtoul(tmp1
, NULL
, 16);
275 *(unsigned int*)(curr_seg
->data
+ i
) = ltmp
;
278 curr_seg
= curr_seg
->next
;
284 PRINT(("File type %s unknown\n", micro_type
));
287 microc_datap
->microc_seg_list
= seg_list
;
296 free(curr_seg
->data
);
298 curr_seg
= curr_seg
->next
;
307 void CTheater200::DSPCleanMicrocode(struct rt200_microc_data
* microc_datap
)
309 struct rt200_microc_seg
* seg_list
= microc_datap
->microc_seg_list
;
310 struct rt200_microc_seg
* prev_seg
;
314 free(seg_list
->data
);
316 seg_list
= seg_list
->next
;
322 status_t
CTheater200::DspInit()
327 PRINT(("CTheater200::Dsp_Init()\n"));
329 /* Map FIFOD to DSP Port I/O port */
330 data
= Register(VIP_HOSTINTF_PORT_CNTL
);
331 SetRegister(VIP_HOSTINTF_PORT_CNTL
, data
& (~VIP_HOSTINTF_PORT_CNTL__FIFO_RW_MODE
));
333 /* The default endianess is LE. It matches the ost one for x86 */
334 data
= Register(VIP_HOSTINTF_PORT_CNTL
);
335 SetRegister(VIP_HOSTINTF_PORT_CNTL
, data
& (~VIP_HOSTINTF_PORT_CNTL__FIFOD_ENDIAN_SWAP
));
337 /* Wait until Shuttle bus channel 14 is available */
338 data
= Register(VIP_TC_STATUS
);
339 while(((data
& VIP_TC_STATUS__TC_CHAN_BUSY
) & 0x00004000) && (i
++ < 10000))
340 data
= Register(VIP_TC_STATUS
);
342 PRINT(("Microcode: dsp_init: channel 14 available\n"));
347 status_t
CTheater200::DspLoad( struct rt200_microc_data
* microc_datap
)
350 struct rt200_microc_seg
* seg_list
= microc_datap
->microc_seg_list
;
352 uint32 data
, fb_scratch0
, fb_scratch1
;
358 PRINT(("Microcode: before everything: %x\n", data8
));
360 if (ReadFifo(0x000, &data8
))
361 PRINT(("Microcode: FIFO status0: %x\n", data8
));
364 PRINT(("Microcode: error reading FIFO status0\n"));
369 if (ReadFifo(0x100, &data8
))
370 PRINT(("Microcode: FIFO status1: %x\n", data8
));
373 PRINT(("Microcode: error reading FIFO status1\n"));
378 * Download the Boot Code and CRC Checking Code (first segment)
380 //debugger("DSPLoad");
382 while(result
!= DSP_OK
&& tries
++ < 10)
385 /* Put DSP in reset before download (0x02) */
386 data
= Register(VIP_TC_DOWNLOAD
);
387 SetRegister(VIP_TC_DOWNLOAD
, (data
& ~VIP_TC_DOWNLOAD__TC_RESET_MODE
) | (0x02 << 17));
390 * Configure shuttle bus for tranfer between DSP I/O "Program Interface"
391 * and Program Memory at address 0
394 SetRegister(VIP_TC_SOURCE
, 0x90000000);
395 SetRegister(VIP_TC_DESTINATION
, 0x00000000);
396 SetRegister(VIP_TC_COMMAND
, 0xe0000044 | ((seg_list
->num_bytes
- 1) << 7));
398 /* Load first segment */
399 PRINT(("Microcode: Loading first segment\n"));
401 if (!WriteFifo(0x700, seg_list
->num_bytes
, seg_list
->data
))
403 PRINT(("Microcode: write to FIFOD failed\n"));
407 /* Wait until Shuttle bus channel 14 is available */
409 data
= Register(VIP_TC_STATUS
);
410 while(((data
& VIP_TC_STATUS__TC_CHAN_BUSY
) & 0x00004000) && (i
++ < 10000))
411 data
= Register(VIP_TC_STATUS
);
415 PRINT(("Microcode: channel 14 timeout\n"));
419 PRINT(("Microcode: dsp_load: checkpoint 1\n"));
420 PRINT(("Microcode: TC_STATUS: %x\n", data
));
422 /* transfer the code from program memory to data memory */
423 SetRegister(VIP_TC_SOURCE
, 0x00000000);
424 SetRegister(VIP_TC_DESTINATION
, 0x10000000);
425 SetRegister(VIP_TC_COMMAND
, 0xe0000006 | ((seg_list
->num_bytes
- 1) << 7));
427 /* Wait until Shuttle bus channel 14 is available */
429 data
= Register(VIP_TC_STATUS
);
430 while(((data
& VIP_TC_STATUS__TC_CHAN_BUSY
) & 0x00004000) && (i
++ < 10000))
431 data
= Register(VIP_TC_STATUS
);
435 PRINT(("Microcode: channel 14 timeout\n"));
438 PRINT(("Microcode: dsp_load: checkpoint 2\n"));
439 PRINT(("Microcode: TC_STATUS: %x\n", data
));
441 /* Take DSP out from reset (0x0) */
442 data
= Register(VIP_TC_DOWNLOAD
);
443 SetRegister(VIP_TC_DOWNLOAD
, data
& ~VIP_TC_DOWNLOAD__TC_RESET_MODE
);
445 data
= Register(VIP_TC_STATUS
);
446 PRINT(("Microcode: dsp_load: checkpoint 3\n"));
447 PRINT(("Microcode: TC_STATUS: %x\n", data
));
449 /* send dsp_download_check_CRC */
450 fb_scratch0
= ((seg_list
->num_bytes
<< 16) & 0xffff0000) | ((seg_id
<< 8) & 0xff00) | (0xff & 193);
451 fb_scratch1
= (unsigned int)seg_list
->crc_val
;
453 result
= DspSendCommand(fb_scratch1
, fb_scratch0
);
455 PRINT(("Microcode: dsp_load: checkpoint 4\n"));
458 //debugger("DSPLoad");
462 PRINT(("Microcode: Download of boot degment failed\n"));
466 PRINT(("Microcode: Download of boot code succeeded\n"));
468 while((seg_list
= seg_list
->next
) != NULL
)
472 while(result
!= DSP_OK
&& tries
++ < 10)
475 * Configure shuttle bus for tranfer between DSP I/O "Program Interface"
476 * and Data Memory at address 0
479 SetRegister(VIP_TC_SOURCE
, 0x90000000);
480 SetRegister(VIP_TC_DESTINATION
, 0x10000000);
481 SetRegister(VIP_TC_COMMAND
, 0xe0000044 | ((seg_list
->num_bytes
- 1) << 7));
483 if (!WriteFifo(0x700, seg_list
->num_bytes
, seg_list
->data
))
485 PRINT(("Microcode: write to FIFOD failed\n"));
490 data
= Register(VIP_TC_STATUS
);
491 while(((data
& VIP_TC_STATUS__TC_CHAN_BUSY
) & 0x00004000) && (i
++ < 10000))
492 data
= Register(VIP_TC_STATUS
);
494 /* send dsp_download_check_CRC */
495 fb_scratch0
= ((seg_list
->num_bytes
<< 16) & 0xffff0000) | ((seg_id
<< 8) & 0xff00) | (0xff & 193);
496 fb_scratch1
= (unsigned int)seg_list
->crc_val
;
498 result
= DspSendCommand(fb_scratch1
, fb_scratch0
);
503 PRINT(("Microcode: DSP failed to move seg: %x from data to code memory\n", seg_id
));
507 PRINT(("Microcode: segment: %x loaded\n", seg_id
));
510 * The segment is downloaded correctly to data memory. Now move it to code memory
511 * by using dsp_download_code_transfer command.
514 fb_scratch0
= ((seg_list
->num_bytes
<< 16) & 0xffff0000) | ((seg_id
<< 8) & 0xff00) | (0xff & 194);
515 fb_scratch1
= (unsigned int)seg_list
->download_dst
;
517 result
= DspSendCommand(fb_scratch1
, fb_scratch0
);
519 if (result
!= DSP_OK
)
521 PRINT(("Microcode: DSP failed to move seg: %x from data to code memory\n", seg_id
));
526 PRINT(("Microcode: download complete\n"));
529 * The last step is sending dsp_download_check_CRC with "download complete"
532 fb_scratch0
= ((165 << 8) & 0xff00) | (0xff & 193);
533 fb_scratch1
= (unsigned int)0x11111;
535 result
= DspSendCommand(fb_scratch1
, fb_scratch0
);
537 if (result
== DSP_OK
)
538 PRINT(("Microcode: DSP microcode successfully loaded\n"));
541 PRINT(("Microcode: DSP microcode UNsuccessfully loaded\n"));
548 status_t
CTheater200::DspSendCommand(uint32 fb_scratch1
, uint32 fb_scratch0
)
554 * Clear the FB_INT0 bit in INT_CNTL
556 data
= Register(VIP_INT_CNTL
);
557 SetRegister(VIP_INT_CNTL
, data
| VIP_INT_CNTL__FB_INT0_CLR
);
560 * Write FB_SCRATCHx registers. If FB_SCRATCH1==0 then we have a DWORD command.
562 SetRegister(VIP_FB_SCRATCH0
, fb_scratch0
);
563 if (fb_scratch1
!= 0)
564 SetRegister(VIP_FB_SCRATCH1
, fb_scratch1
);
567 * Attention DSP. We are talking to you.
569 data
= Register(VIP_FB_INT
);
570 SetRegister(VIP_FB_INT
, data
| VIP_FB_INT__INT_7
);
573 * Wait (by polling) for the DSP to process the command.
576 data
= Register(VIP_INT_CNTL
);
577 while((!(data
& VIP_INT_CNTL__FB_INT0
)) && (i
++ < 10))
580 data
= Register(VIP_INT_CNTL
);
584 * The return code is in FB_SCRATCH0
586 fb_scratch0
= Register(VIP_FB_SCRATCH0
);
589 * If we are here it means we got an answer. Clear the FB_INT0 bit.
591 data
= Register(VIP_INT_CNTL
);
592 SetRegister(VIP_INT_CNTL
, data
| VIP_INT_CNTL__FB_INT0_CLR
);
597 void CTheater200::InitTheatre()
602 /* this will give 108Mhz at 27Mhz reference */
609 fMode
= MODE_INITIALIZATION_IN_PROGRESS
;
611 data
= M
| (N
<< 11) | (P
<<24);
612 SetRegister(VIP_DSP_PLL_CNTL
, data
);
614 Register(VIP_PLL_CNTL0
, data
);
616 SetRegister(VIP_PLL_CNTL0
, data
);
618 /* RT_regw(VIP_I2C_SLVCNTL, 0x249); */
619 Register(VIP_PLL_CNTL1
, data
);
621 SetRegister(VIP_PLL_CNTL1
, data
);
623 Register(VIP_PLL_CNTL0
, data
);
625 SetRegister(VIP_PLL_CNTL0
, data
);
628 Register(VIP_CLOCK_SEL_CNTL
, data
);
630 SetRegister(VIP_CLOCK_SEL_CNTL
, data
);
632 Register(VIP_MASTER_CNTL
, data
);
634 SetRegister(VIP_MASTER_CNTL
, data
);
636 SetRegister(VIP_MASTER_CNTL
, data
);
639 if (microcode_path
== NULL
)
641 microcode_path
= const_cast<char *>(DEFAULT_MICROC_PATH
);
642 PRINT(("Microcode: Use default microcode path: %s\n", DEFAULT_MICROC_PATH
));
646 PRINT(("Microcode: Use microcode path: %s\n", microcode_path
));
649 if (microcode_type
== NULL
)
651 microcode_type
= const_cast<char *>(DEFAULT_MICROC_TYPE
);
652 PRINT(("Microcode: Use default microcode type: %s\n", DEFAULT_MICROC_TYPE
));
656 PRINT(("Microcode: Use microcode type: %s\n", microcode_type
));
659 if (DSPDownloadMicrocode() < 0)
665 //DspSetLowPowerState(1);
666 //DspSetVideoStreamFormat(1);
668 fMode
= MODE_INITIALIZED_FOR_TV_IN
;
671 int CTheater200::DSPDownloadMicrocode()
673 struct rt200_microc_data microc_data
;
674 microc_data
.microc_seg_list
= NULL
;
676 if (DSPLoadMicrocode(microcode_path
, microcode_type
, µc_data
) < 0)
678 PRINT(("Microcode: cannot load microcode\n"));
683 PRINT(("Microcode: device_id: %x\n", microc_data
.microc_head
.device_id
));
684 PRINT(("Microcode: vendor_id: %x\n", microc_data
.microc_head
.vendor_id
));
685 PRINT(("Microcode: rev_id: %x\n", microc_data
.microc_head
.revision_id
));
686 PRINT(("Microcode: num_seg: %x\n", microc_data
.microc_head
.num_seg
));
691 PRINT(("Microcode: dsp_init failed\n"));
696 PRINT(("Microcode: dsp_init OK\n"));
699 if (DspLoad(µc_data
) < 0)
701 PRINT(("Microcode: dsp_download failed\n"));
706 PRINT(("Microcode: dsp_download OK\n"));
709 DSPCleanMicrocode(µc_data
);
714 DSPCleanMicrocode(µc_data
);
719 void CTheater200::ShutdownTheatre()
721 fMode
= MODE_UNINITIALIZED
;
724 void CTheater200::ResetTheatreRegsForNoTVout()
726 SetRegister(VIP_CLKOUT_CNTL
, 0x0);
727 SetRegister(VIP_HCOUNT
, 0x0);
728 SetRegister(VIP_VCOUNT
, 0x0);
729 SetRegister(VIP_DFCOUNT
, 0x0);
731 SetRegister(VIP_CLOCK_SEL_CNTL
, 0x2b7); /* versus 0x237 <-> 0x2b7 */
732 SetRegister(VIP_VIN_PLL_CNTL
, 0x60a6039);
734 SetRegister(VIP_FRAME_LOCK_CNTL
, 0x0);
737 void CTheater200::ResetTheatreRegsForTVout()
739 SetRegister(VIP_CLKOUT_CNTL
, 0x29);
741 SetRegister(VIP_HCOUNT
, 0x1d1);
742 SetRegister(VIP_VCOUNT
, 0x1e3);
744 SetRegister(VIP_HCOUNT
, 0x322);
745 SetRegister(VIP_VCOUNT
, 0x151);
747 SetRegister(VIP_DFCOUNT
, 0x01);
748 SetRegister(VIP_CLOCK_SEL_CNTL
, 0x2b7); /* versus 0x237 <-> 0x2b7 */
749 SetRegister(VIP_VIN_PLL_CNTL
, 0x60a6039);
750 SetRegister(VIP_FRAME_LOCK_CNTL
, 0x0f);
753 int32
CTheater200::DspSetVideostreamformat(int32 format
)
755 int32 fb_scratch0
= 0;
758 fb_scratch0
= ((format
<< 8) & 0xff00) | (65 & 0xff);
759 result
= DspSendCommand(0, fb_scratch0
);
761 PRINT(("dsp_set_videostreamformat: %x\n", result
));
766 int32
CTheater200::DspGetSignalLockStatus()
768 int32 fb_scratch1
= 0;
769 int32 fb_scratch0
= 0;
772 fb_scratch0
= 0 | (77 & 0xff);
774 result
= DspSendCommand(fb_scratch1
, fb_scratch0
);
776 PRINT(("dsp_get_signallockstatus: %x, h_pll: %x, v_pll: %x\n", \
777 result
, (result
>> 8) & 0xff, (result
>> 16) & 0xff));
782 // disable/enable capturing
783 void CTheater200::SetEnable(bool enable
, bool vbi
)
786 PRINT(("CTheater200::SetEnable(%d, %d)\n", enable
, vbi
));
791 SetADC(fStandard
, fSource
);
793 SetScaler(fStandard
, fHActive
, fVActive
, fDeinterlace
);
796 SetRegister(VIP_ADC_CNTL
, ADC_PDWN
, ADC_PDWN_UP
);
800 // restore luminance and chroma settings
801 SetLuminanceLevels(fStandard
, fBrightness
, fContrast
);
802 SetChromaLevels(fStandard
, fSaturation
, fHue
);
806 void CTheater200::SetStandard(theater_standard standard
, theater_source source
)
808 PRINT(("CTheater200::SetStandard(%s, %s)\n",
809 "NTSC\0\0\0\0\0\0NTSC-J\0\0\0\0NTSC-443\0\0PAL-M\0\0\0\0\0"
810 "PAL-N\0\0\0\0\0PAL-NC\0\0\0\0PAL-BDGHI\0PAL-60\0\0\0\0"
811 "SECAM\0\0\0\0\0"+10*standard
,
812 "TUNER\0COMP\0\0SVIDEO"+6*source
));
814 fStandard
= standard
;
818 void CTheater200::SetSize(int hactive
, int vactive
)
820 PRINT(("CTheater200::SetSize(%d, %d)\n", hactive
, vactive
));
826 void CTheater200::SetDeinterlace(bool deinterlace
)
828 PRINT(("CTheater200::SetDeinterlace(%d)\n", deinterlace
));
830 fDeinterlace
= deinterlace
;
833 /* one assumes as sharpness is not used it's not supported */
834 void CTheater200::SetSharpness(int sharpness
)
836 int32 fb_scratch0
= 0;
837 int32 fb_scratch1
= 1;
840 PRINT(("CTheater200::SetSharpness(%d)\n", sharpness
));
842 fb_scratch0
= 0 | (73 & 0xff);
843 result
= DspSendCommand(fb_scratch1
, fb_scratch0
);
846 void CTheater200::SetBrightness(int brightness
)
848 PRINT(("CTheater200::SetBrightness(%d)\n", brightness
));
850 fBrightness
= brightness
;
851 SetLuminanceLevels(fStandard
, fBrightness
, fContrast
);
854 void CTheater200::SetContrast(int contrast
)
856 PRINT(("CTheater200::SetContrast(%d)\n", contrast
));
858 fContrast
= contrast
;
859 SetLuminanceLevels(fStandard
, fBrightness
, fContrast
);
862 void CTheater200::SetSaturation(int saturation
)
864 PRINT(("CTheater200::SetSaturation(%d)\n", saturation
));
866 fSaturation
= saturation
;
867 SetChromaLevels(fStandard
, fSaturation
, fHue
);
870 void CTheater200::SetHue(int hue
)
872 PRINT(("CTheater200::SetHue(%d)\n", hue
));
875 SetChromaLevels(fStandard
, fSaturation
, fHue
);
878 // setup analog-digital converter
879 void CTheater200::SetADC(theater_standard standard
, theater_source source
)
881 uint32 fb_scratch0
= 0;
885 PRINT(("CTheater200::SetADC(%c, %c)\n", "NJ4MNCB6S"[standard
], "TCS"[source
]));
887 // set HW_DEBUG before setting the standard
888 SetRegister(VIP_HW_DEBUG
, 0x0000f000);
890 // select the video standard
893 case C_THEATER_NTSC_JAPAN
:
894 case C_THEATER_NTSC_443
:
895 case C_THEATER_PAL_M
:
896 // SetRegister(VIP_STANDARD_SELECT, STANDARD_SEL, STANDARD_NTSC);
898 case C_THEATER_PAL_BDGHI
:
899 case C_THEATER_PAL_N
:
900 case C_THEATER_PAL_60
:
901 case C_THEATER_PAL_NC
:
902 // SetRegister(VIP_STANDARD_SELECT, STANDARD_SEL, STANDARD_PAL);
904 case C_THEATER_SECAM
:
905 // SetRegister(VIP_STANDARD_SELECT, STANDARD_SEL, STANDARD_SECAM);
906 fb_scratch0
= ((standard
<< 8) & 0xff00) | (52 & 0xff);
907 result
= DspSendCommand(0, fb_scratch0
);
910 PRINT(("CTheater200::SetADC() - Bad standard\n"));
914 Register(VIP_GPIO_CNTL
, data
);
915 PRINT(("VIP_GPIO_CNTL: %x\n", data
));
917 Register(VIP_GPIO_INOUT
, data
);
918 PRINT(("VIP_GPIO_INOUT: %x\n", data
));
920 // select input connector and Y/C mode
922 case C_THEATER_TUNER
:
923 // set video input connector
924 fb_scratch0
= ((fTunerPort
<< 8) & 0xff00) | (55 & 0xff);
925 DspSendCommand(0, fb_scratch0
);
927 /* this is to set the analog mux used for sond */
928 Register(VIP_GPIO_CNTL
, data
);
930 SetRegister(VIP_GPIO_CNTL
, data
);
932 Register(VIP_GPIO_INOUT
, data
);
934 SetRegister(VIP_GPIO_INOUT
, data
);
936 case C_THEATER_COMPOSITE
:
937 // set video input connector
938 fb_scratch0
= ((fCompositePort
<< 8) & 0xff00) | (55 & 0xff);
939 DspSendCommand(0, fb_scratch0
);
941 /* this is to set the analog mux used for sond */
942 Register(VIP_GPIO_CNTL
, data
);
944 SetRegister(VIP_GPIO_CNTL
, data
);
946 Register(VIP_GPIO_INOUT
, data
);
948 SetRegister(VIP_GPIO_INOUT
, data
);
950 case C_THEATER_SVIDEO
:
951 // set video input connector
952 fb_scratch0
= ((fSVideoPort
<< 8) & 0xff00) | (55 & 0xff);
953 DspSendCommand(0, fb_scratch0
);
955 /* this is to set the analog mux used for sond */
956 Register(VIP_GPIO_CNTL
, data
);
958 SetRegister(VIP_GPIO_CNTL
, data
);
960 Register(VIP_GPIO_INOUT
, data
);
962 SetRegister(VIP_GPIO_INOUT
, data
);
965 PRINT(("CTheater200::SetADC() - Bad source\n"));
970 Register(VIP_GPIO_CNTL
, data
);
971 PRINT(("VIP_GPIO_CNTL: %x\n", data
));
973 Register(VIP_GPIO_INOUT
, data
);
974 PRINT(("VIP_GPIO_INOUT: %x\n", data
));
977 DspConfigureI2SPort(0, 0, 0);
978 DspConfigureSpdifPort(0);
980 /*dsp_audio_detection(t, 0);*/
982 DspSetAudioVolume(128, 128, 0);
986 // wait until horizontal scaler is locked
987 void CTheater200::WaitHSYNC()
989 for (int timeout
= 0; timeout
< 1000; timeout
++) {
990 if (Register(VIP_HS_PULSE_WIDTH
, HS_GENLOCKED
) != 0)
994 PRINT(("CTheater200::WaitHSYNC() - wait for HSync locking time out!\n"));
999 // wait until a visible line is viewed
1000 void CTheater200::WaitVSYNC()
1002 for (int timeout
= 0; timeout
< 1000; timeout
++) {
1003 int lineCount
= CurrentLine();
1004 if (lineCount
> 1 && lineCount
< 20)
1008 PRINT(("CTheater200::WaitVSYNC() - wait for VBI timed out!\n"));
1011 // setup brightness and contrast
1012 void CTheater200::SetLuminanceLevels(theater_standard standard
, int brightness
, int contrast
)
1015 int32 fb_scratch1
= 0;
1016 int32 fb_scratch0
= 0;
1019 /* set luminance processor constrast */
1020 fb_scratch0
= ((contrast
<< 8) & 0xff00) | (71 & 0xff);
1021 result
= DspSendCommand(fb_scratch1
, fb_scratch0
);
1022 PRINT(("dsp_set_contrast: %x\n", result
));
1024 /* set luminance processor brightness */
1025 fb_scratch0
= ((brightness
<< 8) & 0xff00) | (67 & 0xff);
1026 DspSendCommand(fb_scratch1
, fb_scratch0
);
1027 PRINT(("dsp_set_brightness: %x\n", result
));
1031 // set colour saturation and hue.
1032 // hue makes sense for NTSC only and seems to act as saturation for PAL
1033 void CTheater200::SetChromaLevels(theater_standard standard
, int saturation
, int hue
)
1036 int32 fb_scratch1
= 0;
1037 int32 fb_scratch0
= 0;
1040 fb_scratch0
= ((hue
<< 8) & 0xff00) | (75 & 0xff);
1041 DspSendCommand(fb_scratch1
, fb_scratch0
);
1044 fb_scratch0
= ((saturation
<< 8) & 0xff00) | (69 & 0xff);
1045 DspSendCommand(fb_scratch1
, fb_scratch0
);
1047 PRINT(("dsp_set_saturation: %x\n", saturation
));
1048 PRINT(("dsp_set_tint: %x\n", hue
));
1052 // these values are used by scaler as well
1053 static const uint16 h_active_start
[] = {
1054 0x06b, 0x06B, 0x07E, 0x067, 0x09A, 0x07D, 0x09A, 0x084, 0x095 };
1055 static const uint16 h_active_end
[] = {
1056 0x363, 0x363, 0x42A, 0x363, 0x439, 0x439, 0x439, 0x363, 0x439 };
1057 static const uint16 v_active_start
[] = {
1058 0x025, 0x025, 0x025, 0x025, 0x02E, 0x02E, 0x02E, 0x025, 0x02E };
1059 // PAL height is too small (572 instead of 576 lines), but changing 0x269 to 0x26d
1060 // leads to trouble, and the last 2 lines seem to be used for VBI data
1061 // (read: garbage) anyway
1062 static const uint16 v_active_end
[] = {
1063 0x204, 0x204, 0x204, 0x204, 0x269, 0x269, 0x269, 0x204, 0x269 };
1064 static const uint16 h_vbi_wind_start
[] = {
1065 0x064, 0x064, 0x064, 0x064, 0x084, 0x084, 0x084, 0x064, 0x084 };
1066 static const uint16 h_vbi_wind_end
[] = {
1067 0x366, 0x366, 0x366, 0x366, 0x41F, 0x41F, 0x41F, 0x366, 0x41F };
1068 static const uint16 v_vbi_wind_start
[] = {
1069 0x00b, 0x00b, 0x00b, 0x00b, 0x008, 0x008, 0x008, 0x00b, 0x008 };
1070 static const uint16 v_vbi_wind_end
[] = {
1071 0x024, 0x024, 0x024, 0x024, 0x02d, 0x02d, 0x02d, 0x024, 0x02d };
1074 void CTheater200::getActiveRange( theater_standard standard
, CRadeonRect
&rect
)
1078 h_active_start
[standard
], v_active_start
[standard
],
1079 h_active_end
[standard
], v_active_end
[standard
] );
1083 void CTheater200::getVBIRange( theater_standard standard
, CRadeonRect
&rect
)
1087 h_vbi_wind_start
[standard
], v_vbi_wind_start
[standard
],
1088 h_vbi_wind_end
[standard
], v_vbi_wind_end
[standard
] );
1092 // setup capture scaler.
1093 void CTheater200::SetScaler(theater_standard standard
, int hactive
, int vactive
, bool deinterlace
)
1096 int32 fb_scratch1
= 0;
1097 int32 fb_scratch0
= 0;
1098 int oddOffset
, evenOffset
;
1099 uint16 h_active_width
, v_active_height
;
1101 // ASSERT(vactive <= 511);
1103 // TK: Gatos uses different values here
1104 h_active_width
= h_active_end
[standard
] - h_active_start
[standard
] + 1;
1105 v_active_height
= v_active_end
[standard
] - v_active_start
[standard
] + 1;
1107 // for PAL, we have 572 lines only, but need 576 lines;
1108 // my attempts to find those missing lines all failed, so if the application requests
1109 // 576 lines, we had to upscale the video which is not supported by hardware;
1110 // solution: restrict to 572 lines - the scaler will fill out the missing lines with black
1111 if( vactive
> v_active_height
)
1112 vactive
= v_active_height
;
1116 evenOffset
= oddOffset
= 512 - (int) ((512 * vactive
) / v_active_height
);
1120 evenOffset
= (int) ((512 * vactive
) / v_active_height
);
1121 oddOffset
= 2048 - evenOffset
;
1124 // Set Horizontal Size
1125 fb_scratch0
= ((h_active_width
<< 8) & 0x00ffff00) | (195 & 0xff);
1126 fb_scratch1
= ((h_active_end
[standard
] << 16) & 0xffff0000) | (h_active_start
[standard
] & 0xffff);
1127 DspSendCommand(fb_scratch1
, fb_scratch0
);
1129 // Set Vertical Size
1130 fb_scratch0
= ((v_active_height
<< 8) & 0x00ffff00) | (196 & 0xff);
1131 fb_scratch1
= ((v_active_end
[standard
] << 16) & 0xffff0000) | (v_active_start
[standard
] + 1 & 0xffff);
1132 DspSendCommand(fb_scratch1
, fb_scratch0
);
1135 int32
CTheater200::DspAudioMute(int8 left
, int8 right
)
1137 int32 fb_scratch1
= 0;
1138 int32 fb_scratch0
= 0;
1141 fb_scratch0
= ((right
<< 16) & 0xff0000) | ((left
<< 8) & 0xff00) | (21 & 0xff);
1142 result
= DspSendCommand(fb_scratch1
, fb_scratch0
);
1144 PRINT(("dsp_audio_mute: %x\n", result
));
1149 int32
CTheater200::DspSetAudioVolume(int8 left
, int8 right
, int8 auto_mute
)
1151 int32 fb_scratch1
= 0;
1152 int32 fb_scratch0
= 0;
1155 fb_scratch0
= ((auto_mute
<< 24) & 0xff000000)
1156 | ((right
<< 16) & 0xff0000)
1157 | ((left
<< 8) & 0xff00) | (22 & 0xff);
1158 result
= DspSendCommand(fb_scratch1
, fb_scratch0
);
1160 PRINT(("dsp_set_audio_volume: %x\n", result
));
1165 int32
CTheater200::DspConfigureI2SPort(int8 tx_mode
, int8 rx_mode
, int8 clk_mode
)
1167 int32 fb_scratch1
= 0;
1168 int32 fb_scratch0
= 0;
1171 fb_scratch0
= ((clk_mode
<< 24) & 0xff000000) | ((rx_mode
<< 16) & 0xff0000)
1172 | ((tx_mode
<< 8) & 0xff00) | (40 & 0xff);
1174 result
= DspSendCommand(fb_scratch1
, fb_scratch0
);
1176 PRINT(("dsp_configure_i2s_port: %x\n", result
));
1181 int32
CTheater200::DspConfigureSpdifPort(int8 state
)
1183 int32 fb_scratch1
= 0;
1184 int32 fb_scratch0
= 0;
1187 fb_scratch0
= ((state
<< 8) & 0xff00) | (41 & 0xff);
1189 result
= DspSendCommand(fb_scratch1
, fb_scratch0
);
1191 PRINT(("dsp_configure_spdif_port: %x\n", result
));
1196 int CTheater200::ReadFifo( uint32 address
, uint8
*buffer
)
1198 return fPort
.ReadFifo(fDevice
, address
, 1, buffer
);
1201 int CTheater200::WriteFifo( uint32 address
, uint32 count
, uint8
*buffer
)
1203 return fPort
.WriteFifo(fDevice
, address
, count
, buffer
);
1206 int CTheater200::CurrentLine()
1208 // return Register(VIP_VS_LINE_COUNT) & VS_LINE_COUNT;
1209 int32 fb_scratch1
= 0;
1210 int32 fb_scratch0
= 0;
1213 fb_scratch0
= 0 | (78 & 0xff);
1214 result
= DspSendCommand(fb_scratch1
, fb_scratch0
);
1216 PRINT(("dsp_get_signallinenumber: %x, linenum: %x\n", \
1217 result
, (result
>> 8) & 0xffff));
1223 void CTheater200::PrintToStream()
1225 PRINT(("<<< Rage Theater Registers >>>\n"));
1226 /*for (int index = 0x0400; index <= 0x06ff; index += 4) {
1227 int value = Register(index);
1228 PRINT(("REG_0x%04x = 0x%08x\n", index, value));