summaryrefslogtreecommitdiff
path: root/src/smi_501.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/smi_501.c')
-rw-r--r--src/smi_501.c372
1 files changed, 55 insertions, 317 deletions
diff --git a/src/smi_501.c b/src/smi_501.c
index 4e78a75..63d704f 100644
--- a/src/smi_501.c
+++ b/src/smi_501.c
@@ -31,6 +31,7 @@ authorization from The XFree86 Project or Silicon Motion.
#endif
#include "smi.h"
+#include "smi_crtc.h"
#include "smi_501.h"
#include "regsmi.h"
@@ -45,15 +46,8 @@ authorization from The XFree86 Project or Silicon Motion.
/*
* Prototypes
*/
-static void SMI501_ModeSet(ScrnInfoPtr pScrn, MSOCRegPtr mode);
-static char *format_integer_base2(int32_t word);
-static double SMI501_FindClock(double clock, int max_divider, Bool has1xclck,
- int32_t *x2_1xclck, int32_t *x2_select,
- int32_t *x2_divider, int32_t *x2_shift);
-static double SMI501_FindPLLClock(double clock, int32_t *m, int32_t *n,
- int32_t *xclck);
-static void SMI501_PrintRegs(ScrnInfoPtr pScrn);
+static char *format_integer_base2(int32_t word);
static void SMI501_SetClock(SMIPtr pSmi, int32_t port,
int32_t pll, int32_t value);
static void SMI501_WaitVSync(SMIPtr pSmi, int vsync_count);
@@ -62,72 +56,6 @@ static void SMI501_WaitVSync(SMIPtr pSmi, int vsync_count);
/*
* Implemementation
*/
-Bool
-SMI501_EnterVT(int scrnIndex, int flags)
-{
- ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
- SMIPtr pSmi = SMIPTR(pScrn);
- Bool result;
-
- /* Enable MMIO and map memory */
- SMI_MapMem(pScrn);
-
- pSmi->Save(pScrn);
-
- /* FBBase may have changed after remapping the memory */
- pScrn->pixmapPrivate.ptr = pSmi->FBBase;
- if(pSmi->useEXA)
- pSmi->EXADriverPtr->memoryBase = pSmi->FBBase;
-
- /* #670 */
- if (pSmi->shadowFB) {
- pSmi->FBOffset = pSmi->savedFBOffset;
- pSmi->FBReserved = pSmi->savedFBReserved;
- }
-
- result = pSmi->ModeInit(pScrn, pScrn->currentMode);
-
- if (result && pSmi->shadowFB) {
- BoxRec box;
-
- if (pSmi->pSaveBuffer) {
- memcpy(pSmi->FBBase, pSmi->pSaveBuffer, pSmi->saveBufferSize);
- xfree(pSmi->pSaveBuffer);
- pSmi->pSaveBuffer = NULL;
- }
-
- box.x1 = 0;
- box.y1 = 0;
- box.x2 = pSmi->width;
- box.y2 = pSmi->height;
- SMI_RefreshArea(pScrn, 1, &box);
- }
-
- /* Reset the grapics engine */
- if (!pSmi->NoAccel)
- SMI_EngineReset(pScrn);
-
- return (result);
-}
-
-void
-SMI501_LeaveVT(int scrnIndex, int flags)
-{
- ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
- SMIPtr pSmi = SMIPTR(pScrn);
-
- if (pSmi->shadowFB) {
- pSmi->pSaveBuffer = xnfalloc(pSmi->saveBufferSize);
- if (pSmi->pSaveBuffer)
- memcpy(pSmi->pSaveBuffer, pSmi->FBBase, pSmi->saveBufferSize);
-
- pSmi->savedFBOffset = pSmi->FBOffset;
- pSmi->savedFBReserved = pSmi->FBReserved;
- }
-
- memset(pSmi->FBBase, 0, 256 * 1024);
- SMI_UnmapMem(pScrn);
-}
void
SMI501_Save(ScrnInfoPtr pScrn)
@@ -204,57 +132,25 @@ SMI501_DisplayPowerManagementSet(ScrnInfoPtr pScrn,
int PowerManagementMode, int flags)
{
SMIPtr pSmi = SMIPTR(pScrn);
- MSOCRegPtr mode = pSmi->mode;
if (pSmi->CurrentDPMS != PowerManagementMode) {
- mode->system_ctl.value = READ_SCR(pSmi, SYSTEM_CTL);
- switch (PowerManagementMode) {
- case DPMSModeOn:
- mode->system_ctl.f.dpmsh = 1;
- mode->system_ctl.f.dpmsv = 1;
- break;
- case DPMSModeStandby:
- mode->system_ctl.f.dpmsh = 0;
- mode->system_ctl.f.dpmsv = 1;
- break;
- case DPMSModeSuspend:
- mode->system_ctl.f.dpmsh = 1;
- mode->system_ctl.f.dpmsv = 0;
- break;
- case DPMSModeOff:
- mode->system_ctl.f.dpmsh = 0;
- mode->system_ctl.f.dpmsv = 0;
- break;
- }
- WRITE_SCR(pSmi, SYSTEM_CTL, mode->system_ctl.value);
+ /* Set the DPMS mode to every output and CRTC */
+ xf86DPMSSet(pScrn, PowerManagementMode, flags);
+
pSmi->CurrentDPMS = PowerManagementMode;
}
}
Bool
-SMI501_ModeInit(ScrnInfoPtr pScrn, DisplayModePtr xf86mode)
+SMI501_HWInit(ScrnInfoPtr pScrn)
{
MSOCRegPtr save;
MSOCRegPtr mode;
SMIPtr pSmi = SMIPTR(pScrn);
- double p2_diff, pll_diff;
- int32_t x2_select, x2_divider, x2_shift, x2_1xclck, p2_pll;
save = pSmi->save;
mode = pSmi->mode;
- pSmi->Bpp = pScrn->bitsPerPixel / 8;
- if (pSmi->rotate) {
- pSmi->width = pScrn->virtualY;
- pSmi->height = pScrn->virtualX;
- pSmi->Stride = (pSmi->height * pSmi->Bpp + 15) & ~15;
- }
- else {
- pSmi->width = pScrn->virtualX;
- pSmi->height = pScrn->virtualY;
- pSmi->Stride = (pSmi->width * pSmi->Bpp + 15) & ~15;
- }
-
/* Start with a fresh copy of registers before any mode change */
memcpy(mode, save, sizeof(MSOCRegRec));
@@ -310,165 +206,21 @@ SMI501_ModeInit(ScrnInfoPtr pScrn, DisplayModePtr xf86mode)
break;
}
- if (pSmi->lcd) {
- /* P2CLK have dividers 1, 3 and 5 */
- xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, VERBLEV,
- "Clock request %5.2f (max_divider %d)\n",
- (double)xf86mode->Clock, 5);
- p2_diff = SMI501_FindClock(xf86mode->Clock, 5,
- (uint32_t)mode->device_id.f.revision >= 0xc0,
- &x2_1xclck, &x2_select, &x2_divider,
- &x2_shift);
- mode->clock.f.p2_select = x2_select;
- mode->clock.f.p2_divider = x2_divider;
- mode->clock.f.p2_shift = x2_shift;
- mode->clock.f.p2_1xclck = x2_1xclck;
-
- /* Check if it is a SMI 502 */
- /* FIXME May need to add a Boolean option here, (or use extra
- * xorg.conf options?) to force it to not use 502 mode set. */
- if ((uint32_t)mode->device_id.f.revision >= 0xc0) {
- int32_t m, n, xclck;
-
- pll_diff = SMI501_FindPLLClock(xf86mode->Clock, &m, &n, &xclck);
- if (pll_diff < p2_diff) {
-
- /* FIXME Need to clarify. This is required for the GDIUM,
- * but based on the sample smi source code, it is not
- * always required to set this field to 1. */
- mode->clock.f.p2_1xclck = 1;
-
- mode->clock.f.pll_select = 1;
- mode->pll_ctl.f.m = m;
- mode->pll_ctl.f.n = n;
-
- /* 0: Crystal input
- * 1: Test clock input */
- mode->pll_ctl.f.select = 0;
-
- /* 0: pll output divided by 1
- * 1: pll output divided by 2 */
- mode->pll_ctl.f.divider = xclck != 1;
- mode->pll_ctl.f.power = 1;
- }
- else
- mode->clock.f.pll_select = 0;
- }
- else
- mode->clock.f.pll_select = 0;
-
- mode->panel_display_ctl.f.format =
- pScrn->bitsPerPixel == 8 ? 0 :
- pScrn->bitsPerPixel == 16 ? 1 : 2;
-
- mode->panel_display_ctl.f.enable = 1;
- mode->panel_display_ctl.f.timing = 1;
-
- /* FIXME if non clone dual head, and secondary, need to
- * properly set panel fb address properly ... */
- mode->panel_fb_address.f.address = 0;
- mode->panel_fb_address.f.mextern = 0; /* local memory */
- mode->panel_fb_address.f.pending = 0; /* FIXME required? */
-
- /* >> 4 because of the "unused bits" that should be set to 0 */
- /* FIXME this should be used for virtual size? */
- mode->panel_fb_width.f.offset = pSmi->Stride >> 4;
- mode->panel_fb_width.f.width = pSmi->Stride >> 4;
-
- mode->panel_wwidth.f.x = 0;
- mode->panel_wwidth.f.width = xf86mode->HDisplay;
-
- mode->panel_wheight.f.y = 0;
- mode->panel_wheight.f.height = xf86mode->VDisplay;
-
- mode->panel_plane_tl.f.top = 0;
- mode->panel_plane_tl.f.left = 0;
-
- mode->panel_plane_br.f.right = xf86mode->HDisplay - 1;
- mode->panel_plane_br.f.bottom = xf86mode->VDisplay - 1;
-
- /* 0 means pulse high */
- mode->panel_display_ctl.f.hsync = !(xf86mode->Flags & V_PHSYNC);
- mode->panel_display_ctl.f.vsync = !(xf86mode->Flags & V_PVSYNC);
- mode->panel_htotal.f.total = xf86mode->HTotal - 1;
- mode->panel_htotal.f.end = xf86mode->HDisplay - 1;
-
- mode->panel_hsync.f.start = xf86mode->HSyncStart;
- mode->panel_hsync.f.width = xf86mode->HSyncEnd -
- xf86mode->HSyncStart;
-
- mode->panel_vtotal.f.total = xf86mode->VTotal - 1;
- mode->panel_vtotal.f.end = xf86mode->VDisplay - 1;
-
- mode->panel_vsync.f.start = xf86mode->VSyncStart;
- mode->panel_vsync.f.height = xf86mode->VSyncEnd -
- xf86mode->VSyncStart;
- }
- else {
- /* V2CLK have dividers 1 and 3 */
- xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, VERBLEV,
- "Clock request %5.2f (max_divider %d)\n",
- (double)xf86mode->Clock, 3);
- (void)SMI501_FindClock(xf86mode->Clock, 3,
- (uint32_t)mode->device_id.f.revision >= 0xc0,
- &x2_1xclck, &x2_select, &x2_divider, &x2_shift);
- mode->clock.f.v2_select = x2_select;
- mode->clock.f.v2_divider = x2_divider;
- mode->clock.f.v2_shift = x2_shift;
- mode->clock.f.v2_1xclck = x2_1xclck;
-
- mode->crt_display_ctl.f.format =
- pScrn->bitsPerPixel == 8 ? 0 :
- pScrn->bitsPerPixel == 16 ? 1 : 2;
-
- /* 0: select panel - 1: select crt */
- mode->crt_display_ctl.f.select = 1;
+ /* FIXME: No dual head setup, and in this case, crt may
+ * just be another panel */
+ /* crt clones panel */
mode->crt_display_ctl.f.enable = 1;
+ /* 0: select panel - 1: select crt */
+ mode->crt_display_ctl.f.select = 0;
- /* FIXME if non clone dual head, and secondary, need to
- * properly set crt fb address ... */
- mode->crt_fb_address.f.address = 0;
- mode->crt_fb_address.f.mextern = 0; /* local memory */
- mode->crt_fb_address.f.pending = 0; /* FIXME required? */
-
- /* >> 4 because of the "unused bits" that should be set to 0 */
- /* FIXME this should be used for virtual size? */
- mode->crt_fb_width.f.offset = pSmi->Stride >> 4;
- mode->crt_fb_width.f.width = pSmi->Stride >> 4;
-
- /* 0 means pulse high */
- mode->crt_display_ctl.f.hsync = !(xf86mode->Flags & V_PHSYNC);
- mode->crt_display_ctl.f.vsync = !(xf86mode->Flags & V_PVSYNC);
-
- mode->crt_htotal.f.total = xf86mode->HTotal - 1;
- mode->crt_htotal.f.end = xf86mode->HDisplay - 1;
-
- mode->crt_hsync.f.start = xf86mode->HSyncStart;
- mode->crt_hsync.f.width = xf86mode->HSyncEnd -
- xf86mode->HSyncStart;
-
- mode->crt_vtotal.f.total = xf86mode->VTotal - 1;
- mode->crt_vtotal.f.end = xf86mode->VDisplay - 1;
-
- mode->crt_vsync.f.start = xf86mode->HSyncStart;
- mode->crt_vsync.f.height = xf86mode->HSyncEnd -
- xf86mode->HSyncStart;
- }
-
- SMI501_ModeSet(pScrn, mode);
-
- SMI_AdjustFrame(pScrn->scrnIndex, pScrn->frameX0, pScrn->frameY0, 0);
-
- xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, VERBLEV,
- "Register dump (After Mode Init)\n");
- SMI501_PrintRegs(pScrn);
+ SMI501_WriteMode_common(pScrn, mode);
return (TRUE);
}
-static void
-SMI501_ModeSet(ScrnInfoPtr pScrn, MSOCRegPtr mode)
+void
+SMI501_WriteMode_common(ScrnInfoPtr pScrn, MSOCRegPtr mode)
{
int32_t pll;
MSOCClockRec clock;
@@ -491,7 +243,29 @@ SMI501_ModeSet(ScrnInfoPtr pScrn, MSOCRegPtr mode)
clock.f.m1_shift = mode->clock.f.m1_shift;
SMI501_SetClock(pSmi, mode->current_clock, pll, clock.value);
- if (pSmi->lcd) {
+ WRITE_SCR(pSmi, MISC_CTL, mode->misc_ctl.value);
+
+ WRITE_SCR(pSmi, POWER_CTL, mode->power_ctl.value);
+
+ /* Match configuration */
+ /* FIXME some other fields should also be set, otherwise, since
+ * neither kernel nor driver change it, a reboot is required to
+ * modify or reset to default */
+ mode->system_ctl.f.burst = mode->system_ctl.f.burst_read =
+ pSmi->PCIBurst != FALSE;
+ mode->system_ctl.f.retry = pSmi->PCIRetry != FALSE;
+ WRITE_SCR(pSmi, SYSTEM_CTL, mode->system_ctl.value);
+
+ WRITE_SCR(pSmi, CRT_DISPLAY_CTL, mode->crt_display_ctl.value);
+}
+
+void
+SMI501_WriteMode_lcd(ScrnInfoPtr pScrn, MSOCRegPtr mode)
+{
+ int32_t pll;
+ MSOCClockRec clock;
+ SMIPtr pSmi = SMIPTR(pScrn);
+
/* Alternate pll_select is only available for the SMI 502,
* and the bit should be only set in that case. */
if (mode->clock.f.pll_select)
@@ -503,19 +277,7 @@ SMI501_ModeSet(ScrnInfoPtr pScrn, MSOCRegPtr mode)
clock.f.pll_select = mode->clock.f.pll_select;
clock.f.p2_1xclck = mode->clock.f.p2_1xclck;
SMI501_SetClock(pSmi, mode->current_clock, pll, clock.value);
- }
- else {
- clock.f.v2_select = mode->clock.f.v2_select;
- pll = clock.value;
- clock.f.v2_divider = mode->clock.f.v2_divider;
- clock.f.v2_shift = mode->clock.f.v2_shift;
- clock.f.v2_1xclck = mode->clock.f.v2_1xclck;
- SMI501_SetClock(pSmi, mode->current_clock, pll, clock.value);
- }
- WRITE_SCR(pSmi, MISC_CTL, mode->misc_ctl.value);
-
- if (pSmi->lcd) {
WRITE_SCR(pSmi, PANEL_FB_ADDRESS, mode->panel_fb_address.value);
WRITE_SCR(pSmi, PANEL_FB_WIDTH, mode->panel_fb_width.value);
@@ -547,16 +309,22 @@ SMI501_ModeSet(ScrnInfoPtr pScrn, MSOCRegPtr mode)
mode->panel_display_ctl.f.fp = 1;
WRITE_SCR(pSmi, PANEL_DISPLAY_CTL, mode->panel_display_ctl.value);
SMI501_WaitVSync(pSmi, 4);
-
- /* FIXME: No dual head setup, and in this case, crt may
- * just be another panel */
- /* crt clones panel */
- mode->crt_display_ctl.f.enable = 1;
- /* 0: select panel - 1: select crt */
- mode->crt_display_ctl.f.select = 0;
- WRITE_SCR(pSmi, CRT_DISPLAY_CTL, mode->crt_display_ctl.value);
}
- else {
+
+void
+SMI501_WriteMode_crt(ScrnInfoPtr pScrn, MSOCRegPtr mode)
+{
+ int32_t pll;
+ MSOCClockRec clock;
+ SMIPtr pSmi = SMIPTR(pScrn);
+
+ clock.f.v2_select = mode->clock.f.v2_select;
+ pll = clock.value;
+ clock.f.v2_divider = mode->clock.f.v2_divider;
+ clock.f.v2_shift = mode->clock.f.v2_shift;
+ clock.f.v2_1xclck = mode->clock.f.v2_1xclck;
+ SMI501_SetClock(pSmi, mode->current_clock, pll, clock.value);
+
WRITE_SCR(pSmi, CRT_FB_ADDRESS, mode->crt_fb_address.value);
WRITE_SCR(pSmi, CRT_FB_WIDTH, mode->crt_fb_width.value);
WRITE_SCR(pSmi, CRT_HTOTAL, mode->crt_htotal.value);
@@ -564,36 +332,6 @@ SMI501_ModeSet(ScrnInfoPtr pScrn, MSOCRegPtr mode)
WRITE_SCR(pSmi, CRT_VTOTAL, mode->crt_vtotal.value);
WRITE_SCR(pSmi, CRT_VSYNC, mode->crt_vsync.value);
WRITE_SCR(pSmi, CRT_DISPLAY_CTL, mode->crt_display_ctl.value);
-
- /* Turn CRT on */
- SMI501_DisplayPowerManagementSet(pScrn, DPMSModeOn, 0);
- }
-
- WRITE_SCR(pSmi, POWER_CTL, mode->power_ctl.value);
-
- /* Match configuration */
- /* FIXME some other fields should also be set, otherwise, since
- * neither kernel nor driver change it, a reboot is required to
- * modify or reset to default */
- mode->system_ctl.f.burst = mode->system_ctl.f.burst_read =
- pSmi->PCIBurst != FALSE;
- mode->system_ctl.f.retry = pSmi->PCIRetry != FALSE;
- WRITE_SCR(pSmi, SYSTEM_CTL, mode->system_ctl.value);
-}
-
-void
-SMI501_LoadPalette(ScrnInfoPtr pScrn, int numColors, int *indices,
- LOCO *colors, VisualPtr pVisual)
-{
- SMIPtr pSmi = SMIPTR(pScrn);
- int i, port;
-
- port = pSmi->IsSecondary ? CRT_PALETTE : PANEL_PALETTE;
- for (i = 0; i < numColors; i++)
- WRITE_SCR(pSmi, port + (indices[i] << 2),
- (colors[indices[i]].red << 16) |
- (colors[indices[i]].green << 8) |
- colors[indices[i]].blue);
}
static char *
@@ -612,7 +350,7 @@ format_integer_base2(int32_t word)
return (buffer);
}
-static double
+double
SMI501_FindClock(double clock, int32_t max_divider, Bool has1xclck,
int32_t *x2_1xclck,
int32_t *x2_select, int32_t *x2_divider, int32_t *x2_shift)
@@ -659,7 +397,7 @@ SMI501_FindClock(double clock, int32_t max_divider, Bool has1xclck,
return (best);
}
-static double
+double
SMI501_FindPLLClock(double clock, int32_t *m, int32_t *n, int32_t *xclck)
{
int32_t M, N, K;
@@ -718,7 +456,7 @@ SMI501_FindPLLClock(double clock, int32_t *m, int32_t *n, int32_t *xclck)
return (best);
}
-static void
+void
SMI501_PrintRegs(ScrnInfoPtr pScrn)
{
int i;