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