xref: /haiku/src/add-ons/accelerants/radeon/crtc.c (revision 67bce78b48ed6d01b5a8eef89f5694c372b7e0a1)
1 /*
2 	Copyright (c) 2002, Thomas Kurschel
3 
4 
5 	Part of Radeon accelerant
6 
7 	CRTC programming
8 */
9 
10 #include "radeon_accelerant.h"
11 //#include "../include/radeon_regs.h"
12 #include "mmio.h"
13 #include "crtc_regs.h"
14 #include "dac_regs.h"
15 
16 // hammer CRTC registers
17 void Radeon_ProgramCRTCRegisters( accelerator_info *ai, virtual_port *port,
18 	port_regs *values )
19 {
20 	vuint8 *regs = ai->regs;
21 
22 	SHOW_FLOW0( 2, "" );
23 
24 	if( port->is_crtc2 ) {
25 		OUTREGP( regs, RADEON_CRTC2_GEN_CNTL, values->crtc_gen_cntl,
26 			RADEON_CRTC2_VSYNC_DIS |
27 			RADEON_CRTC2_HSYNC_DIS |
28 			RADEON_CRTC2_DISP_DIS );
29 
30 		switch( ai->si->asic ) {
31 		case rt_r200:
32 		case rt_r300:
33 			OUTREG( regs, RADEON_DISP_OUTPUT_CNTL, values->disp_output_cntl );
34 			break;
35 		default:
36 			OUTREG( regs, RADEON_DAC_CNTL2, values->dac_cntl );
37 		}
38 
39 		OUTREG( regs, RADEON_CRTC2_H_TOTAL_DISP, values->crtc_h_total_disp );
40 		OUTREG( regs, RADEON_CRTC2_H_SYNC_STRT_WID, values->crtc_h_sync_strt_wid );
41 		OUTREG( regs, RADEON_CRTC2_V_TOTAL_DISP, values->crtc_v_total_disp );
42 		OUTREG( regs, RADEON_CRTC2_V_SYNC_STRT_WID, values->crtc_v_sync_strt_wid );
43 		OUTREG( regs, RADEON_CRTC2_OFFSET_CNTL, values->crtc_offset_cntl );
44 		OUTREG( regs, RADEON_CRTC2_PITCH, values->crtc_pitch );
45 
46 	} else {
47 		OUTREG( regs, RADEON_CRTC_GEN_CNTL, values->crtc_gen_cntl );
48 
49 		OUTREGP( regs, RADEON_CRTC_EXT_CNTL, values->crtc_ext_cntl,
50 			RADEON_CRTC_VSYNC_DIS |
51 			RADEON_CRTC_HSYNC_DIS |
52 			RADEON_CRTC_DISPLAY_DIS );
53 
54 		OUTREGP( regs, RADEON_DAC_CNTL, values->dac_cntl,
55 			RADEON_DAC_RANGE_CNTL | RADEON_DAC_BLANKING );
56 
57 		OUTREG( regs, RADEON_CRTC_H_TOTAL_DISP, values->crtc_h_total_disp );
58 		OUTREG( regs, RADEON_CRTC_H_SYNC_STRT_WID, values->crtc_h_sync_strt_wid );
59 		OUTREG( regs, RADEON_CRTC_V_TOTAL_DISP, values->crtc_v_total_disp );
60 		OUTREG( regs, RADEON_CRTC_V_SYNC_STRT_WID, values->crtc_v_sync_strt_wid );
61 		OUTREG( regs, RADEON_CRTC_OFFSET_CNTL, values->crtc_offset_cntl );
62 		OUTREG( regs, RADEON_CRTC_PITCH, values->crtc_pitch );
63 	}
64 }
65 
66 
67 // get required hsync delay depending on bit depth and output device
68 uint16 Radeon_GetHSyncFudge( shared_info *si, physical_port *port, int datatype )
69 {
70 	static int hsync_fudge_default[] = { 0x00, 0x12, 0x09, 0x09, 0x06, 0x05 };
71 	static int hsync_fudge_fp[]      = { 0x02, 0x02, 0x00, 0x00, 0x05, 0x05 };
72 
73 	// there is an sync delay which depends on colour-depth and output device
74 	if( port->disp_type == dt_dvi_1 || port->disp_type == dt_dvi_2 ||
75 		port->disp_type == dt_lvds )
76 		return hsync_fudge_fp[datatype - 1];
77     else
78     	return hsync_fudge_default[datatype - 1];
79 }
80 
81 
82 // calculate CRTC register content
83 void Radeon_CalcCRTCRegisters( accelerator_info *ai, virtual_port *port,
84 	display_mode *mode, port_regs *values )
85 {
86 	virtual_card *vc = ai->vc;
87 	shared_info *si = ai->si;
88     int    hsync_start;
89     int    hsync_wid;
90     int    hsync_fudge;
91     int    vsync_wid;
92     display_type_e disp_type;
93     physical_port *phys_port = &si->ports[port->physical_port];
94 
95 	disp_type = si->ports[port->physical_port].disp_type;
96 	hsync_fudge = Radeon_GetHSyncFudge( si, phys_port, vc->datatype );
97 
98 	if( port->is_crtc2 ) {
99 		values->crtc_gen_cntl = (RADEON_CRTC2_EN
100 			| RADEON_CRTC2_CRT2_ON
101 			| (vc->datatype << 8)
102 			| (0/*doublescan*/ ? RADEON_CRTC2_DBL_SCAN_EN	: 0)
103 			| ((mode->timing.flags & B_TIMING_INTERLACED)
104 				? RADEON_CRTC2_INTERLACE_EN	: 0));
105 
106 		//values->crtc_gen_cntl &= ~RADEON_CRTC2_CRT2_ON;
107 
108 		// make ports independant of each other
109 		switch( si->asic ) {
110 		case rt_r200:
111 		case rt_r300:
112 			values->disp_output_cntl = INREG( ai->regs, RADEON_DISP_OUTPUT_CNTL );
113 			values->disp_output_cntl =
114 				(values->disp_output_cntl & ~RADEON_DISP_DAC_SOURCE_MASK)
115 				| RADEON_DISP_DAC_SOURCE_CRTC2;
116 			break;
117 		default:
118 			// we always use CRTC1 for FP and CRTC2 for CRT
119 			// a better way were to take output device into consideration too
120 			values->dac_cntl = INREG( ai->regs, RADEON_DAC_CNTL2 ) &
121 				~RADEON_DAC_CLK_SEL;
122 			values->dac_cntl |= RADEON_DAC_CLK_SEL_CRTC2;
123 		}
124 
125 	} else {
126 		// here, we should set interlace/double scan mode
127 		// but we don't support them (anyone missing them?)
128 	    values->crtc_gen_cntl = (RADEON_CRTC_EXT_DISP_EN
129 			| RADEON_CRTC_EN
130 			| (vc->datatype << 8));
131 
132 		// we shouldn't set CRT_ON if a flat panel is connected,
133 		// but this flag seems to be independant of CRTC the
134 		// CRT is connected to
135 		values->crtc_ext_cntl =
136 	    	RADEON_VGA_ATI_LINEAR |
137 			RADEON_XCRT_CNT_EN |
138 			RADEON_CRTC_CRT_ON;
139 
140 		values->dac_cntl = RADEON_DAC_MASK_ALL
141 			| RADEON_DAC_VGA_ADR_EN
142 			| RADEON_DAC_8BIT_EN;
143 	}
144 
145     values->crtc_h_total_disp =
146     	((mode->timing.h_total / 8 - 1) & RADEON_CRTC_H_TOTAL)
147 		| (((mode->timing.h_display / 8 - 1) << RADEON_CRTC_H_DISP_SHIFT) & RADEON_CRTC_H_DISP);
148 
149     hsync_wid = (mode->timing.h_sync_end - mode->timing.h_sync_start) / 8;
150 
151     hsync_start = mode->timing.h_sync_start - 8 + hsync_fudge;
152 
153 	// TBD: the sync may be the other way around
154     values->crtc_h_sync_strt_wid =
155     	(hsync_start & (RADEON_CRTC_H_SYNC_STRT_CHAR | RADEON_CRTC_H_SYNC_STRT_PIX))
156 		| (hsync_wid << RADEON_CRTC_H_SYNC_WID_SHIFT)
157 		| ((mode->flags & B_POSITIVE_HSYNC) == 0 ? RADEON_CRTC_H_SYNC_POL : 0);
158 
159    	values->crtc_v_total_disp =
160     	((mode->timing.v_total - 1) & RADEON_CRTC_V_TOTAL)
161 		| (((mode->timing.v_display - 1) << RADEON_CRTC_V_DISP_SHIFT) & RADEON_CRTC_V_DISP);
162 
163     vsync_wid = mode->timing.v_sync_end - mode->timing.v_sync_start;
164 
165 	// TBD: vertial sync may be the other way around
166     values->crtc_v_sync_strt_wid =
167     	((mode->timing.v_sync_start - 1) & RADEON_CRTC_V_SYNC_STRT)
168 		| (vsync_wid << RADEON_CRTC_V_SYNC_WID_SHIFT)
169 		| ((mode->flags & B_POSITIVE_VSYNC) == 0
170 		    ? RADEON_CRTC_V_SYNC_POL : 0);
171 
172     values->crtc_offset_cntl = 0;
173 
174 	values->crtc_pitch = Radeon_RoundVWidth( mode->virtual_width, vc->bpp ) / 8;
175 
176 	SHOW_FLOW( 2, "crtc_pitch=%ld", values->crtc_pitch );
177 
178     values->crtc_pitch |= values->crtc_pitch << 16;
179 }
180