BTRFS: Implement BTree::Path and change _Find.
[haiku.git] / src / add-ons / accelerants / radeon / flat_panel.c
blob66ea70082ce463f3819d631b9e463902ba4aea3e
1 /*
2 Copyright (c) 2002-2004, Thomas Kurschel
5 Part of Radeon accelerant
7 Flat panel support
8 */
10 #include "radeon_accelerant.h"
11 #include "mmio.h"
12 #include "fp_regs.h"
13 #include "memcntrl_regs.h"
14 #include "utils.h"
15 #include "set_mode.h"
16 #include "pll_regs.h"
17 #include "pll_access.h"
20 void Radeon_ReadRMXRegisters(
21 accelerator_info *ai, fp_regs *values )
23 vuint8 *regs = ai->regs;
25 values->fp_horz_stretch = INREG( regs, RADEON_FP_HORZ_STRETCH );
26 values->fp_vert_stretch = INREG( regs, RADEON_FP_VERT_STRETCH );
29 void Radeon_CalcRMXRegisters(
30 fp_info *flatpanel, display_mode *mode, bool use_rmx, fp_regs *values )
32 uint xres = mode->timing.h_display;
33 uint yres = mode->timing.v_display;
34 uint64 Hratio, Vratio;
36 if( !use_rmx ) {
37 // disable RMX unit if requested
38 values->fp_horz_stretch &=
39 ~(RADEON_HORZ_STRETCH_BLEND |
40 RADEON_HORZ_STRETCH_ENABLE);
42 values->fp_vert_stretch &=
43 ~(RADEON_VERT_STRETCH_ENABLE |
44 RADEON_VERT_STRETCH_BLEND);
46 return;
49 // RMX unit can only upscale, not downscale
50 if( xres > flatpanel->panel_xres )
51 xres = flatpanel->panel_xres;
52 if( yres > flatpanel->panel_yres )
53 yres = flatpanel->panel_yres;
55 Hratio = FIX_SCALE * (uint32)xres / flatpanel->panel_xres;
56 Vratio = FIX_SCALE * (uint32)yres / flatpanel->panel_yres;
58 // save it for overlay unit (overlays must be vertically scaled manually)
59 flatpanel->h_ratio = Hratio;
60 flatpanel->v_ratio = Vratio;
62 values->fp_horz_stretch = flatpanel->panel_xres << RADEON_HORZ_PANEL_SIZE_SHIFT;
64 if( Hratio == FIX_SCALE ) {
65 values->fp_horz_stretch &=
66 ~(RADEON_HORZ_STRETCH_BLEND |
67 RADEON_HORZ_STRETCH_ENABLE);
68 } else {
69 uint32 stretch;
71 stretch = (uint32)((Hratio * RADEON_HORZ_STRETCH_RATIO_MAX +
72 FIX_SCALE / 2) >> FIX_SHIFT) & RADEON_HORZ_STRETCH_RATIO_MASK;
74 values->fp_horz_stretch = stretch
75 | (values->fp_horz_stretch & (RADEON_HORZ_PANEL_SIZE |
76 RADEON_HORZ_FP_LOOP_STRETCH |
77 RADEON_HORZ_AUTO_RATIO_INC));
78 values->fp_horz_stretch |=
79 RADEON_HORZ_STRETCH_BLEND |
80 RADEON_HORZ_STRETCH_ENABLE;
82 values->fp_horz_stretch &= ~RADEON_HORZ_AUTO_RATIO;
84 values->fp_vert_stretch = flatpanel->panel_yres << RADEON_VERT_PANEL_SIZE_SHIFT;
86 if( Vratio == FIX_SCALE ) {
87 values->fp_vert_stretch &=
88 ~(RADEON_VERT_STRETCH_ENABLE |
89 RADEON_VERT_STRETCH_BLEND);
90 } else {
91 uint32 stretch;
93 stretch = (uint32)((Vratio * RADEON_VERT_STRETCH_RATIO_MAX +
94 FIX_SCALE / 2) >> FIX_SHIFT) & RADEON_VERT_STRETCH_RATIO_MASK;
96 values->fp_vert_stretch = stretch
97 | (values->fp_vert_stretch & (RADEON_VERT_PANEL_SIZE |
98 RADEON_VERT_STRETCH_RESERVED));
99 values->fp_vert_stretch |=
100 RADEON_VERT_STRETCH_ENABLE |
101 RADEON_VERT_STRETCH_BLEND;
103 values->fp_vert_stretch &= ~RADEON_VERT_AUTO_RATIO_EN;
106 // write RMX registers
107 void Radeon_ProgramRMXRegisters(
108 accelerator_info *ai, fp_regs *values )
110 vuint8 *regs = ai->regs;
111 SHOW_FLOW0( 2, "" );
112 OUTREG( regs, RADEON_FP_HORZ_STRETCH, values->fp_horz_stretch );
113 OUTREG( regs, RADEON_FP_VERT_STRETCH, values->fp_vert_stretch );
117 void Radeon_ReadFPRegisters(
118 accelerator_info *ai, fp_regs *values )
120 vuint8 *regs = ai->regs;
122 values->fp_gen_cntl = INREG( regs, RADEON_FP_GEN_CNTL );
123 values->fp2_gen_cntl = INREG( regs, RADEON_FP2_GEN_CNTL );
124 values->lvds_gen_cntl = INREG( regs, RADEON_LVDS_GEN_CNTL );
125 values->tmds_pll_cntl = INREG( regs, RADEON_TMDS_PLL_CNTL );
126 values->tmds_trans_cntl = INREG( regs, RADEON_TMDS_TRANSMITTER_CNTL );
127 values->fp_h_sync_strt_wid = INREG( regs, RADEON_FP_H_SYNC_STRT_WID );
128 values->fp_v_sync_strt_wid = INREG( regs, RADEON_FP_V_SYNC_STRT_WID );
129 values->fp2_h_sync_strt_wid = INREG( regs, RADEON_FP_H2_SYNC_STRT_WID );
130 values->fp2_v_sync_strt_wid = INREG( regs, RADEON_FP_V2_SYNC_STRT_WID );
131 values->bios_4_scratch = INREG( regs, RADEON_BIOS_4_SCRATCH );
132 values->bios_5_scratch = INREG( regs, RADEON_BIOS_5_SCRATCH );
133 values->bios_6_scratch = INREG( regs, RADEON_BIOS_6_SCRATCH );
135 if (ai->si->asic == rt_rv280) {
136 // bit 22 of TMDS_PLL_CNTL is read-back inverted
137 values->tmds_pll_cntl ^= (1 << 22);
140 SHOW_FLOW( 2, "before: fp_gen_cntl=%08lx, horz=%08lx, vert=%08lx, lvds_gen_cntl=%08lx",
141 values->fp_gen_cntl, values->fp_horz_stretch, values->fp_vert_stretch,
142 values->lvds_gen_cntl );
145 // calculcate flat panel crtc registers;
146 // must be called after normal CRTC registers are determined
147 void Radeon_CalcFPRegisters(
148 accelerator_info *ai, crtc_info *crtc,
149 fp_info *fp_port, crtc_regs *crtc_values, fp_regs *values )
151 int i;
152 uint32 tmp = values->tmds_pll_cntl & 0xfffff;
154 // setup synchronization position
155 // (most values are ignored according to fp_gen_cntl, but at least polarity
156 // and pixel precise horizontal sync position are always used)
157 if( fp_port->is_fp2 ) {
158 SHOW_FLOW0( 2, "is_fp2" );
159 values->fp2_h_sync_strt_wid = crtc_values->crtc_h_sync_strt_wid;
160 values->fp2_v_sync_strt_wid = crtc_values->crtc_v_sync_strt_wid;
161 } else {
162 SHOW_FLOW0( 2, "fp1" );
163 values->fp_h_sync_strt_wid = crtc_values->crtc_h_sync_strt_wid;
164 values->fp_v_sync_strt_wid = crtc_values->crtc_v_sync_strt_wid;
167 if( fp_port->is_fp2 ) {
168 // should retain POST values (esp bit 28)
169 values->fp2_gen_cntl &= (0xFFFF0000);
171 } else {
172 // setup magic CRTC shadowing
173 values->fp_gen_cntl &=
174 ~(RADEON_FP_RMX_HVSYNC_CONTROL_EN |
175 RADEON_FP_DFP_SYNC_SEL |
176 RADEON_FP_CRT_SYNC_SEL |
177 RADEON_FP_CRTC_LOCK_8DOT |
178 RADEON_FP_USE_SHADOW_EN |
179 RADEON_FP_CRTC_USE_SHADOW_VEND |
180 RADEON_FP_CRT_SYNC_ALT);
181 values->fp_gen_cntl |=
182 RADEON_FP_CRTC_DONT_SHADOW_VPAR |
183 RADEON_FP_CRTC_DONT_SHADOW_HEND;
186 for (i = 0; i < 4; i++) {
187 if (ai->si->tmds_pll[i].freq == 0)
188 break;
189 if ((uint32)(fp_port->dot_clock) < ai->si->tmds_pll[i].freq) {
190 tmp = ai->si->tmds_pll[i].value ;
191 break;
195 if (IS_R300_VARIANT || (ai->si->asic == rt_rv280)) {
196 if (tmp & 0xfff00000) {
197 values->tmds_pll_cntl = tmp;
198 } else {
199 values->tmds_pll_cntl = ai->si->tmds_pll_cntl & 0xfff00000;
200 values->tmds_pll_cntl |= tmp;
202 } else {
203 values->tmds_pll_cntl = tmp;
206 values->tmds_trans_cntl = ai->si->tmds_transmitter_cntl
207 & ~(RADEON_TMDS_TRANSMITTER_PLLRST);
209 if (IS_R300_VARIANT || (ai->si->asic == rt_r200) || (ai->si->num_crtc == 1))
210 values->tmds_trans_cntl &= ~(RADEON_TMDS_TRANSMITTER_PLLEN);
211 else // weird, RV chips got this bit reversed?
212 values->tmds_trans_cntl |= (RADEON_TMDS_TRANSMITTER_PLLEN);
215 // enable proper transmitter
216 if( (crtc->chosen_displays & dd_lvds) != 0 ) {
217 // using LVDS means there cannot be a DVI monitor
218 SHOW_FLOW0( 2, "lvds" );
219 values->lvds_gen_cntl |= (RADEON_LVDS_ON | RADEON_LVDS_BLON);
220 values->fp_gen_cntl &= ~(RADEON_FP_FPON | RADEON_FP_TMDS_EN);
222 } else if( !fp_port->is_fp2 ) {
223 // DVI on internal transmitter
224 SHOW_FLOW0( 2, "DVI INT" );
225 values->fp_gen_cntl |= RADEON_FP_FPON | RADEON_FP_TMDS_EN;
226 // enabling 8 bit data may be dangerous; BIOS should have taken care of that
227 values->fp_gen_cntl |= RADEON_FP_PANEL_FORMAT;
229 } else {
230 // DVI on external transmitter
231 SHOW_FLOW0( 2, "DVI EXT" );
232 values->fp2_gen_cntl |= RADEON_FP2_FPON | RADEON_FP_PANEL_FORMAT;
233 values->fp2_gen_cntl &= ~RADEON_FP2_BLANK_EN;
235 //hack in missing bits test...
236 //values->fp2_gen_cntl |= (1 << 22) | (1 << 28);
238 if( ai->si->asic >= rt_r200 )
239 values->fp2_gen_cntl |= RADEON_FP2_DV0_EN;
242 SHOW_FLOW( 2, "after: fp_gen_cntl=%08lx, fp2_gen_cntl=%08lx, horz=%08lx, vert=%08lx, lvds_gen_cntl=%08lx",
243 values->fp_gen_cntl, values->fp2_gen_cntl, values->fp_horz_stretch, values->fp_vert_stretch,
244 values->lvds_gen_cntl );
248 // write flat panel registers
249 void Radeon_ProgramFPRegisters(
250 accelerator_info *ai, crtc_info *crtc,
251 fp_info *fp_port, fp_regs *values )
253 shared_info *si = ai->si;
254 vuint8 *regs = ai->regs;
256 SHOW_FLOW0( 2, "" );
258 OUTREGP( regs, RADEON_FP_GEN_CNTL, values->fp_gen_cntl, RADEON_FP_SEL_CRTC2 );
260 if( fp_port->is_fp2 ) {
261 SHOW_FLOW0( 2, "is_fp2" );
262 OUTREGP( regs, RADEON_FP2_GEN_CNTL, values->fp2_gen_cntl,
263 ~(RADEON_FP2_SOURCE_SEL_MASK | RADEON_FP2_SRC_SEL_MASK));
264 OUTREGP( regs, RADEON_FP2_GEN_CNTL, values->fp2_gen_cntl,
265 RADEON_FP2_SOURCE_SEL_CRTC2 | RADEON_FP2_SRC_SEL_CRTC2 );
266 OUTREG( regs, RADEON_FP_H2_SYNC_STRT_WID, values->fp2_h_sync_strt_wid );
267 OUTREG( regs, RADEON_FP_V2_SYNC_STRT_WID, values->fp2_v_sync_strt_wid );
268 } else {
269 SHOW_FLOW0( 2, "is_fp1" );
270 OUTREG( regs, RADEON_FP_H_SYNC_STRT_WID, values->fp_h_sync_strt_wid );
271 OUTREG( regs, RADEON_FP_V_SYNC_STRT_WID, values->fp_v_sync_strt_wid );
274 // workaround for old AIW Radeon having display buffer underflow
275 // in conjunction with DVI
276 if( si->asic == rt_r100 ) {
277 OUTREG( regs, RADEON_GRPH_BUFFER_CNTL,
278 INREG( regs, RADEON_GRPH_BUFFER_CNTL) & ~0x7f0000);
281 if ( ai->si->is_mobility ) {
282 OUTREG( regs, RADEON_BIOS_4_SCRATCH, values->bios_4_scratch);
283 OUTREG( regs, RADEON_BIOS_5_SCRATCH, values->bios_5_scratch);
284 OUTREG( regs, RADEON_BIOS_6_SCRATCH, values->bios_6_scratch);
287 if( (crtc->chosen_displays & dd_lvds) != 0 ) {
289 //OUTREGP( regs, RADEON_LVDS_GEN_CNTL, values->lvds_gen_cntl,
290 // RADEON_LVDS_ON | RADEON_LVDS_BLON );
292 uint32 old_pixclks_cntl;
293 uint32 tmp;
295 old_pixclks_cntl = Radeon_INPLL( ai->regs, ai->si->asic, RADEON_PIXCLKS_CNTL);
297 // ASIC bug: when LVDS_ON is reset, LVDS_ALWAYS_ON must be zero
298 if( ai->si->is_mobility || ai->si->is_igp )
300 if (!(values->lvds_gen_cntl & RADEON_LVDS_ON)) {
301 Radeon_OUTPLLP( ai->regs, ai->si->asic, RADEON_PIXCLKS_CNTL, 0, ~RADEON_PIXCLK_LVDS_ALWAYS_ONb );
305 // get current state of LCD
306 tmp = INREG( regs, RADEON_LVDS_GEN_CNTL);
308 // if LCD is on, and previous state was on, just write the state directly.
309 if (( tmp & ( RADEON_LVDS_ON | RADEON_LVDS_BLON )) ==
310 ( values->lvds_gen_cntl & ( RADEON_LVDS_ON | RADEON_LVDS_BLON ))) {
311 OUTREG( regs, RADEON_LVDS_GEN_CNTL, values->lvds_gen_cntl );
312 } else {
313 if ( values->lvds_gen_cntl & ( RADEON_LVDS_ON | RADEON_LVDS_BLON )) {
314 snooze( ai->si->panel_pwr_delay * 1000 );
315 OUTREG( regs, RADEON_LVDS_GEN_CNTL, values->lvds_gen_cntl );
316 } else {
318 //turn on backlight, wait for stable before turning on data ???
319 OUTREG( regs, RADEON_LVDS_GEN_CNTL, values->lvds_gen_cntl | RADEON_LVDS_BLON );
320 snooze( ai->si->panel_pwr_delay * 1000 );
321 OUTREG( regs, RADEON_LVDS_GEN_CNTL, values->lvds_gen_cntl );
325 if( ai->si->is_mobility || ai->si->is_igp ) {
326 if (!(values->lvds_gen_cntl & RADEON_LVDS_ON)) {
327 Radeon_OUTPLL( ai->regs, ai->si->asic, RADEON_PIXCLKS_CNTL, old_pixclks_cntl );