108705d96Sshatty 208705d96Sshatty /* 308705d96Sshatty Copyright 1999, Be Incorporated. All Rights Reserved. 408705d96Sshatty This file may be used under the terms of the Be Sample Code License. 508705d96Sshatty 608705d96Sshatty Other authors: 708705d96Sshatty Mark Watson, 808705d96Sshatty Apsed, 9b2459715SRudolf Cornelissen Rudolf Cornelissen 11/2002-10/2005 1008705d96Sshatty */ 1108705d96Sshatty 1208705d96Sshatty #define MODULE_BIT 0x00200000 1308705d96Sshatty 1408705d96Sshatty #include "acc_std.h" 1508705d96Sshatty 1608705d96Sshatty /* 1708705d96Sshatty Enable/Disable interrupts. Just a wrapper around the 1808705d96Sshatty ioctl() to the kernel driver. 1908705d96Sshatty */ 2008705d96Sshatty static void interrupt_enable(bool flag) { 2108705d96Sshatty status_t result; 2208705d96Sshatty nv_set_bool_state sbs; 2308705d96Sshatty 2408705d96Sshatty /* set the magic number so the driver knows we're for real */ 2508705d96Sshatty sbs.magic = NV_PRIVATE_DATA_MAGIC; 2608705d96Sshatty sbs.do_it = flag; 2708705d96Sshatty /* contact driver and get a pointer to the registers and shared data */ 2808705d96Sshatty result = ioctl(fd, NV_RUN_INTERRUPTS, &sbs, sizeof(sbs)); 2908705d96Sshatty } 3008705d96Sshatty 3108705d96Sshatty /* First validate the mode, then call lots of bit banging stuff to set the mode(s)! */ 3208705d96Sshatty status_t SET_DISPLAY_MODE(display_mode *mode_to_set) 3308705d96Sshatty { 3408705d96Sshatty /* BOUNDS WARNING: 3508705d96Sshatty * It's impossible to deviate whatever small amount in a display_mode if the lower 3608705d96Sshatty * and upper limits are the same! 3708705d96Sshatty * Besides: 3808705d96Sshatty * BeOS (tested R5.0.3PE) is failing BWindowScreen::SetFrameBuffer() if PROPOSEMODE 3908705d96Sshatty * returns B_BAD_VALUE! 4008705d96Sshatty * Which means PROPOSEMODE should not return that on anything except on 4108705d96Sshatty * deviations for: 4208705d96Sshatty * display_mode.virtual_width; 4308705d96Sshatty * display_mode.virtual_height; 4408705d96Sshatty * display_mode.timing.h_display; 4508705d96Sshatty * display_mode.timing.v_display; 4608705d96Sshatty * So: 4708705d96Sshatty * We don't use bounds here by making sure bounds and target are the same struct! 4808705d96Sshatty * (See the call to PROPOSE_DISPLAY_MODE below) */ 4908705d96Sshatty display_mode /*bounds,*/ target; 5008705d96Sshatty 5108705d96Sshatty uint8 colour_depth1 = 32; 5208705d96Sshatty status_t result; 5308705d96Sshatty uint32 startadd,startadd_right; 5408705d96Sshatty bool display, h, v; 5530f76422SRudolf Cornelissen // bool crt1, crt2, cross; 5608705d96Sshatty 5708705d96Sshatty /* Adjust mode to valid one and fail if invalid */ 5808705d96Sshatty target /*= bounds*/ = *mode_to_set; 5908705d96Sshatty /* show the mode bits */ 6008705d96Sshatty LOG(1, ("SETMODE: (ENTER) initial modeflags: $%08x\n", target.flags)); 6108705d96Sshatty LOG(1, ("SETMODE: requested target pixelclock %dkHz\n", target.timing.pixel_clock)); 6208705d96Sshatty LOG(1, ("SETMODE: requested virtual_width %d, virtual_height %d\n", 6308705d96Sshatty target.virtual_width, target.virtual_height)); 6408705d96Sshatty 6508705d96Sshatty /* See BOUNDS WARNING above... */ 6608705d96Sshatty if (PROPOSE_DISPLAY_MODE(&target, &target, &target) == B_ERROR) return B_ERROR; 6708705d96Sshatty 6808705d96Sshatty /* if not dualhead capable card clear dualhead flags */ 6908705d96Sshatty if (!(target.flags & DUALHEAD_CAPABLE)) 7008705d96Sshatty { 7108705d96Sshatty target.flags &= ~DUALHEAD_BITS; 7208705d96Sshatty } 7308705d96Sshatty /* if not TVout capable card clear TVout flags */ 7408705d96Sshatty if (!(target.flags & TV_CAPABLE)) 7508705d96Sshatty { 7608705d96Sshatty target.flags &= ~TV_BITS; 7708705d96Sshatty } 7808705d96Sshatty LOG(1, ("SETMODE: (CONT.) validated command modeflags: $%08x\n", target.flags)); 7908705d96Sshatty 80c9c0c72bSRudolf Cornelissen /* make sure a possible 3D add-on will block rendering and re-initialize itself. 81c9c0c72bSRudolf Cornelissen * note: update in _this_ order only */ 82c9c0c72bSRudolf Cornelissen /* SET_DISPLAY_MODE will reset this flag when it's done. */ 8321545d00SRudolf Cornelissen si->engine.threeD.mode_changing = true; 8421545d00SRudolf Cornelissen /* every 3D add-on will reset this bit-flag when it's done. */ 8521545d00SRudolf Cornelissen si->engine.threeD.newmode = 0xffffffff; 8621545d00SRudolf Cornelissen /* every 3D clone needs to reclaim a slot. 8721545d00SRudolf Cornelissen * note: this also cleans up reserved channels for killed 3D clones.. */ 8821545d00SRudolf Cornelissen si->engine.threeD.clones = 0x00000000; 89afb207acSRudolf Cornelissen 9008705d96Sshatty /* disable interrupts using the kernel driver */ 9108705d96Sshatty interrupt_enable(false); 9208705d96Sshatty 93*0b36eea4SRudolf Cornelissen /* disable TVout (set GPU CRTC to master mode) */ 94*0b36eea4SRudolf Cornelissen //fixme: testing on singlehead cards only for now... 95*0b36eea4SRudolf Cornelissen //tmp disabled: 96*0b36eea4SRudolf Cornelissen // if (!(si->ps.secondary_head)) BT_stop_tvout(); 97*0b36eea4SRudolf Cornelissen 9808705d96Sshatty /* find current DPMS state, then turn off screen(s) */ 990669fe20SRudolf Cornelissen head1_dpms_fetch(&display, &h, &v); 1000669fe20SRudolf Cornelissen head1_dpms(false, false, false); 1010669fe20SRudolf Cornelissen if (si->ps.secondary_head) head2_dpms(false, false, false); 10208705d96Sshatty 10308705d96Sshatty /*where in framebuffer the screen is (should this be dependant on previous MOVEDISPLAY?)*/ 104f2777ca1SRudolf Cornelissen startadd = (uint8*)si->fbc.frame_buffer - (uint8*)si->framebuffer; 10508705d96Sshatty 10608705d96Sshatty /* calculate and set new mode bytes_per_row */ 10705ed3229SRudolf Cornelissen nv_general_validate_pic_size (&target, &si->fbc.bytes_per_row, &si->acc_mode); 10808705d96Sshatty 10908705d96Sshatty /*Perform the very long mode switch!*/ 11008705d96Sshatty if (target.flags & DUALHEAD_BITS) /*if some dualhead mode*/ 11108705d96Sshatty { 11208705d96Sshatty uint8 colour_depth2 = colour_depth1; 11308705d96Sshatty 11408705d96Sshatty /* init display mode for secondary head */ 11508705d96Sshatty display_mode target2 = target; 11608705d96Sshatty 11708705d96Sshatty LOG(1,("SETMODE: setting DUALHEAD mode\n")); 11808705d96Sshatty 11908705d96Sshatty /* validate flags for secondary TVout */ 120b2459715SRudolf Cornelissen //fixme: remove or block on autodetect fail. (is now shutoff) 121b2459715SRudolf Cornelissen if ((0) && (target2.flags & TV_BITS)) 12208705d96Sshatty { 12308705d96Sshatty target.flags &= ~TV_BITS;//still needed for some routines... 12408705d96Sshatty target2.flags &= ~TV_BITS; 12508705d96Sshatty LOG(1,("SETMODE: blocking TVout: no TVout cable connected!\n")); 12608705d96Sshatty } 12708705d96Sshatty 12830f76422SRudolf Cornelissen /* detect which connectors have a CRT connected */ 12930f76422SRudolf Cornelissen //fixme: 'hot-plugging' for analog monitors removed: remove code as well; 13030f76422SRudolf Cornelissen //or make it work with digital panels connected as well. 13130f76422SRudolf Cornelissen // crt1 = nv_dac_crt_connected(); 13230f76422SRudolf Cornelissen // crt2 = nv_dac2_crt_connected(); 13330f76422SRudolf Cornelissen /* connect outputs 'straight-through' */ 13430f76422SRudolf Cornelissen // if (crt1) 13530f76422SRudolf Cornelissen // { 13630f76422SRudolf Cornelissen /* connector1 is used as primary output */ 13730f76422SRudolf Cornelissen // cross = false; 13830f76422SRudolf Cornelissen // } 13930f76422SRudolf Cornelissen // else 14030f76422SRudolf Cornelissen // { 14130f76422SRudolf Cornelissen // if (crt2) 14230f76422SRudolf Cornelissen /* connector2 is used as primary output */ 14330f76422SRudolf Cornelissen // cross = true; 14430f76422SRudolf Cornelissen // else 14530f76422SRudolf Cornelissen /* no CRT detected: assume connector1 is used as primary output */ 14630f76422SRudolf Cornelissen // cross = false; 14730f76422SRudolf Cornelissen // } 14830f76422SRudolf Cornelissen /* set output connectors assignment if possible */ 14930f76422SRudolf Cornelissen if ((target.flags & DUALHEAD_BITS) == DUALHEAD_SWITCH) 15030f76422SRudolf Cornelissen /* invert output assignment in switch mode */ 15106f4c439SRudolf Cornelissen nv_general_head_select(true); 15230f76422SRudolf Cornelissen else 15306f4c439SRudolf Cornelissen nv_general_head_select(false); 15430f76422SRudolf Cornelissen 15508705d96Sshatty /* set the pixel clock PLL(s) */ 15608705d96Sshatty LOG(8,("SETMODE: target clock %dkHz\n",target.timing.pixel_clock)); 15730f76422SRudolf Cornelissen if (head1_set_pix_pll(target) == B_ERROR) 15808705d96Sshatty LOG(8,("SETMODE: error setting pixel clock (internal DAC)\n")); 15908705d96Sshatty 16008705d96Sshatty /* we do not need to set the pixelclock here for a head that's in TVout mode */ 16108705d96Sshatty if (!(target2.flags & TV_BITS)) 16208705d96Sshatty { 16308705d96Sshatty LOG(8,("SETMODE: target2 clock %dkHz\n",target2.timing.pixel_clock)); 16430f76422SRudolf Cornelissen if (head2_set_pix_pll(target2) == B_ERROR) 165a3b9d212SRudolf Cornelissen LOG(8,("SETMODE: error setting pixel clock (DAC2)\n")); 16608705d96Sshatty } 16708705d96Sshatty 16808705d96Sshatty /*set the colour depth for CRTC1 and the DAC */ 16908705d96Sshatty switch(target.space) 17008705d96Sshatty { 171bc5690abSRudolf Cornelissen case B_CMAP8: 172bc5690abSRudolf Cornelissen colour_depth1 = 8; 17330f76422SRudolf Cornelissen head1_mode(BPP8, 1.0); 1740669fe20SRudolf Cornelissen head1_depth(BPP8); 175bc5690abSRudolf Cornelissen break; 176bc5690abSRudolf Cornelissen case B_RGB15_LITTLE: 177bc5690abSRudolf Cornelissen colour_depth1 = 16; 17830f76422SRudolf Cornelissen head1_mode(BPP15, 1.0); 1790669fe20SRudolf Cornelissen head1_depth(BPP15); 180bc5690abSRudolf Cornelissen break; 18108705d96Sshatty case B_RGB16_LITTLE: 18208705d96Sshatty colour_depth1 = 16; 18330f76422SRudolf Cornelissen head1_mode(BPP16, 1.0); 1840669fe20SRudolf Cornelissen head1_depth(BPP16); 18508705d96Sshatty break; 18608705d96Sshatty case B_RGB32_LITTLE: 18708705d96Sshatty colour_depth1 = 32; 18830f76422SRudolf Cornelissen head1_mode(BPP32, 1.0); 1890669fe20SRudolf Cornelissen head1_depth(BPP32); 19008705d96Sshatty break; 19108705d96Sshatty } 192a3b9d212SRudolf Cornelissen /*set the colour depth for CRTC2 and DAC2 */ 19308705d96Sshatty switch(target2.space) 19408705d96Sshatty { 195bc5690abSRudolf Cornelissen case B_CMAP8: 196bc5690abSRudolf Cornelissen colour_depth2 = 8; 19730f76422SRudolf Cornelissen head2_mode(BPP8, 1.0); 1980669fe20SRudolf Cornelissen head2_depth(BPP8); 199bc5690abSRudolf Cornelissen break; 200bc5690abSRudolf Cornelissen case B_RGB15_LITTLE: 201bc5690abSRudolf Cornelissen colour_depth2 = 16; 20230f76422SRudolf Cornelissen head2_mode(BPP15, 1.0); 2030669fe20SRudolf Cornelissen head2_depth(BPP15); 204bc5690abSRudolf Cornelissen break; 20508705d96Sshatty case B_RGB16_LITTLE: 20608705d96Sshatty colour_depth2 = 16; 20730f76422SRudolf Cornelissen head2_mode(BPP16, 1.0); 2080669fe20SRudolf Cornelissen head2_depth(BPP16); 20908705d96Sshatty break; 21008705d96Sshatty case B_RGB32_LITTLE: 21108705d96Sshatty colour_depth2 = 32; 21230f76422SRudolf Cornelissen head2_mode(BPP32, 1.0); 2130669fe20SRudolf Cornelissen head2_depth(BPP32); 21408705d96Sshatty break; 21508705d96Sshatty } 21608705d96Sshatty 21708705d96Sshatty /* check if we are doing interlaced TVout mode */ 218b2459715SRudolf Cornelissen //fixme: we don't support interlaced mode? 21908705d96Sshatty si->interlaced_tv_mode = false; 22008705d96Sshatty /* if ((target2.flags & TV_BITS) && (si->ps.card_type >= G450)) 22108705d96Sshatty si->interlaced_tv_mode = true; 22208705d96Sshatty */ 22308705d96Sshatty /*set the display(s) pitches*/ 2240669fe20SRudolf Cornelissen head1_set_display_pitch (); 22508705d96Sshatty //fixme: seperate for real dualhead modes: 22608705d96Sshatty //we need a secondary si->fbc! 2270669fe20SRudolf Cornelissen head2_set_display_pitch (); 22808705d96Sshatty 22908705d96Sshatty /*work out where the "right" screen starts*/ 23008705d96Sshatty startadd_right = startadd + (target.timing.h_display * (colour_depth1 >> 3)); 23108705d96Sshatty 23208705d96Sshatty /* Tell card what memory to display */ 23308705d96Sshatty switch (target.flags & DUALHEAD_BITS) 23408705d96Sshatty { 23508705d96Sshatty case DUALHEAD_ON: 23608705d96Sshatty case DUALHEAD_SWITCH: 2370669fe20SRudolf Cornelissen head1_set_display_start(startadd,colour_depth1); 2380669fe20SRudolf Cornelissen head2_set_display_start(startadd_right,colour_depth2); 23908705d96Sshatty break; 24008705d96Sshatty case DUALHEAD_CLONE: 2410669fe20SRudolf Cornelissen head1_set_display_start(startadd,colour_depth1); 2420669fe20SRudolf Cornelissen head2_set_display_start(startadd,colour_depth2); 24308705d96Sshatty break; 24408705d96Sshatty } 24508705d96Sshatty 24608705d96Sshatty /* set the timing */ 2470669fe20SRudolf Cornelissen head1_set_timing(target); 24808705d96Sshatty /* we do not need to setup CRTC2 here for a head that's in TVout mode */ 2490669fe20SRudolf Cornelissen if (!(target2.flags & TV_BITS)) result = head2_set_timing(target2); 25008705d96Sshatty 25108705d96Sshatty /* TVout support: setup CRTC2 and it's pixelclock */ 252b2459715SRudolf Cornelissen if (si->ps.tvout && (target2.flags & TV_BITS)) BT_setmode(target2); 25308705d96Sshatty } 25408705d96Sshatty else /* single head mode */ 25508705d96Sshatty { 25608705d96Sshatty status_t status; 25708705d96Sshatty int colour_mode = BPP32; 25808705d96Sshatty 25930f76422SRudolf Cornelissen /* connect output */ 26030f76422SRudolf Cornelissen if (si->ps.secondary_head) 26130f76422SRudolf Cornelissen { 26230f76422SRudolf Cornelissen /* detect which connectors have a CRT connected */ 26330f76422SRudolf Cornelissen //fixme: 'hot-plugging' for analog monitors removed: remove code as well; 26430f76422SRudolf Cornelissen //or make it work with digital panels connected as well. 26530f76422SRudolf Cornelissen // crt1 = nv_dac_crt_connected(); 26630f76422SRudolf Cornelissen // crt2 = nv_dac2_crt_connected(); 26730f76422SRudolf Cornelissen /* connect outputs 'straight-through' */ 26830f76422SRudolf Cornelissen // if (crt1) 26930f76422SRudolf Cornelissen // { 27030f76422SRudolf Cornelissen /* connector1 is used as primary output */ 27130f76422SRudolf Cornelissen // cross = false; 27230f76422SRudolf Cornelissen // } 27330f76422SRudolf Cornelissen // else 27430f76422SRudolf Cornelissen // { 27530f76422SRudolf Cornelissen // if (crt2) 27630f76422SRudolf Cornelissen /* connector2 is used as primary output */ 27730f76422SRudolf Cornelissen // cross = true; 27830f76422SRudolf Cornelissen // else 27930f76422SRudolf Cornelissen /* no CRT detected: assume connector1 is used as primary output */ 28030f76422SRudolf Cornelissen // cross = false; 28130f76422SRudolf Cornelissen // } 28230f76422SRudolf Cornelissen /* set output connectors assignment if possible */ 28306f4c439SRudolf Cornelissen nv_general_head_select(false); 28430f76422SRudolf Cornelissen } 28530f76422SRudolf Cornelissen 28608705d96Sshatty switch(target.space) 28708705d96Sshatty { 28808705d96Sshatty case B_CMAP8: colour_depth1 = 8; colour_mode = BPP8; break; 28908705d96Sshatty case B_RGB15_LITTLE: colour_depth1 = 16; colour_mode = BPP15; break; 29008705d96Sshatty case B_RGB16_LITTLE: colour_depth1 = 16; colour_mode = BPP16; break; 29108705d96Sshatty case B_RGB32_LITTLE: colour_depth1 = 32; colour_mode = BPP32; break; 29208705d96Sshatty default: 29308705d96Sshatty LOG(8,("SETMODE: Invalid singlehead colour depth 0x%08x\n", target.space)); 29408705d96Sshatty return B_ERROR; 29508705d96Sshatty } 29608705d96Sshatty 29708705d96Sshatty /* set the pixel clock PLL */ 29830f76422SRudolf Cornelissen status = head1_set_pix_pll(target); 29908705d96Sshatty 30008705d96Sshatty if (status==B_ERROR) 30108705d96Sshatty LOG(8,("CRTC: error setting pixel clock (internal DAC)\n")); 30208705d96Sshatty 30308705d96Sshatty /* set the colour depth for CRTC1 and the DAC */ 30408705d96Sshatty /* first set the colordepth */ 3050669fe20SRudolf Cornelissen head1_depth(colour_mode); 30608705d96Sshatty /* then(!) program the PAL (<8bit colordepth does not support 8bit PAL) */ 30730f76422SRudolf Cornelissen head1_mode(colour_mode,1.0); 30808705d96Sshatty 30908705d96Sshatty /* set the display pitch */ 3100669fe20SRudolf Cornelissen head1_set_display_pitch(); 31108705d96Sshatty 31208705d96Sshatty /* tell the card what memory to display */ 3130669fe20SRudolf Cornelissen head1_set_display_start(startadd,colour_depth1); 31408705d96Sshatty 31508705d96Sshatty /* set the timing */ 316b2459715SRudolf Cornelissen if (!(target.flags & TV_BITS)) head1_set_timing(target); 317b2459715SRudolf Cornelissen 318b2459715SRudolf Cornelissen /* TVout support: setup CRTC and it's pixelclock */ 319b2459715SRudolf Cornelissen if (si->ps.tvout && (target.flags & TV_BITS)) BT_setmode(target); 32008705d96Sshatty 32108705d96Sshatty //fixme: shut-off the videoPLL if it exists... 32208705d96Sshatty } 32308705d96Sshatty 32408705d96Sshatty /* update driver's mode store */ 32508705d96Sshatty si->dm = target; 32608705d96Sshatty 3273c4c0505SRudolf Cornelissen /* update FIFO data fetching according to mode */ 3283c4c0505SRudolf Cornelissen nv_crtc_update_fifo(); 3293c4c0505SRudolf Cornelissen 33008705d96Sshatty /* turn screen one on */ 3310669fe20SRudolf Cornelissen head1_dpms(display, h, v); 33208705d96Sshatty /* turn screen two on if a dualhead mode is active */ 3330669fe20SRudolf Cornelissen if (target.flags & DUALHEAD_BITS) head2_dpms(display,h,v); 33408705d96Sshatty 33508705d96Sshatty /* set up acceleration for this mode */ 336dd43fd34SRudolf Cornelissen /* note: 3373c4c0505SRudolf Cornelissen * Maybe later we can forget about non-DMA mode (depends on 3D acceleration 3383c4c0505SRudolf Cornelissen * attempts). */ 339dd446dd3SRudolf Cornelissen if (!si->settings.dma_acc) 340b4c44701Sshatty nv_acc_init(); 341dd43fd34SRudolf Cornelissen else 342dd43fd34SRudolf Cornelissen nv_acc_init_dma(); 343b4c44701Sshatty /* set up overlay unit for this mode */ 344aa1e552fSshatty nv_bes_init(); 34508705d96Sshatty 34689d37d46SRudolf Cornelissen /* note freemem range */ 34789d37d46SRudolf Cornelissen /* first free adress follows hardcursor and workspace */ 34821545d00SRudolf Cornelissen si->engine.threeD.mem_low = si->fbc.bytes_per_row * si->dm.virtual_height; 34921545d00SRudolf Cornelissen if (si->settings.hardcursor) si->engine.threeD.mem_low += 2048; 35089d37d46SRudolf Cornelissen /* last free adress is end-of-ram minus max space needed for overlay bitmaps */ 35189d37d46SRudolf Cornelissen //fixme possible: 35289d37d46SRudolf Cornelissen //if overlay buffers are allocated subtract buffersize from mem_high; 35389d37d46SRudolf Cornelissen //only allocate overlay buffers if 3D is not in use. (block overlay during 3D) 35421545d00SRudolf Cornelissen si->engine.threeD.mem_high = si->ps.memory_size - 1; 355fee251bcSRudolf Cornelissen /* don't touch the DMA acceleration engine command buffer if it exists */ 356fee251bcSRudolf Cornelissen /* note: 357fdd699c7SRudolf Cornelissen * the buffer is 32kB in size. Keep some extra distance for safety (faulty apps). */ 358fdd699c7SRudolf Cornelissen if (si->settings.dma_acc) 359fdd699c7SRudolf Cornelissen { 360fdd699c7SRudolf Cornelissen if (si->ps.card_arch < NV40A) 361fdd699c7SRudolf Cornelissen { 362fdd699c7SRudolf Cornelissen /* keeping 32kB distance from the DMA buffer */ 36321545d00SRudolf Cornelissen si->engine.threeD.mem_high -= (64 * 1024); 364fdd699c7SRudolf Cornelissen } 365fdd699c7SRudolf Cornelissen else 366fdd699c7SRudolf Cornelissen { 367fdd699c7SRudolf Cornelissen /* 416kB distance is just OK: keeping another 64kB distance for safety; 368fdd699c7SRudolf Cornelissen * confirmed for NV43. */ 369fdd699c7SRudolf Cornelissen /* note: 370fdd699c7SRudolf Cornelissen * if you get too close to the DMA command buffer on NV40 and NV43 at 371fdd699c7SRudolf Cornelissen * least (both confirmed), the source DMA instance will mess-up for 372fdd699c7SRudolf Cornelissen * at least engine cmd NV_IMAGE_BLIT and NV12_IMAGE_BLIT. */ 37321545d00SRudolf Cornelissen si->engine.threeD.mem_high -= (512 * 1024); 374fdd699c7SRudolf Cornelissen } 375fdd699c7SRudolf Cornelissen } 37621545d00SRudolf Cornelissen si->engine.threeD.mem_high -= (MAXBUFFERS * 1024 * 1024 * 2); /* see overlay.c file */ 37789d37d46SRudolf Cornelissen 378255e5021SRudolf Cornelissen LOG(1,("SETMODE: booted since %f mS\n", system_time()/1000.0)); 37908705d96Sshatty 38008705d96Sshatty /* enable interrupts using the kernel driver */ 38108705d96Sshatty interrupt_enable(true); 38208705d96Sshatty 383c9c0c72bSRudolf Cornelissen /* make sure a possible 3D add-on will re-initialize itself by signalling ready */ 38421545d00SRudolf Cornelissen si->engine.threeD.mode_changing = false; 385c9c0c72bSRudolf Cornelissen 38608705d96Sshatty /* optimize memory-access if needed */ 3870669fe20SRudolf Cornelissen // head1_mem_priority(colour_depth1); 38808705d96Sshatty 38908705d96Sshatty /* Tune RAM CAS-latency if needed. Must be done *here*! */ 39008705d96Sshatty nv_set_cas_latency(); 39108705d96Sshatty 39208705d96Sshatty return B_OK; 39308705d96Sshatty } 39408705d96Sshatty 39508705d96Sshatty /* 39608705d96Sshatty Set which pixel of the virtual frame buffer will show up in the 39708705d96Sshatty top left corner of the display device. Used for page-flipping 39808705d96Sshatty games and virtual desktops. 39908705d96Sshatty */ 40008705d96Sshatty status_t MOVE_DISPLAY(uint16 h_display_start, uint16 v_display_start) { 40108705d96Sshatty uint8 colour_depth; 40208705d96Sshatty uint32 startadd,startadd_right; 40308705d96Sshatty 40408705d96Sshatty LOG(4,("MOVE_DISPLAY: h %d, v %d\n", h_display_start, v_display_start)); 40508705d96Sshatty 406255e5021SRudolf Cornelissen /* nVidia cards support pixelprecise panning on both heads in all modes: 407255e5021SRudolf Cornelissen * No stepping granularity needed! */ 408255e5021SRudolf Cornelissen 409255e5021SRudolf Cornelissen /* determine bits used for the colordepth */ 41008705d96Sshatty switch(si->dm.space) 41108705d96Sshatty { 41208705d96Sshatty case B_CMAP8: 41308705d96Sshatty colour_depth=8; 41408705d96Sshatty break; 415255e5021SRudolf Cornelissen case B_RGB15_LITTLE: 416255e5021SRudolf Cornelissen case B_RGB16_LITTLE: 41708705d96Sshatty colour_depth=16; 418255e5021SRudolf Cornelissen break; 419255e5021SRudolf Cornelissen case B_RGB24_LITTLE: 420255e5021SRudolf Cornelissen colour_depth=24; 42108705d96Sshatty break; 42208705d96Sshatty case B_RGB32_LITTLE: 42308705d96Sshatty colour_depth=32; 42408705d96Sshatty break; 42508705d96Sshatty default: 42608705d96Sshatty return B_ERROR; 42708705d96Sshatty } 42808705d96Sshatty 42908705d96Sshatty /* do not run past end of display */ 43008705d96Sshatty switch (si->dm.flags & DUALHEAD_BITS) 43108705d96Sshatty { 43208705d96Sshatty case DUALHEAD_ON: 43308705d96Sshatty case DUALHEAD_SWITCH: 43408705d96Sshatty if (((si->dm.timing.h_display * 2) + h_display_start) > si->dm.virtual_width) 43508705d96Sshatty return B_ERROR; 43608705d96Sshatty break; 43708705d96Sshatty default: 43808705d96Sshatty if ((si->dm.timing.h_display + h_display_start) > si->dm.virtual_width) 43908705d96Sshatty return B_ERROR; 44008705d96Sshatty break; 44108705d96Sshatty } 44208705d96Sshatty if ((si->dm.timing.v_display + v_display_start) > si->dm.virtual_height) 44308705d96Sshatty return B_ERROR; 44408705d96Sshatty 44508705d96Sshatty /* everybody remember where we parked... */ 44608705d96Sshatty si->dm.h_display_start = h_display_start; 44708705d96Sshatty si->dm.v_display_start = v_display_start; 44808705d96Sshatty 44908705d96Sshatty /* actually set the registers */ 45008705d96Sshatty //fixme: seperate both heads: we need a secondary si->fbc! 45108705d96Sshatty startadd = v_display_start * si->fbc.bytes_per_row; 45208705d96Sshatty startadd += h_display_start * (colour_depth >> 3); 453f2777ca1SRudolf Cornelissen startadd += (uint8*)si->fbc.frame_buffer - (uint8*)si->framebuffer; 45408705d96Sshatty startadd_right = startadd + si->dm.timing.h_display * (colour_depth >> 3); 45508705d96Sshatty 45608705d96Sshatty interrupt_enable(false); 45708705d96Sshatty 45808705d96Sshatty switch (si->dm.flags & DUALHEAD_BITS) 45908705d96Sshatty { 46008705d96Sshatty case DUALHEAD_ON: 46108705d96Sshatty case DUALHEAD_SWITCH: 4620669fe20SRudolf Cornelissen head1_set_display_start(startadd,colour_depth); 4630669fe20SRudolf Cornelissen head2_set_display_start(startadd_right,colour_depth); 46408705d96Sshatty break; 46508705d96Sshatty case DUALHEAD_OFF: 4660669fe20SRudolf Cornelissen head1_set_display_start(startadd,colour_depth); 46708705d96Sshatty break; 46808705d96Sshatty case DUALHEAD_CLONE: 4690669fe20SRudolf Cornelissen head1_set_display_start(startadd,colour_depth); 4700669fe20SRudolf Cornelissen head2_set_display_start(startadd,colour_depth); 47108705d96Sshatty break; 47208705d96Sshatty } 47308705d96Sshatty 47408705d96Sshatty interrupt_enable(true); 47508705d96Sshatty return B_OK; 47608705d96Sshatty } 47708705d96Sshatty 478255e5021SRudolf Cornelissen /* Set the indexed color palette */ 47908705d96Sshatty void SET_INDEXED_COLORS(uint count, uint8 first, uint8 *color_data, uint32 flags) { 48008705d96Sshatty int i; 48108705d96Sshatty uint8 *r,*g,*b; 48208705d96Sshatty 48308705d96Sshatty /* Protect gamma correction when not in CMAP8 */ 48408705d96Sshatty if (si->dm.space != B_CMAP8) return; 48508705d96Sshatty 48608705d96Sshatty r=si->color_data; 48708705d96Sshatty g=r+256; 48808705d96Sshatty b=g+256; 48908705d96Sshatty 49008705d96Sshatty i=first; 49108705d96Sshatty while (count--) 49208705d96Sshatty { 49308705d96Sshatty r[i]=*color_data++; 49408705d96Sshatty g[i]=*color_data++; 49508705d96Sshatty b[i]=*color_data++; 49608705d96Sshatty i++; 49708705d96Sshatty } 49830f76422SRudolf Cornelissen head1_palette(r,g,b); 49930f76422SRudolf Cornelissen if (si->dm.flags & DUALHEAD_BITS) head2_palette(r,g,b); 50008705d96Sshatty } 50108705d96Sshatty 50208705d96Sshatty /* Put the display into one of the Display Power Management modes. */ 50308705d96Sshatty status_t SET_DPMS_MODE(uint32 dpms_flags) { 50408705d96Sshatty interrupt_enable(false); 50508705d96Sshatty 50608705d96Sshatty LOG(4,("SET_DPMS_MODE: 0x%08x\n", dpms_flags)); 50708705d96Sshatty 50808705d96Sshatty if (si->dm.flags & DUALHEAD_BITS) /*dualhead*/ 50908705d96Sshatty { 51008705d96Sshatty switch(dpms_flags) 51108705d96Sshatty { 51208705d96Sshatty case B_DPMS_ON: /* H: on, V: on, display on */ 5130669fe20SRudolf Cornelissen head1_dpms(true, true, true); 5140669fe20SRudolf Cornelissen if (si->ps.secondary_head) head2_dpms(true, true, true); 51508705d96Sshatty break; 51608705d96Sshatty case B_DPMS_STAND_BY: 5170669fe20SRudolf Cornelissen head1_dpms(false, false, true); 5180669fe20SRudolf Cornelissen if (si->ps.secondary_head) head2_dpms(false, false, true); 51908705d96Sshatty break; 52008705d96Sshatty case B_DPMS_SUSPEND: 5210669fe20SRudolf Cornelissen head1_dpms(false, true, false); 5220669fe20SRudolf Cornelissen if (si->ps.secondary_head) head2_dpms(false, true, false); 52308705d96Sshatty break; 52408705d96Sshatty case B_DPMS_OFF: /* H: off, V: off, display off */ 5250669fe20SRudolf Cornelissen head1_dpms(false, false, false); 5260669fe20SRudolf Cornelissen if (si->ps.secondary_head) head2_dpms(false, false, false); 52708705d96Sshatty break; 52808705d96Sshatty default: 52908705d96Sshatty LOG(8,("SET: Invalid DPMS settings (DH) 0x%08x\n", dpms_flags)); 53008705d96Sshatty interrupt_enable(true); 53108705d96Sshatty return B_ERROR; 53208705d96Sshatty } 53308705d96Sshatty } 53408705d96Sshatty else /* singlehead */ 53508705d96Sshatty { 53608705d96Sshatty switch(dpms_flags) 53708705d96Sshatty { 53808705d96Sshatty case B_DPMS_ON: /* H: on, V: on, display on */ 5390669fe20SRudolf Cornelissen head1_dpms(true, true, true); 54008705d96Sshatty break; 54108705d96Sshatty case B_DPMS_STAND_BY: 5420669fe20SRudolf Cornelissen head1_dpms(false, false, true); 54308705d96Sshatty break; 54408705d96Sshatty case B_DPMS_SUSPEND: 5450669fe20SRudolf Cornelissen head1_dpms(false, true, false); 54608705d96Sshatty break; 54708705d96Sshatty case B_DPMS_OFF: /* H: off, V: off, display off */ 5480669fe20SRudolf Cornelissen head1_dpms(false, false, false); 54908705d96Sshatty break; 55008705d96Sshatty default: 55108705d96Sshatty LOG(8,("SET: Invalid DPMS settings (DH) 0x%08x\n", dpms_flags)); 55208705d96Sshatty interrupt_enable(true); 55308705d96Sshatty return B_ERROR; 55408705d96Sshatty } 55508705d96Sshatty } 55608705d96Sshatty interrupt_enable(true); 55708705d96Sshatty return B_OK; 55808705d96Sshatty } 55908705d96Sshatty 56008705d96Sshatty /* Report device DPMS capabilities */ 56108705d96Sshatty uint32 DPMS_CAPABILITIES(void) { 56208705d96Sshatty return (B_DPMS_ON | B_DPMS_STAND_BY | B_DPMS_SUSPEND | B_DPMS_OFF); 56308705d96Sshatty } 56408705d96Sshatty 56508705d96Sshatty /* Return the current DPMS mode */ 56608705d96Sshatty uint32 DPMS_MODE(void) { 56708705d96Sshatty bool display, h, v; 56808705d96Sshatty 56908705d96Sshatty interrupt_enable(false); 5700669fe20SRudolf Cornelissen head1_dpms_fetch(&display, &h, &v); 57108705d96Sshatty interrupt_enable(true); 57208705d96Sshatty 57308705d96Sshatty if (display && h && v) 57408705d96Sshatty return B_DPMS_ON; 57508705d96Sshatty else if(v) 57608705d96Sshatty return B_DPMS_STAND_BY; 57708705d96Sshatty else if(h) 57808705d96Sshatty return B_DPMS_SUSPEND; 57908705d96Sshatty else 58008705d96Sshatty return B_DPMS_OFF; 58108705d96Sshatty } 582