1 /* second CTRC functionality 2 3 Authors: 4 Mark Watson 6/2000, 5 Rudolf Cornelissen 12/2002 - 12/2003 6 */ 7 8 #define MODULE_BIT 0x00020000 9 10 #include "mga_std.h" 11 12 /*set a mode line - inputs are in pixels/scanlines*/ 13 status_t g400_crtc2_set_timing(display_mode target) 14 { 15 uint32 temp; 16 17 LOG(4,("CRTC2: setting timing\n")); 18 19 if ((!(target.flags & TV_BITS)) || (si->ps.card_type <= G400MAX)) 20 { 21 /* G450/G550 monitor mode, and all modes on older cards */ 22 23 /* check horizontal timing parameters are to nearest 8 pixels */ 24 if ((target.timing.h_display & 0x07) | (target.timing.h_sync_start & 0x07) | 25 (target.timing.h_sync_end & 0x07) | (target.timing.h_total & 0x07)) 26 { 27 LOG(8,("CRTC2: Horizontal timings are not multiples of 8 pixels\n")); 28 return B_ERROR; 29 } 30 31 /* make sure NTSC clock killer circuitry is disabled */ 32 CR2W(DATACTL, (CR2R(DATACTL) & ~0x00000010)); 33 34 /* make sure CRTC2 is set to progressive scan for monitor mode */ 35 CR2W(CTL, (CR2R(CTL) & ~0x02001000)); 36 37 /* program the second CRTC */ 38 CR2W(HPARAM, ((((target.timing.h_display - 8) & 0x0fff) << 16) | 39 ((target.timing.h_total - 8) & 0x0fff))); 40 CR2W(HSYNC, ((((target.timing.h_sync_end - 8) & 0x0fff) << 16) | 41 ((target.timing.h_sync_start - 8) & 0x0fff))); 42 CR2W(VPARAM, ((((target.timing.v_display - 1) & 0x0fff) << 16) | 43 ((target.timing.v_total - 1) & 0x0fff))); 44 CR2W(VSYNC, ((((target.timing.v_sync_end - 1) & 0x0fff) << 16) | 45 ((target.timing.v_sync_start - 1) & 0x0fff))); 46 //Mark: (wrong AFAIK, warning: SETMODE MAVEN-CRTC delay is now tuned to new setup!!) 47 //CR2W(PRELOAD, (((target.timing.v_sync_start & 0x0fff) << 16) | 48 // (target.timing.h_sync_start & 0x0fff))); 49 CR2W(PRELOAD, ((((target.timing.v_sync_start - 1) & 0x0fff) << 16) | 50 ((target.timing.h_sync_start - 8) & 0x0fff))); 51 52 temp = (0xfff << 16); 53 if (!(target.timing.flags & B_POSITIVE_HSYNC)) temp |= (0x01 << 8); 54 if (!(target.timing.flags & B_POSITIVE_VSYNC)) temp |= (0x01 << 9); 55 CR2W(MISC, temp); 56 57 /* On <= G400MAX dualhead cards we need to send a copy to the MAVEN; 58 * unless TVout is active */ 59 if ((si->ps.secondary_head) && (!(target.flags & TV_BITS))) 60 gx00_maven_set_timing(target); 61 } 62 else 63 { 64 /* G450/G550 TVout mode */ 65 display_mode tv_mode = target; 66 uint8 frame; 67 unsigned int vcount, prev_vcount; 68 69 LOG(4,("CRTC2: setting up G450/G550 TVout mode\n")); 70 71 /* check horizontal timing parameters are to nearest 8 pixels */ 72 if ((tv_mode.timing.h_display & 0x07) | (tv_mode.timing.h_sync_start & 0x07) | 73 (tv_mode.timing.h_sync_end & 0x07)) 74 { 75 LOG(8,("CRTC2: Horizontal timings are not multiples of 8 pixels\n")); 76 return B_ERROR; 77 } 78 79 /* disable NTSC clock killer circuitry */ 80 CR2W(DATACTL, (CR2R(DATACTL) & ~0x00000010)); 81 82 if (tv_mode.timing.h_total & 0x07) 83 { 84 /* we rely on this for both PAL and NTSC modes if h_total is 'illegal' */ 85 LOG(4,("CRTC2: enabling clock killer circuitry\n")); 86 CR2W(DATACTL, (CR2R(DATACTL) | 0x00000010)); 87 } 88 89 /* make sure h_total is valid for TVout mode */ 90 tv_mode.timing.h_total &= ~0x07; 91 92 /* modify tv_mode for interlaced use */ 93 tv_mode.timing.v_display >>= 1; 94 tv_mode.timing.v_sync_start >>= 1; 95 tv_mode.timing.v_sync_end >>= 1; 96 tv_mode.timing.v_total >>= 1; 97 98 /*program the second CRTC*/ 99 CR2W(HPARAM, ((((tv_mode.timing.h_display - 8) & 0x0fff) << 16) | 100 ((tv_mode.timing.h_total - 8) & 0x0fff))); 101 CR2W(HSYNC, ((((tv_mode.timing.h_sync_end - 8) & 0x0fff) << 16) | 102 ((tv_mode.timing.h_sync_start - 8) & 0x0fff))); 103 CR2W(VPARAM, ((((tv_mode.timing.v_display - 1) & 0x0fff) << 16) | 104 ((tv_mode.timing.v_total - 1) & 0x0fff))); 105 CR2W(VSYNC, ((((tv_mode.timing.v_sync_end - 1) & 0x0fff) << 16) | 106 ((tv_mode.timing.v_sync_start - 1) & 0x0fff))); 107 //Mark: (wrong AFAIK, warning: SETMODE MAVEN-CRTC delay is now tuned to new setup!!) 108 //CR2W(PRELOAD, (((tv_mode.timing.v_sync_start & 0x0fff) << 16) | 109 // (tv_mode.timing.h_sync_start & 0x0fff))); 110 CR2W(PRELOAD, ((((tv_mode.timing.v_sync_start - 1) & 0x0fff) << 16) | 111 ((tv_mode.timing.h_sync_start - 8) & 0x0fff))); 112 113 /* set CRTC2 to interlaced mode: 114 * First enable progressive scan mode while making sure 115 * CRTC2 is setup for TVout mode use... */ 116 CR2W(CTL, ((CR2R(CTL) & ~0x02000000) | 0x00001000)); 117 /* now synchronize to the start of a frame... */ 118 prev_vcount = 0; 119 for (frame = 0; frame < 2; frame++) 120 { 121 for (;;) 122 { 123 vcount = (CR2R(VCOUNT) & 0x00000fff); 124 if (vcount >= prev_vcount) 125 prev_vcount = vcount; 126 else 127 break; 128 } 129 } 130 /* and start interlaced mode now! */ 131 CR2W(CTL, (CR2R(CTL) | 0x02000000)); 132 133 temp = (0xfff << 16); 134 if (!(tv_mode.timing.flags & B_POSITIVE_HSYNC)) temp |= (0x01 << 8); 135 if (!(tv_mode.timing.flags & B_POSITIVE_VSYNC)) temp |= (0x01 << 9); 136 CR2W(MISC, temp); 137 } 138 139 return B_OK; 140 } 141 142 status_t g400_crtc2_depth(int mode) 143 { 144 /* validate bit depth and set mode */ 145 /* also clears TVout mode (b12) */ 146 switch(mode) 147 { 148 case BPP16:case BPP32DIR: 149 CR2W(CTL,(CR2R(CTL)&0xFF10077F)|(mode<<21)); 150 break; 151 case BPP8:case BPP15:case BPP24:case BPP32:default: 152 LOG(8,("CRTC2:Invalid bit depth\n")); 153 return B_ERROR; 154 break; 155 } 156 157 return B_OK; 158 } 159 160 status_t g400_crtc2_dpms(bool display, bool h, bool v) 161 { 162 LOG(4,("CRTC2: setting DPMS: ")); 163 164 if (si->ps.card_type <= G400MAX) 165 { 166 if (display && h && v) 167 { 168 /* enable CRTC2 and don't touch the rest */ 169 CR2W(CTL, ((CR2R(CTL) & 0xFFF0177E) | 0x01)); 170 LOG(4,("display on, hsync enabled, vsync enabled\n")); 171 } 172 else 173 { 174 /* disable CRTC2 and don't touch the rest */ 175 CR2W(CTL, (CR2R(CTL) & 0xFFF0177E)); 176 LOG(4,("display off, hsync disabled, vsync disabled\n")); 177 } 178 179 /* On <= G400MAX dualhead cards we always need to send a 'copy' to the MAVEN */ 180 if (si->ps.secondary_head) gx00_maven_dpms(display, h, v); 181 } 182 else /* G450/G550 */ 183 { 184 /* set HD15 and DVI-A sync pol. to be fixed 'straight through' from the CRTCs, 185 * and preset enabled sync signals on both connectors. 186 * (polarities and primary DPMS are done via other registers.) */ 187 uint8 temp = 0x00; 188 189 if (display) 190 { 191 /* enable CRTC2 and don't touch the rest */ 192 CR2W(CTL, ((CR2R(CTL) & 0xFFF0177E) | 0x01)); 193 LOG(4,("display on, ")); 194 } 195 else 196 { 197 /* disable CRTC2 and don't touch the rest */ 198 CR2W(CTL, (CR2R(CTL) & 0xFFF0177E)); 199 LOG(4,("display off, ")); 200 } 201 202 if (si->crossed_conns) 203 { 204 if (h) 205 { 206 /* enable DVI-A hsync */ 207 temp &= ~0x01; 208 LOG(4,("hsync enabled, ")); 209 } 210 else 211 { 212 /* disable DVI-A hsync */ 213 temp |= 0x01; 214 LOG(4,("hsync disabled, ")); 215 } 216 if (v) 217 { 218 /* enable DVI-A vsync */ 219 temp &= ~0x02; 220 LOG(4,("vsync enabled\n")); 221 } 222 else 223 { 224 /* disable DVI-A vsync */ 225 temp |= 0x02; 226 LOG(4,("vsync disabled\n")); 227 } 228 } 229 else 230 { 231 if (h) 232 { 233 /* enable HD15 hsync */ 234 temp &= ~0x10; 235 LOG(4,("hsync enabled, ")); 236 } 237 else 238 { 239 /* disable HD15 hsync */ 240 temp |= 0x10; 241 LOG(4,("hsync disabled, ")); 242 } 243 if (v) 244 { 245 /* enable HD15 vsync */ 246 temp &= ~0x20; 247 LOG(4,("vsync enabled\n")); 248 } 249 else 250 { 251 /* disable HD15 vsync */ 252 temp |= 0x20; 253 LOG(4,("vsync disabled\n")); 254 } 255 } 256 /* program new syncs */ 257 DXIW(SYNCCTRL, temp); 258 } 259 260 return B_OK; 261 } 262 263 status_t g400_crtc2_dpms_fetch(bool *display, bool *h, bool *v) 264 { 265 *display = (CR2R(CTL) & 0x00000001); 266 267 if ((si->ps.card_type <= G400MAX)) 268 { 269 /* no full DPMS support: display controls all signals */ 270 *h = *v = *display; 271 } 272 else 273 { 274 /* G450 and G550 have full DPMS support on CRTC2 */ 275 if (si->crossed_conns) 276 { 277 *h = !(DXIR(SYNCCTRL) & 0x01); 278 *v = !(DXIR(SYNCCTRL) & 0x02); 279 } 280 else 281 { 282 *h = !(DXIR(SYNCCTRL) & 0x10); 283 *v = !(DXIR(SYNCCTRL) & 0x20); 284 } 285 } 286 287 LOG(4,("CTRC2: fetched DPMS state: ")); 288 if (*display) LOG(4,("display on, ")); 289 else LOG(4,("display off, ")); 290 if (*h) LOG(4,("hsync enabled, ")); 291 else LOG(4,("hsync disabled, ")); 292 if (*v) LOG(4,("vsync enabled\n")); 293 else LOG(4,("vsync disabled\n")); 294 295 return B_OK; 296 } 297 298 status_t g400_crtc2_set_display_pitch() 299 { 300 uint32 offset; 301 302 LOG(4,("CRTC2: setting card pitch (offset between lines)\n")); 303 304 /* figure out offset value hardware needs */ 305 offset = si->fbc.bytes_per_row; 306 if (si->interlaced_tv_mode) 307 { 308 LOG(4,("CRTC2: setting interlaced mode\n")); 309 /* double the CRTC2 linelength so fields are displayed instead of frames */ 310 offset *= 2; 311 } 312 else 313 LOG(4,("CRTC2: setting progressive scan mode\n")); 314 315 LOG(2,("CRTC2: offset set to %d bytes\n", offset)); 316 317 /* program the head */ 318 CR2W(OFFSET,offset); 319 return B_OK; 320 } 321 322 status_t g400_crtc2_set_display_start(uint32 startadd,uint8 bpp) 323 { 324 LOG(4,("CRTC2: setting card RAM to be displayed for %d bits per pixel\n", bpp)); 325 326 LOG(2,("CRTC2: startadd: $%x\n",startadd)); 327 LOG(2,("CRTC2: frameRAM: $%x\n",si->framebuffer)); 328 LOG(2,("CRTC2: framebuffer: $%x\n",si->fbc.frame_buffer)); 329 330 if (si->interlaced_tv_mode) 331 { 332 LOG(4,("CRTC2: setting up fields for interlaced mode\n")); 333 /* program the head for interlaced use */ 334 //fixme: seperate both heads: we need a secondary si->fbc! 335 /* setup field 0 startadress in buffer to read picture's odd lines */ 336 CR2W(STARTADD0, (startadd + si->fbc.bytes_per_row)); 337 /* setup field 1 startadress in buffer to read picture's even lines */ 338 CR2W(STARTADD1, startadd); 339 } 340 else 341 { 342 LOG(4,("CRTC2: setting up frames for progressive scan mode\n")); 343 /* program the head for non-interlaced use */ 344 CR2W(STARTADD0, startadd); 345 } 346 347 return B_OK; 348 } 349