summaryrefslogtreecommitdiff
path: root/src/i830_raw.c
diff options
context:
space:
mode:
authorDave Airlie <airlied@linux.ie>2006-02-27 14:20:41 +1100
committerDave Airlie <airlied@linux.ie>2006-06-02 09:55:03 +1000
commitdb400cb0fa05ec7cf5337e9b849ec15968f745b1 (patch)
treee815bdaef1fa1b9e1b7a98fa06119ff30c590179 /src/i830_raw.c
parent3641648e14220c2d32c7fb8e3e386e9208b12a35 (diff)
i830: add basic single CRT raw mode setting
This ports over the intelfbhw.c which is MIT licenesed from the Linux kernel to the X driver at least allowing CRT mode setting
Diffstat (limited to 'src/i830_raw.c')
-rw-r--r--src/i830_raw.c677
1 files changed, 677 insertions, 0 deletions
diff --git a/src/i830_raw.c b/src/i830_raw.c
new file mode 100644
index 00000000..1e87d11a
--- /dev/null
+++ b/src/i830_raw.c
@@ -0,0 +1,677 @@
+/**************************************************************************
+
+ Copyright 2006 Dave Airlie <airlied@linux.ie>
+
+ Dervied from intelfhw.c licenesd under MIT/XFree86.
+ Copyright © 2002, 2003 David Dawes <dawes@xfree86.org>
+
+
+All Rights Reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the "Software"),
+to deal in the Software without restriction, including without limitation
+on the rights to use, copy, modify, merge, publish, distribute, sub
+license, and/or sell copies of the Software, and to permit persons to whom
+the Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice (including the next
+paragraph) shall be included in all copies or substantial portions of the
+Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+THE COPYRIGHT HOLDERS AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
+DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+**************************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "xf86.h"
+#include "xf86_ansic.h"
+#include "xf86_OSproc.h"
+#include "xf86Resources.h"
+#include "xf86RAC.h"
+#include "xf86cmap.h"
+#include "compiler.h"
+#include "mibstore.h"
+#include "vgaHW.h"
+#include "mipointer.h"
+#include "micmap.h"
+#include "shadowfb.h"
+#include <X11/extensions/randr.h>
+#include "fb.h"
+#include "miscstruct.h"
+#include "xf86xv.h"
+#include <X11/extensions/Xv.h>
+#include "shadow.h"
+#include "i830.h"
+
+
+#ifdef XF86DRI
+#include "dri.h"
+#endif
+
+#define ROUND_UP_TO(x, y) (((x) + (y) - 1) / (y) * (y))
+
+#define PIPE_A 0
+#define PIPE_B 1
+
+/* Split the M parameter into M1 and M2. */
+static int
+splitm(unsigned int m, CARD32 *retm1, CARD32 *retm2)
+{
+ int m1, m2;
+
+ m1 = (m - 2 - (MIN_M2 + MAX_M2) / 2) / 5 - 2;
+ if (m1 < MIN_M1)
+ m1 = MIN_M1;
+ if (m1 > MAX_M1)
+ m1 = MAX_M1;
+ m2 = m - 5 * (m1 + 2) - 2;
+ if (m2 < MIN_M2 || m2 > MAX_M2 || m2 >= m1) {
+ return 1;
+ } else {
+ *retm1 = (unsigned int)m1;
+ *retm2 = (unsigned int)m2;
+ return 0;
+ }
+}
+
+/* Split the P parameter into P1 and P2. */
+static int
+splitp(unsigned int p, CARD32 *retp1, CARD32 *retp2)
+{
+ int p1, p2;
+
+ if (p % 4 == 0)
+ p2 = 1;
+ else
+ p2 = 0;
+ p1 = (p / (1 << (p2 + 1))) - 2;
+ if (p % 4 == 0 && p1 < MIN_P1) {
+ p2 = 0;
+ p1 = (p / (1 << (p2 + 1))) - 2;
+ }
+ if (p1 < MIN_P1 || p1 > MAX_P1 || (p1 + 2) * (1 << (p2 + 1)) != p) {
+ return 1;
+ } else {
+ *retp1 = (unsigned int)p1;
+ *retp2 = (unsigned int)p2;
+ return 0;
+ }
+}
+
+static int
+calc_pll_params(int clock, CARD32 *retm1, CARD32 *retm2, CARD32 *retn, CARD32 *retp1,
+ CARD32 *retp2, CARD32 *retclock)
+{
+ CARD32 m1, m2, n, p1, p2, n1;
+ CARD32 f_vco, p, p_best = 0, m, f_out;
+ CARD32 err_max, err_target, err_best = 10000000;
+ CARD32 n_best = 0, m_best = 0, f_best, f_err;
+ CARD32 p_min, p_max, p_inc, div_min, div_max;
+
+ /* Accept 0.5% difference, but aim for 0.1% */
+ err_max = 5 * clock / 1000;
+ err_target = clock / 1000;
+
+ DPRINTF(PFX, "Clock is %d\n", clock);
+
+ div_max = MAX_VCO_FREQ / clock;
+ div_min = ROUND_UP_TO(MIN_VCO_FREQ, clock) / clock;
+
+ if (clock <= P_TRANSITION_CLOCK)
+ p_inc = 4;
+ else
+ p_inc = 2;
+ p_min = ROUND_UP_TO(div_min, p_inc);
+ p_max = ROUND_DOWN_TO(div_max, p_inc);
+ if (p_min < MIN_P)
+ p_min = 4;
+ if (p_max > MAX_P)
+ p_max = 128;
+
+ DPRINTF(PFX, "p range is %d-%d (%d)\n", p_min, p_max, p_inc);
+
+ p = p_min;
+ do {
+ if (splitp(p, &p1, &p2)) {
+ WRN_MSG("cannot split p = %d\n", p);
+ p += p_inc;
+ continue;
+ }
+ n = MIN_N;
+ f_vco = clock * p;
+
+ do {
+ m = ROUND_UP_TO(f_vco * n, PLL_REFCLK) / PLL_REFCLK;
+ if (m < MIN_M)
+ m = MIN_M;
+ if (m > MAX_M)
+ m = MAX_M;
+ f_out = CALC_VCLOCK3(m, n, p);
+ if (splitm(m, &m1, &m2)) {
+ WRN_MSG("cannot split m = %d\n", m);
+ n++;
+ continue;
+ }
+ if (clock > f_out)
+ f_err = clock - f_out;
+ else
+ f_err = f_out - clock;
+
+ if (f_err < err_best) {
+ m_best = m;
+ n_best = n;
+ p_best = p;
+ f_best = f_out;
+ err_best = f_err;
+ }
+ n++;
+ } while ((n <= MAX_N) && (f_out >= clock));
+ p += p_inc;
+ } while ((p <= p_max));
+
+ if (!m_best) {
+ WRN_MSG("cannot find parameters for clock %d\n", clock);
+ return 1;
+ }
+ m = m_best;
+ n = n_best;
+ p = p_best;
+ splitm(m, &m1, &m2);
+ splitp(p, &p1, &p2);
+ n1 = n - 2;
+
+ DPRINTF(PFX, "m, n, p: %d (%d,%d), %d (%d), %d (%d,%d), "
+ "f: %d (%d), VCO: %d\n",
+ m, m1, m2, n, n1, p, p1, p2,
+ CALC_VCLOCK3(m, n, p), CALC_VCLOCK(m1, m2, n1, p1, p2),
+ CALC_VCLOCK3(m, n, p) * p);
+ *retm1 = m1;
+ *retm2 = m2;
+ *retn = n1;
+ *retp1 = p1;
+ *retp2 = p2;
+ *retclock = CALC_VCLOCK(m1, m2, n1, p1, p2);
+
+ return 0;
+}
+
+static int
+check_overflow(ScrnInfoPtr pScrn, CARD32 value, CARD32 limit, const char *description)
+{
+ if (value > limit) {
+ xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+ "%s value %d exceeds limit %d\n",
+ description, value, limit);
+ return 1;
+ }
+ return 0;
+}
+
+/* It is assumed that hw is filled in with the initial state information. */
+int
+I830RawSetHw(ScrnInfoPtr pScrn, DisplayModePtr pMode)
+{
+ I830Ptr pI830 = I830PTR(pScrn);
+ I830RegPtr hw = &pI830->ModeReg;
+ int pipe = PIPE_A;
+ unsigned long Start;
+ CARD32 *dpll, *fp0, *fp1;
+ CARD32 m1, m2, n, p1, p2, clock_target, clock;
+ CARD32 hsync_start, hsync_end, hblank_start, hblank_end, htotal, hactive;
+ CARD32 vsync_start, vsync_end, vblank_start, vblank_end, vtotal, vactive;
+ CARD32 vsync_pol, hsync_pol;
+ CARD32 *vs, *vb, *vt, *hs, *hb, *ht, *ss, *pipe_conf;
+
+ /* Disable VGA */
+ hw->vgacntrl |= VGA_CNTRL_DISABLE;
+
+ /* Check whether pipe A or pipe B is enabled. */
+ if (hw->pipe_a_conf & PIPEACONF_ENABLE)
+ pipe = PIPE_A;
+ else if (hw->pipe_b_conf & PIPEBCONF_ENABLE)
+ pipe = PIPE_B;
+
+ /* Set which pipe's registers will be set. */
+ if (pipe == PIPE_B) {
+ dpll = &hw->dpll_b;
+ fp0 = &hw->fpb0;
+ fp1 = &hw->fpb1;
+ hs = &hw->hsync_b;
+ hb = &hw->hblank_b;
+ ht = &hw->htotal_b;
+ vs = &hw->vsync_b;
+ vb = &hw->vblank_b;
+ vt = &hw->vtotal_b;
+ ss = &hw->pipe_src_b;
+ pipe_conf = &hw->pipe_b_conf;
+ } else {
+ dpll = &hw->dpll_a;
+ fp0 = &hw->fpa0;
+ fp1 = &hw->fpa1;
+ hs = &hw->hsync_a;
+ hb = &hw->hblank_a;
+ ht = &hw->htotal_a;
+ vs = &hw->vsync_a;
+ vb = &hw->vblank_a;
+ vt = &hw->vtotal_a;
+ ss = &hw->pipe_src_a;
+ pipe_conf = &hw->pipe_a_conf;
+ }
+
+ /* Use ADPA register for sync control. */
+ hw->adpa &= ~ADPA_USE_VGA_HVPOLARITY;
+
+ /* sync polarity */
+ hsync_pol = (pMode->Flags & V_PHSYNC) ?
+ ADPA_HSYNC_ACTIVE_HIGH : ADPA_HSYNC_ACTIVE_LOW;
+ vsync_pol = (pMode->Flags & V_PVSYNC) ?
+ ADPA_VSYNC_ACTIVE_HIGH : ADPA_VSYNC_ACTIVE_LOW;
+ hw->adpa &= ~(ADPA_HSYNC_ACTIVE_HIGH | ADPA_VSYNC_ACTIVE_HIGH);
+ hw->adpa |= (hsync_pol | vsync_pol);
+
+ /* Connect correct pipe to the analog port DAC */
+ hw->adpa &= ~(ADPA_PIPE_SELECT_MASK);
+ hw->adpa |= (pipe==PIPE_B) ? ADPA_PIPE_B_SELECT : 0;
+
+ /* Set DPMS state to D0 (on) */
+ hw->adpa &= ~(ADPA_VSYNC_CNTL_DISABLE | ADPA_HSYNC_CNTL_DISABLE);
+ // hw->adpa |= ADPA_DPMS_D0;
+
+ hw->adpa |= ADPA_DAC_ENABLE;
+
+ *dpll |= (DPLL_VCO_ENABLE | DPLL_VGA_MODE_DISABLE);
+ *dpll &= ~(DPLL_RATE_SELECT_MASK | DPLL_REFERENCE_SELECT_MASK);
+ *dpll |= (DPLL_REFERENCE_DEFAULT | DPLL_RATE_SELECT_FP0);
+
+ /* Desired clock in kHz */
+ // clock_target = 1000000000 / var->pixclock;
+ clock_target = pMode->Clock;
+
+ if (calc_pll_params(clock_target, &m1, &m2, &n, &p1, &p2, &clock)) {
+ WRN_MSG("calc_pll_params failed\n");
+ return FALSE;
+ }
+
+ /* Check for overflow. */
+ if (check_overflow(pScrn, p1, DPLL_P1_MASK, "PLL P1 parameter"))
+ return FALSE;
+ if (check_overflow(pScrn, p2, DPLL_P2_MASK, "PLL P2 parameter"))
+ return FALSE;
+ if (check_overflow(pScrn, m1, FP_DIVISOR_MASK, "PLL M1 parameter"))
+ return FALSE;
+ if (check_overflow(pScrn, m2, FP_DIVISOR_MASK, "PLL M2 parameter"))
+ return FALSE;
+ if (check_overflow(pScrn, n, FP_DIVISOR_MASK, "PLL N parameter"))
+ return FALSE;
+
+ *dpll &= ~DPLL_P1_FORCE_DIV2;
+ *dpll &= ~((DPLL_P2_MASK << DPLL_P2_SHIFT) |
+ (DPLL_P1_MASK << DPLL_P1_SHIFT));
+ *dpll |= (p2 << DPLL_P2_SHIFT) | (p1 << DPLL_P1_SHIFT);
+ *fp0 = (n << FP_N_DIVISOR_SHIFT) |
+ (m1 << FP_M1_DIVISOR_SHIFT) |
+ (m2 << FP_M2_DIVISOR_SHIFT);
+ *fp1 = *fp0;
+
+ hw->dvob &= ~DVO_ENABLE;
+ hw->dvoc &= ~DVO_ENABLE;
+
+ /* Use display plane A. */
+ hw->disp_a_ctrl |= DISPLAY_PLANE_ENABLE;
+ hw->disp_a_ctrl &= ~DISPPLANE_GAMMA_ENABLE;
+ hw->disp_a_ctrl &= ~DISPPLANE_PIXFORMAT_MASK;
+ switch (pScrn->bitsPerPixel) {
+ case 8:
+ hw->disp_a_ctrl |= DISPPLANE_8BPP | DISPPLANE_GAMMA_ENABLE;
+ break;
+ case 15:
+ hw->disp_a_ctrl |= DISPPLANE_15_16BPP;
+ break;
+ case 16:
+ hw->disp_a_ctrl |= DISPPLANE_16BPP;
+ break;
+ case 24:
+ hw->disp_a_ctrl |= DISPPLANE_32BPP_NO_ALPHA;
+ break;
+ }
+ hw->disp_a_ctrl &= ~(DISPPLANE_SEL_PIPE_MASK);
+ hw->disp_a_ctrl |= (pipe == PIPE_B ? DISPPLANE_SEL_PIPE_B : DISPPLANE_SEL_PIPE_A);
+
+ /* Set CRTC registers. */
+ hactive = pMode->CrtcHBlankStart;
+ hsync_start = pMode->CrtcHSyncStart;
+ hsync_end = pMode->CrtcHSyncEnd;
+ htotal = pMode->CrtcHTotal;
+ hblank_start = pMode->CrtcHBlankStart;
+ hblank_end = pMode->CrtcHBlankEnd;
+
+ DPRINTF(PFX, "H: act %d, ss %d, se %d, tot %d bs %d, be %d\n",
+ hactive, hsync_start, hsync_end, htotal, hblank_start,
+ hblank_end);
+
+ vactive = pMode->CrtcVBlankStart;
+ vsync_start = pMode->CrtcVSyncStart;
+ vsync_end = pMode->CrtcVSyncEnd;
+ vtotal = pMode->CrtcVTotal;
+ vblank_start = pMode->CrtcVBlankStart;
+ vblank_end = pMode->CrtcVBlankEnd;
+
+ DPRINTF(PFX, "V: act %d, ss %d, se %d, tot %d bs %d, be %d\n",
+ vactive, vsync_start, vsync_end, vtotal, vblank_start,
+ vblank_end);
+
+ /* Adjust for register values, and check for overflow. */
+ hactive--;
+ if (check_overflow(pScrn, hactive, HACTIVE_MASK, "CRTC hactive"))
+ return FALSE;
+ hsync_start--;
+ if (check_overflow(pScrn, hsync_start, HSYNCSTART_MASK, "CRTC hsync_start"))
+ return FALSE;
+ hsync_end--;
+ if (check_overflow(pScrn, hsync_end, HSYNCEND_MASK, "CRTC hsync_end"))
+ return FALSE;
+ htotal--;
+ if (check_overflow(pScrn, htotal, HTOTAL_MASK, "CRTC htotal"))
+ return FALSE;
+ hblank_start--;
+ if (check_overflow(pScrn, hblank_start, HBLANKSTART_MASK, "CRTC hblank_start"))
+ return FALSE;
+ hblank_end--;
+ if (check_overflow(pScrn, hblank_end, HBLANKEND_MASK, "CRTC hblank_end"))
+ return FALSE;
+
+ vactive--;
+ if (check_overflow(pScrn, vactive, VACTIVE_MASK, "CRTC vactive"))
+ return FALSE;
+ vsync_start--;
+ if (check_overflow(pScrn, vsync_start, VSYNCSTART_MASK, "CRTC vsync_start"))
+ return FALSE;
+ vsync_end--;
+ if (check_overflow(pScrn, vsync_end, VSYNCEND_MASK, "CRTC vsync_end"))
+ return FALSE;
+ vtotal--;
+ if (check_overflow(pScrn, vtotal, VTOTAL_MASK, "CRTC vtotal"))
+ return FALSE;
+ vblank_start--;
+ if (check_overflow(pScrn, vblank_start, VBLANKSTART_MASK, "CRTC vblank_start"))
+ return FALSE;
+ vblank_end--;
+ if (check_overflow(pScrn, vblank_end, VBLANKEND_MASK, "CRTC vblank_end"))
+ return FALSE;
+
+ *ht = (htotal << HTOTAL_SHIFT) | (hactive << HACTIVE_SHIFT);
+ *hb = (hblank_start << HBLANKSTART_SHIFT) |
+ (hblank_end << HSYNCEND_SHIFT);
+ *hs = (hsync_start << HSYNCSTART_SHIFT) | (hsync_end << HSYNCEND_SHIFT);
+
+ *vt = (vtotal << VTOTAL_SHIFT) | (vactive << VACTIVE_SHIFT);
+ *vb = (vblank_start << VBLANKSTART_SHIFT) |
+ (vblank_end << VSYNCEND_SHIFT);
+ *vs = (vsync_start << VSYNCSTART_SHIFT) | (vsync_end << VSYNCEND_SHIFT);
+ *ss = (hactive << SRC_SIZE_HORIZ_SHIFT) |
+ (vactive << SRC_SIZE_VERT_SHIFT);
+
+ /* Set the palette to 8-bit mode. */
+ *pipe_conf &= ~PIPEACONF_GAMMA;
+ return TRUE;
+}
+
+/* Program a (non-VGA) video mode. */
+int
+I830ProgramModeReg(ScrnInfoPtr pScrn, DisplayModePtr pMode)
+{
+ I830Ptr pI830 = I830PTR(pScrn);
+ I830RegPtr hw = &pI830->ModeReg;
+ int pipe = PIPE_A;
+ CARD32 tmp;
+ const CARD32 *dpll, *fp0, *fp1, *pipe_conf;
+ const CARD32 *hs, *ht, *hb, *vs, *vt, *vb, *ss;
+ CARD32 dpll_reg, fp0_reg, fp1_reg, pipe_conf_reg;
+ CARD32 hsync_reg, htotal_reg, hblank_reg;
+ CARD32 vsync_reg, vtotal_reg, vblank_reg;
+ CARD32 pipe_src_reg;
+
+ /* Assume single pipe, display plane A, analog CRT. */
+
+ /* Disable VGA */
+ tmp = INREG(VGACNTRL);
+ tmp |= VGA_CNTRL_DISABLE;
+ OUTREG(VGACNTRL, tmp);
+
+ /* Check whether pipe A or pipe B is enabled. */
+ if (hw->pipe_a_conf & PIPEACONF_ENABLE)
+ pipe = PIPE_A;
+ else if (hw->pipe_b_conf & PIPEBCONF_ENABLE)
+ pipe = PIPE_B;
+
+ if (pipe == PIPE_B) {
+ dpll = &hw->dpll_b;
+ fp0 = &hw->fpb0;
+ fp1 = &hw->fpb1;
+ pipe_conf = &hw->pipe_b_conf;
+ hs = &hw->hsync_b;
+ hb = &hw->hblank_b;
+ ht = &hw->htotal_b;
+ vs = &hw->vsync_b;
+ vb = &hw->vblank_b;
+ vt = &hw->vtotal_b;
+ ss = &hw->pipe_src_b;
+ dpll_reg = DPLL_B;
+ fp0_reg = FPB0;
+ fp1_reg = FPB1;
+ pipe_conf_reg = PIPEBCONF;
+ hsync_reg = HSYNC_B;
+ htotal_reg = HTOTAL_B;
+ hblank_reg = HBLANK_B;
+ vsync_reg = VSYNC_B;
+ vtotal_reg = VTOTAL_B;
+ vblank_reg = VBLANK_B;
+ pipe_src_reg = PIPEBSRC;
+ } else {
+ dpll = &hw->dpll_a;
+ fp0 = &hw->fpa0;
+ fp1 = &hw->fpa1;
+ pipe_conf = &hw->pipe_a_conf;
+ hs = &hw->hsync_a;
+ hb = &hw->hblank_a;
+ ht = &hw->htotal_a;
+ vs = &hw->vsync_a;
+ vb = &hw->vblank_a;
+ vt = &hw->vtotal_a;
+ ss = &hw->pipe_src_a;
+ dpll_reg = DPLL_A;
+ fp0_reg = FPA0;
+ fp1_reg = FPA1;
+ pipe_conf_reg = PIPEACONF;
+ hsync_reg = HSYNC_A;
+ htotal_reg = HTOTAL_A;
+ hblank_reg = HBLANK_A;
+ vsync_reg = VSYNC_A;
+ vtotal_reg = VTOTAL_A;
+ vblank_reg = VBLANK_A;
+ pipe_src_reg = PIPEASRC;
+ }
+
+ /* Disable planes A and B. */
+ tmp = INREG(DSPACNTR);
+ tmp &= ~DISPLAY_PLANE_ENABLE;
+ OUTREG(DSPACNTR, tmp);
+ tmp = INREG(DSPBCNTR);
+ tmp &= ~DISPLAY_PLANE_ENABLE;
+ OUTREG(DSPBCNTR, tmp);
+
+ /* Wait for vblank. For now, just wait for a 50Hz cycle (20ms)) */
+ usleep(20000);
+
+ /* Disable Sync */
+ tmp = INREG(ADPA);
+ tmp &= ~(ADPA_VSYNC_CNTL_DISABLE | ADPA_HSYNC_CNTL_DISABLE);
+ tmp |= ADPA_VSYNC_CNTL_DISABLE | ADPA_HSYNC_CNTL_DISABLE;
+ OUTREG(ADPA, tmp);
+
+ /* turn off pipe */
+ tmp = INREG(pipe_conf_reg);
+ tmp &= ~PIPEACONF_ENABLE;
+ OUTREG(pipe_conf_reg, tmp);
+
+ /* turn off PLL */
+ tmp = INREG(dpll_reg);
+ dpll_reg &= ~DPLL_VCO_ENABLE;
+ OUTREG(dpll_reg, tmp);
+
+ /* Set PLL parameters */
+ OUTREG(dpll_reg, *dpll & ~DPLL_VCO_ENABLE);
+ OUTREG(fp0_reg, *fp0);
+ OUTREG(fp1_reg, *fp1);
+
+ /* Set pipe parameters */
+ OUTREG(hsync_reg, *hs);
+ OUTREG(hblank_reg, *hb);
+ OUTREG(htotal_reg, *ht);
+ OUTREG(vsync_reg, *vs);
+ OUTREG(vblank_reg, *vb);
+ OUTREG(vtotal_reg, *vt);
+ OUTREG(pipe_src_reg, *ss);
+
+ /* Set DVOs B/C */
+ OUTREG(DVOB, hw->dvob);
+ OUTREG(DVOC, hw->dvoc);
+
+ /* Set ADPA */
+ OUTREG(ADPA, (hw->adpa & ~(ADPA_VSYNC_CNTL_DISABLE|ADPA_HSYNC_CNTL_DISABLE)) | (ADPA_VSYNC_CNTL_DISABLE|ADPA_HSYNC_CNTL_DISABLE));
+
+ /* Enable PLL */
+ tmp = INREG(dpll_reg);
+ tmp |= DPLL_VCO_ENABLE;
+ OUTREG(dpll_reg, tmp);
+
+ /* Enable pipe */
+ OUTREG(pipe_conf_reg, *pipe_conf | PIPEACONF_ENABLE);
+
+ /* Enable sync */
+ tmp = INREG(ADPA);
+ tmp &= ~(ADPA_VSYNC_CNTL_DISABLE|ADPA_HSYNC_CNTL_DISABLE);
+ // tmp |= ADPA_DPMS_D0;
+ OUTREG(ADPA, tmp);
+#if 0
+ /* setup display plane */
+ if (dinfo->pdev->device == PCI_DEVICE_ID_INTEL_830M) {
+ /*
+ * i830M errata: the display plane must be enabled
+ * to allow writes to the other bits in the plane
+ * control register.
+ */
+ tmp = INREG(DSPACNTR);
+ if ((tmp & DISPLAY_PLANE_ENABLE) != DISPLAY_PLANE_ENABLE) {
+ tmp |= DISPLAY_PLANE_ENABLE;
+ OUTREG(DSPACNTR, tmp);
+ OUTREG(DSPACNTR,
+ hw->disp_a_ctrl|DISPLAY_PLANE_ENABLE);
+ usleep(1000);
+ }
+ }
+#endif
+
+ I830SetupDSPRegisters(pScrn, pMode);
+
+ return TRUE;
+}
+
+Bool
+I830RawSaveState(ScrnInfoPtr pScrn, I830RegPtr hw)
+{
+ I830Ptr pI830 = I830PTR(pScrn);
+
+ hw->vga0_divisor = INREG(VCLK_DIVISOR_VGA0);
+ hw->vga1_divisor = INREG(VCLK_DIVISOR_VGA1);
+ hw->vga_pd = INREG(VCLK_POST_DIV);
+
+ hw->dpll_a = INREG(DPLL_A);
+ hw->dpll_b = INREG(DPLL_B);
+ hw->fpa0 = INREG(FPA0);
+ hw->fpa1 = INREG(FPA1);
+ hw->fpb0 = INREG(FPB0);
+ hw->fpb1 = INREG(FPB1);
+
+ hw->htotal_a = INREG(HTOTAL_A);
+ hw->hblank_a = INREG(HBLANK_A);
+ hw->hsync_a = INREG(HSYNC_A);
+ hw->vtotal_a = INREG(VTOTAL_A);
+ hw->vblank_a = INREG(VBLANK_A);
+ hw->vsync_a = INREG(VSYNC_A);
+ hw->pipe_src_a = INREG(PIPEASRC);
+ hw->bclrpat_a = INREG(BCLRPAT_A);
+ hw->htotal_b = INREG(HTOTAL_B);
+ hw->hblank_b = INREG(HBLANK_B);
+ hw->hsync_b = INREG(HSYNC_B);
+ hw->vtotal_b = INREG(VTOTAL_B);
+ hw->vblank_b = INREG(VBLANK_B);
+ hw->vsync_b = INREG(VSYNC_B);
+ hw->pipe_src_b = INREG(PIPEBSRC);
+ hw->bclrpat_b = INREG(BCLRPAT_B);
+
+ hw->dvoa = INREG(DVOA);
+ hw->dvob = INREG(DVOB);
+ hw->dvoc = INREG(DVOC);
+ hw->dvoa_srcdim = INREG(DVOA_SRCDIM);
+ hw->dvob_srcdim = INREG(DVOB_SRCDIM);
+ hw->dvoc_srcdim = INREG(DVOC_SRCDIM);
+ hw->lvds = INREG(LVDS);
+
+
+ hw->pipe_a_conf = INREG(PIPEACONF);
+ hw->pipe_b_conf = INREG(PIPEBCONF);
+ hw->disp_arb = INREG(DISPLAY_ARB);
+
+
+ hw->disp_a_ctrl = INREG(DSPACNTR);
+ hw->disp_b_ctrl = INREG(DSPBCNTR);
+ hw->disp_a_base = INREG(DSPABASE);
+ hw->disp_b_base = INREG(DSPBBASE);
+ hw->disp_a_stride = INREG(DSPASTRIDE);
+ hw->disp_b_stride = INREG(DSPBSTRIDE);
+
+ hw->add_id = INREG(ADD_ID);
+
+ hw->vgacntrl = INREG(VGACNTRL);
+}
+
+
+Bool
+I830RawSwitchMode(int scrnIndex, DisplayModePtr mode, int flags)
+{
+
+ xf86DrvMsg(scrnIndex, X_ERROR,
+ "called raw switch mode\n");
+ ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
+ if (I830RawSetHw(pScrn, mode))
+ I830ProgramModeReg(pScrn, mode);
+
+
+ return 0;
+
+}
+
+Bool
+I830RawSetMode(ScrnInfoPtr pScrn, DisplayModePtr mode)
+{
+ int ret;
+ DPRINTF(PFX, "RawSetMode");
+
+ I830RawSetHw(pScrn, mode);
+ ret=I830ProgramModeReg(pScrn, mode);
+
+ I830DumpModeDebugInfo(pScrn);
+ return ret;
+
+}