2 Copyright (c) 2002/03, Thomas Kurschel
5 Part of Radeon accelerant
7 Programming of internal TV-out unit
10 #include "radeon_interface.h"
11 #include "radeon_accelerant.h"
13 #include "tv_out_regs.h"
14 #include "pll_access.h"
22 // mapping of offset in impactv_regs to register address
23 typedef struct register_mapping
{
24 uint16 address
; // register address
25 uint16 offset
; // offset in impactv_regs
29 // internal TV-encoder:
31 // registers to write before programming PLL
32 static const register_mapping intern_reg_mapping_before_pll
[] = {
33 { RADEON_TV_MASTER_CNTL
, offsetof( impactv_regs
, tv_master_cntl
) },
34 { RADEON_TV_HRESTART
, offsetof( impactv_regs
, tv_hrestart
) },
35 { RADEON_TV_VRESTART
, offsetof( impactv_regs
, tv_vrestart
) },
36 { RADEON_TV_FRESTART
, offsetof( impactv_regs
, tv_frestart
) },
37 { RADEON_TV_FTOTAL
, offsetof( impactv_regs
, tv_ftotal
) },
41 // PLL registers to program
42 static const register_mapping intern_reg_mapping_pll
[] = {
43 { RADEON_TV_PLL_CNTL
, offsetof( impactv_regs
, tv_tv_pll_cntl
) },
44 { RADEON_TV_PLL_CNTL1
, offsetof( impactv_regs
, tv_pll_cntl1
) },
45 { RADEON_TV_PLL_FINE_CNTL
, offsetof( impactv_regs
, tv_pll_fine_cntl
) },
49 // registers to write after programming of PLL
50 static const register_mapping intern_reg_mapping_after_pll
[] = {
51 { RADEON_TV_HTOTAL
, offsetof( impactv_regs
, tv_htotal
) },
52 { RADEON_TV_HDISP
, offsetof( impactv_regs
, tv_hdisp
) },
53 { RADEON_TV_HSTART
, offsetof( impactv_regs
, tv_hstart
) },
54 { RADEON_TV_VTOTAL
, offsetof( impactv_regs
, tv_vtotal
) },
55 { RADEON_TV_VDISP
, offsetof( impactv_regs
, tv_vdisp
) },
57 { RADEON_TV_TIMING_CNTL
, offsetof( impactv_regs
, tv_timing_cntl
) },
59 { RADEON_TV_VSCALER_CNTL1
, offsetof( impactv_regs
, tv_vscaler_cntl1
) },
60 { RADEON_TV_VSCALER_CNTL2
, offsetof( impactv_regs
, tv_vscaler_cntl2
) },
62 { RADEON_TV_Y_SAW_TOOTH_CNTL
, offsetof( impactv_regs
, tv_y_saw_tooth_cntl
) },
63 { RADEON_TV_Y_RISE_CNTL
, offsetof( impactv_regs
, tv_y_rise_cntl
) },
64 { RADEON_TV_Y_FALL_CNTL
, offsetof( impactv_regs
, tv_y_fall_cntl
) },
66 { RADEON_TV_MODULATOR_CNTL1
, offsetof( impactv_regs
, tv_modulator_cntl1
) },
67 { RADEON_TV_MODULATOR_CNTL2
, offsetof( impactv_regs
, tv_modulator_cntl2
) },
68 { RADEON_TV_RGB_CNTL
, offsetof( impactv_regs
, tv_rgb_cntl
) },
69 { RADEON_TV_UV_ADR
, offsetof( impactv_regs
, tv_uv_adr
) },
70 { RADEON_TV_PRE_DAC_MUX_CNTL
, offsetof( impactv_regs
, tv_pre_dac_mux_cntl
) },
71 { RADEON_TV_CRC_CNTL
, offsetof( impactv_regs
, tv_crc_cntl
) },
75 // registers to write when things settled down
76 static const register_mapping intern_reg_mapping_finish
[] = {
77 { RADEON_TV_GAIN_LIMIT_SETTINGS
, offsetof( impactv_regs
, tv_gain_limit_settings
) },
78 { RADEON_TV_LINEAR_GAIN_SETTINGS
, offsetof( impactv_regs
, tv_linear_gain_settings
) },
79 { RADEON_TV_UPSAMP_AND_GAIN_CNTL
, offsetof( impactv_regs
, tv_upsamp_and_gain_cntl
) },
81 { RADEON_TV_DAC_CNTL
, offsetof( impactv_regs
, tv_dac_cntl
) },
82 { RADEON_TV_MASTER_CNTL
, offsetof( impactv_regs
, tv_master_cntl
) },
89 // write list of MM I/O registers
90 static void writeMMIORegList(
91 accelerator_info
*ai
, impactv_regs
*values
, const register_mapping
*mapping
)
93 vuint8
*regs
= ai
->regs
;
95 for( ; mapping
->address
!= 0 && mapping
->offset
!= 0; ++mapping
) {
96 /*SHOW_FLOW( 2, "%x=%x", mapping->address,
97 *(uint32 *)((char *)(values) + mapping->offset) );*/
99 OUTREG( regs
, mapping
->address
, *(uint32
*)((char *)(values
) + mapping
->offset
) );
106 // write list of PLL registers
107 static void writePLLRegList(
108 accelerator_info
*ai
, impactv_regs
*values
, const register_mapping
*mapping
)
110 for( ; mapping
->address
!= 0 && mapping
->offset
!= 0; ++mapping
) {
111 /*SHOW_FLOW( 2, "%x=%x", mapping->address,
112 *(uint32 *)((char *)(values) + mapping->offset) );*/
114 Radeon_OUTPLL( ai
->regs
, ai
->si
->asic
,
115 mapping
->address
, *(uint32
*)((char *)(values
) + mapping
->offset
) );
126 static uint32
Radeon_InternalTVOutReadFIFO(
127 accelerator_info
*ai
, uint16 addr
)
129 vuint8
*regs
= ai
->regs
;
130 bigtime_t start_time
;
133 //SHOW_FLOW( 2, "addr=%d", addr );
135 OUTREG( regs
, RADEON_TV_HOST_RD_WT_CNTL
, addr
| RADEON_TV_HOST_RD_WT_CNTL_RD
);
137 start_time
= system_time();
142 status
= INREG( regs
, RADEON_TV_HOST_RD_WT_CNTL
);
144 if( (status
& RADEON_TV_HOST_RD_WT_CNTL_RD_ACK
) != 0 )
146 } while( system_time() - start_time
< 2000000 );
148 OUTREG( regs
, RADEON_TV_HOST_RD_WT_CNTL
, 0);
149 res
= INREG( regs
, RADEON_TV_HOST_READ_DATA
);
151 //SHOW_FLOW( 2, "res=%x %x", res >> 14, res & 0x3fff );
157 // write to timing FIFO
158 static void Radeon_InternalTVOutWriteFIFO(
159 accelerator_info
*ai
, uint16 addr
, uint32 value
)
161 vuint8
*regs
= ai
->regs
;
162 bigtime_t start_time
;
164 //readFIFO( ai, addr, internal_encoder );
166 //SHOW_FLOW( 2, "addr=%d, value=%x %x", addr, value >> 14, value & 0x3fff );
168 OUTREG( regs
, RADEON_TV_HOST_WRITE_DATA
, value
);
169 OUTREG( regs
, RADEON_TV_HOST_RD_WT_CNTL
, addr
| RADEON_TV_HOST_RD_WT_CNTL_WT
);
171 start_time
= system_time();
176 status
= INREG( regs
, RADEON_TV_HOST_RD_WT_CNTL
);
178 if( (status
& RADEON_TV_HOST_RD_WT_CNTL_WT_ACK
) != 0 )
180 } while( system_time() - start_time
< 2000000 );
182 OUTREG( regs
, RADEON_TV_HOST_RD_WT_CNTL
, 0 );
186 // program TV-Out registers
187 void Radeon_InternalTVOutProgramRegisters(
188 accelerator_info
*ai
, impactv_regs
*values
)
190 uint32 orig_tv_master_cntl
= values
->tv_master_cntl
;
194 // disable TV-out when registers are setup
195 // it gets enabled again when things have settled down
196 values
->tv_master_cntl
|=
197 RADEON_TV_MASTER_CNTL_TV_ASYNC_RST
|
198 RADEON_TV_MASTER_CNTL_CRT_ASYNC_RST
|
199 RADEON_TV_MASTER_CNTL_TV_FIFO_ASYNC_RST
|
201 RADEON_TV_MASTER_CNTL_VIN_ASYNC_RST
|
202 RADEON_TV_MASTER_CNTL_AUD_ASYNC_RST
|
203 RADEON_TV_MASTER_CNTL_DVS_ASYNC_RST
;
205 writeMMIORegList( ai
, values
, intern_reg_mapping_before_pll
);
206 writePLLRegList( ai
, values
, intern_reg_mapping_pll
);
207 writeMMIORegList( ai
, values
, intern_reg_mapping_after_pll
);
209 // un-reset FIFO to access timing table
210 OUTREG( ai
->regs
, RADEON_TV_MASTER_CNTL
,
211 orig_tv_master_cntl
|
212 RADEON_TV_MASTER_CNTL_TV_ASYNC_RST
|
213 RADEON_TV_MASTER_CNTL_CRT_ASYNC_RST
|
215 RADEON_TV_MASTER_CNTL_VIN_ASYNC_RST
|
216 RADEON_TV_MASTER_CNTL_AUD_ASYNC_RST
|
217 RADEON_TV_MASTER_CNTL_DVS_ASYNC_RST
);
219 Radeon_ImpacTVwriteHorTimingTable( ai
, Radeon_InternalTVOutWriteFIFO
, values
, true );
220 Radeon_ImpacTVwriteVertTimingTable( ai
, Radeon_InternalTVOutWriteFIFO
, values
);
224 values
->tv_master_cntl
= orig_tv_master_cntl
;
225 writeMMIORegList( ai
, values
, intern_reg_mapping_finish
);
229 // read list of MM I/O registers
230 static void readMMIORegList(
231 accelerator_info
*ai
, impactv_regs
*values
, const register_mapping
*mapping
)
233 vuint8
*regs
= ai
->regs
;
235 for( ; mapping
->address
!= 0 && mapping
->offset
!= 0; ++mapping
) {
236 *(uint32
*)((char *)(values
) + mapping
->offset
) =
237 INREG( regs
, mapping
->address
);
239 /*SHOW_FLOW( 2, "%x=%x", mapping->address,
240 *(uint32 *)((char *)(values) + mapping->offset) );*/
247 // read list of PLL registers
248 static void readPLLRegList(
249 accelerator_info
*ai
, impactv_regs
*values
, const register_mapping
*mapping
)
251 for( ; mapping
->address
!= 0 && mapping
->offset
!= 0; ++mapping
) {
252 *(uint32
*)((char *)(values
) + mapping
->offset
) =
253 Radeon_INPLL( ai
->regs
, ai
->si
->asic
, mapping
->address
);
255 /*SHOW_FLOW( 2, "%x=%x", mapping->address,
256 *(uint32 *)((char *)(values) + mapping->offset) );*/
263 // read TV-Out registers
264 void Radeon_InternalTVOutReadRegisters(
265 accelerator_info
*ai
, impactv_regs
*values
)
267 readMMIORegList( ai
, values
, intern_reg_mapping_before_pll
);
268 readPLLRegList( ai
, values
, intern_reg_mapping_pll
);
269 readMMIORegList( ai
, values
, intern_reg_mapping_after_pll
);
270 readMMIORegList( ai
, values
, intern_reg_mapping_finish
);