diff options
author | Francisco Jerez <currojerez@gmail.com> | 2008-12-21 19:37:14 +0100 |
---|---|---|
committer | Paulo Cesar Pereira de Andrade <pcpa@mandriva.com.br> | 2008-12-21 19:22:16 -0200 |
commit | 2b3fa385a6da4be5ad6719dd115834b96d1ea3e3 (patch) | |
tree | 30a66389828ff41db9e49070aa558deb7aeca656 | |
parent | 75b1c309f1418d70e8cf112744ff95f372d4ef75 (diff) |
Add a CRTC/Output implementation using BIOS for modesetting.
After the RandR1.2 implementation the "UseBIOS" option wasn't actually
programming the hardware through VESA BIOS, this brings back that
functionality.
-rw-r--r-- | src/smilynx_crtc.c | 98 | ||||
-rw-r--r-- | src/smilynx_hw.c | 160 | ||||
-rw-r--r-- | src/smilynx_output.c | 51 |
3 files changed, 220 insertions, 89 deletions
diff --git a/src/smilynx_crtc.c b/src/smilynx_crtc.c index 08d798e..616cb81 100644 --- a/src/smilynx_crtc.c +++ b/src/smilynx_crtc.c @@ -524,6 +524,90 @@ SMILynx_CrtcModeSet_lcd(xf86CrtcPtr crtc, } static void +SMILynx_CrtcModeSet_bios(xf86CrtcPtr crtc, + DisplayModePtr mode, + DisplayModePtr adjusted_mode, + int x, int y) +{ + ScrnInfoPtr pScrn=crtc->scrn; + SMIPtr pSmi = SMIPTR(pScrn); + SMIRegPtr reg = pSmi->mode; + int i; + CARD8 tmp; + + ENTER(); + + /* Find the INT 10 mode number */ + { + static struct { + int x, y, bpp; + CARD16 mode; + } modeTable[] = + { + { 640, 480, 8, 0x50 }, + { 640, 480, 16, 0x52 }, + { 640, 480, 24, 0x53 }, + { 640, 480, 32, 0x54 }, + { 800, 480, 8, 0x4A }, + { 800, 480, 16, 0x4C }, + { 800, 480, 24, 0x4D }, + { 800, 600, 8, 0x55 }, + { 800, 600, 16, 0x57 }, + { 800, 600, 24, 0x58 }, + { 800, 600, 32, 0x59 }, + { 1024, 768, 8, 0x60 }, + { 1024, 768, 16, 0x62 }, + { 1024, 768, 24, 0x63 }, + { 1024, 768, 32, 0x64 }, + { 1280, 1024, 8, 0x65 }, + { 1280, 1024, 16, 0x67 }, + { 1280, 1024, 24, 0x68 }, + { 1280, 1024, 32, 0x69 }, + }; + + reg->mode = 0; + for (i = 0; i < sizeof(modeTable) / sizeof(modeTable[0]); i++) { + if ((modeTable[i].x == mode->HDisplay) && + (modeTable[i].y == mode->VDisplay) && + (modeTable[i].bpp == pScrn->bitsPerPixel)) { + reg->mode = modeTable[i].mode; + break; + } + } + } + + if(!reg->mode){ + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "SMILynx_CrtcModeSet_bios: Not a known BIOS mode: " + "falling back to direct modesetting.\n"); + SMILynx_CrtcModeSet_vga(crtc,mode,adjusted_mode,x,y); + LEAVE(); + } + + pSmi->pInt10->num = 0x10; + pSmi->pInt10->ax = reg->mode | 0x80; + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Setting mode 0x%02X\n", + reg->mode); + xf86ExecX86int10(pSmi->pInt10); + + /* Enable linear mode. */ + outb(pSmi->PIOBase + VGA_SEQ_INDEX, 0x18); + tmp = inb(pSmi->PIOBase + VGA_SEQ_DATA); + outb(pSmi->PIOBase + VGA_SEQ_DATA, tmp | 0x01); + + /* Enable DPR/VPR registers. */ + tmp = VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x21); + VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x21, tmp & ~0x03); + + + /* Initialize Video Processor Registers */ + + SMICRTC(crtc)->video_init(crtc); + SMILynx_CrtcAdjustFrame(crtc, x,y); + + LEAVE(); +} + +static void SMILynx_CrtcLoadLUT_crt(xf86CrtcPtr crtc) { ScrnInfoPtr pScrn = crtc->scrn; @@ -755,7 +839,12 @@ SMILynx_CrtcPreInit(ScrnInfoPtr pScrn) functions. Has someone access to this hardware? */ SMI_CrtcFuncsInit_base(&crtcFuncs, &crtcPriv); - crtcFuncs->mode_set = SMILynx_CrtcModeSet_vga; + + if(pSmi->useBIOS) + crtcFuncs->mode_set = SMILynx_CrtcModeSet_bios; + else + crtcFuncs->mode_set = SMILynx_CrtcModeSet_vga; + crtcPriv->adjust_frame = SMILynx_CrtcAdjustFrame; crtcPriv->video_init = SMI730_CrtcVideoInit; crtcPriv->load_lut = SMILynx_CrtcLoadLUT_crt; @@ -799,7 +888,12 @@ SMILynx_CrtcPreInit(ScrnInfoPtr pScrn) /* CRTC0 is LCD, but in standard refresh mode it is controlled through the primary VGA registers */ SMI_CrtcFuncsInit_base(&crtcFuncs, &crtcPriv); - crtcFuncs->mode_set = SMILynx_CrtcModeSet_vga; + + if(pSmi->useBIOS) + crtcFuncs->mode_set = SMILynx_CrtcModeSet_bios; + else + crtcFuncs->mode_set = SMILynx_CrtcModeSet_vga; + crtcPriv->adjust_frame = SMILynx_CrtcAdjustFrame; crtcPriv->video_init = SMILynx_CrtcVideoInit_crt; crtcPriv->load_lut = SMILynx_CrtcLoadLUT_crt; diff --git a/src/smilynx_hw.c b/src/smilynx_hw.c index 115a442..8d2c523 100644 --- a/src/smilynx_hw.c +++ b/src/smilynx_hw.c @@ -54,76 +54,78 @@ SMILynx_HWInit(ScrnInfoPtr pScrn) mode->SR17 &= ~0x20; } - /* Disable DAC and LCD framebuffer r/w operation */ - mode->SR21 |= 0xB0; + /* Gamma correction */ + if (pSmi->Chipset == SMI_LYNX3DM || pSmi->Chipset == SMI_COUGAR3DR) { + if(pScrn->bitsPerPixel == 8) + mode->SR66 = (mode->SR66 & 0x33) | 0x00; /* Both RAMLUT on, 6 bits-RAM */ + else + mode->SR66 = (mode->SR66 & 0x33) | 0x04; /* Both RAMLUT on, Gamma correct ON */ + } - /* Power down mode is standby mode, VCLK and MCLK divided by 4 in standby mode */ - mode->SR20 = (mode->SR20 & ~0xB0) | 0x10; + /* Program MCLK */ + if (pSmi->MCLK > 0) + SMI_CommonCalcClock(pScrn->scrnIndex, pSmi->MCLK, + 1, 1, 63, 0, 0, + pSmi->clockRange.minClock, + pSmi->clockRange.maxClock, + &mode->SR6A, &mode->SR6B); - /* Set DPMS state to Off */ - mode->SR22 |= 0x30; + if(!pSmi->useBIOS) { + /* Disable DAC and LCD framebuffer r/w operation */ + mode->SR21 |= 0xB0; - /* VESA compliance power down mode */ - mode->SR24 &= ~0x01; + /* Power down mode is standby mode, VCLK and MCLK divided by 4 in standby mode */ + mode->SR20 = (mode->SR20 & ~0xB0) | 0x10; - if (pSmi->Chipset != SMI_COUGAR3DR) { - /* Select no displays */ - mode->SR31 &= ~0x07; + /* Set DPMS state to Off */ + mode->SR22 |= 0x30; - /* Enable virtual refresh */ - if(pSmi->Dualhead){ - mode->SR31 |= 0x80; - }else{ - mode->SR31 &= ~0x80; - } + /* VESA compliance power down mode */ + mode->SR24 &= ~0x01; - /* Disable expansion */ - mode->SR32 &= ~0x03; - /* Enable autocentering */ - if (SMI_LYNXM_SERIES(pSmi->Chipset)) - mode->SR32 |= 0x04; - else - mode->SR32 &= ~0x04; + if (pSmi->Chipset != SMI_COUGAR3DR) { + /* Select no displays */ + mode->SR31 &= ~0x07; - if (pSmi->lcd == 2) /* Panel is DSTN */ - mode->SR21 = 0x00; + /* Enable virtual refresh */ + if(pSmi->Dualhead){ + mode->SR31 |= 0x80; + }else{ + mode->SR31 &= ~0x80; + } - /* Enable HW LCD power sequencing */ - mode->SR34 |= 0x80; - } + /* Disable expansion */ + mode->SR32 &= ~0x03; + /* Enable autocentering */ + if (SMI_LYNXM_SERIES(pSmi->Chipset)) + mode->SR32 |= 0x04; + else + mode->SR32 &= ~0x04; - /* Disable Vertical Expansion/Vertical Centering/Horizontal Centering */ - mode->CR90[0xE] &= ~0x7; + if (pSmi->lcd == 2) /* Panel is DSTN */ + mode->SR21 = 0x00; - /* Program MCLK */ - if (pSmi->MCLK > 0) - SMI_CommonCalcClock(pScrn->scrnIndex, pSmi->MCLK, - 1, 1, 63, 0, 0, - pSmi->clockRange.minClock, - pSmi->clockRange.maxClock, - &mode->SR6A, &mode->SR6B); + /* Enable HW LCD power sequencing */ + mode->SR34 |= 0x80; + } - /* use vclk1 */ - mode->SR68 = 0x54; + /* Disable Vertical Expansion/Vertical Centering/Horizontal Centering */ + mode->CR90[0xE] &= ~0x7; - if(pSmi->Dualhead){ - /* set LCD to vclk2 */ - mode->SR69 = 0x04; - } + /* use vclk1 */ + mode->SR68 = 0x54; - /* Gamma correction */ - if (pSmi->Chipset == SMI_LYNX3DM || pSmi->Chipset == SMI_COUGAR3DR) { - if(pScrn->bitsPerPixel == 8) - mode->SR66 = (mode->SR66 & 0x33) | 0x00; /* Both RAMLUT on, 6 bits-RAM */ - else - mode->SR66 = (mode->SR66 & 0x33) | 0x04; /* Both RAMLUT on, Gamma correct ON */ - } + if(pSmi->Dualhead){ + /* set LCD to vclk2 */ + mode->SR69 = 0x04; + } - /* Disable panel video */ - mode->SRA0 = 0; + /* Disable panel video */ + mode->SRA0 = 0; - mode->CR33 = 0; - mode->CR3A = 0; + mode->CR33 = 0; + mode->CR3A = 0; + } VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x17, mode->SR17); VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x20, mode->SR20); @@ -340,7 +342,30 @@ SMILynx_WriteMode(ScrnInfoPtr pScrn, vgaRegPtr vgaSavePtr, SMIRegPtr restore) ENTER(); - if (pSmi->useBIOS && pSmi->pInt10 != NULL && restore->mode != 0) { + VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x17, restore->SR17); + VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x18, restore->SR18); + + VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x20, restore->SR20); + VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x21, restore->SR21); + VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x22, restore->SR22); + VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x23, restore->SR23); + VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x24, restore->SR24); + + VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x31, restore->SR31); + VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x32, restore->SR32); + + VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x66, restore->SR66); + VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x68, restore->SR68); + VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x69, restore->SR69); + VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x6A, restore->SR6A); + VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x6B, restore->SR6B); + VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x6C, restore->SR6C); + VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x6D, restore->SR6D); + + VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x81, restore->SR81); + VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0xA0, restore->SRA0); + + if (pSmi->useBIOS && restore->mode != 0){ pSmi->pInt10->num = 0x10; pSmi->pInt10->ax = restore->mode | 0x80; xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Setting mode 0x%02X\n", @@ -356,29 +381,6 @@ SMILynx_WriteMode(ScrnInfoPtr pScrn, vgaRegPtr vgaSavePtr, SMIRegPtr restore) tmp = VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x21); VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x21, tmp & ~0x03); } else { - VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x17, restore->SR17); - VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x18, restore->SR18); - - VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x20, restore->SR20); - VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x21, restore->SR21); - VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x22, restore->SR22); - VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x23, restore->SR23); - VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x24, restore->SR24); - - VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x31, restore->SR31); - VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x32, restore->SR32); - - VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x66, restore->SR66); - VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x68, restore->SR68); - VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x69, restore->SR69); - VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x6A, restore->SR6A); - VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x6B, restore->SR6B); - VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x6C, restore->SR6C); - VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x6D, restore->SR6D); - - VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x81, restore->SR81); - VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0xA0, restore->SRA0); - /* Restore the standard VGA registers */ vgaHWRestore(pScrn, vgaSavePtr, VGA_SR_ALL); if (restore->smiDACMask) { diff --git a/src/smilynx_output.c b/src/smilynx_output.c index 4647cdd..4974d2c 100644 --- a/src/smilynx_output.c +++ b/src/smilynx_output.c @@ -119,6 +119,36 @@ SMILynx_OutputDPMS_lcd(xf86OutputPtr output, int mode) } +static void +SMILynx_OutputDPMS_bios(xf86OutputPtr output, int mode) +{ + ScrnInfoPtr pScrn = output->scrn; + SMIPtr pSmi = SMIPTR(pScrn); + + ENTER(); + + pSmi->pInt10->ax = 0x4F10; + switch (mode) { + case DPMSModeOn: + pSmi->pInt10->bx = 0x0001; + break; + case DPMSModeStandby: + pSmi->pInt10->bx = 0x0101; + break; + case DPMSModeSuspend: + pSmi->pInt10->bx = 0x0201; + break; + case DPMSModeOff: + pSmi->pInt10->bx = 0x0401; + break; + } + pSmi->pInt10->cx = 0x0000; + pSmi->pInt10->num = 0x10; + xf86ExecX86int10(pSmi->pInt10); + + LEAVE(); +} + static DisplayModePtr SMILynx_OutputGetModes_crt(xf86OutputPtr output) @@ -147,13 +177,6 @@ SMILynx_OutputGetModes_crt(xf86OutputPtr output) } } - /* Try DDC1 */ - pMon=SMILynx_ddc1(pScrn); - if(pMon){ - xf86OutputSetEDID(output,pMon); - LEAVE(xf86OutputGetEDIDModes(output)); - } - /* Try DDC2 */ if(pSmi->I2C){ pMon=xf86OutputGetEDID(output,pSmi->I2C); @@ -162,6 +185,13 @@ SMILynx_OutputGetModes_crt(xf86OutputPtr output) LEAVE(xf86OutputGetEDIDModes(output)); } } + + /* Try DDC1 */ + pMon=SMILynx_ddc1(pScrn); + if(pMon){ + xf86OutputSetEDID(output,pMon); + LEAVE(xf86OutputGetEDIDModes(output)); + } } LEAVE(NULL); @@ -255,7 +285,12 @@ SMILynx_OutputPreInit(ScrnInfoPtr pScrn) }else{ /* CRTC0 is LCD */ SMI_OutputFuncsInit_base(&outputFuncs); - outputFuncs->dpms = SMILynx_OutputDPMS_lcd; + + if(pSmi->useBIOS) + outputFuncs->dpms = SMILynx_OutputDPMS_bios; + else + outputFuncs->dpms = SMILynx_OutputDPMS_lcd; + outputFuncs->get_modes = SMI_OutputGetModes_native; outputFuncs->detect = SMI_OutputDetect_lcd; |