Merge branch 'restructure-outputs' into modesetting.

Outputs and Crtcs now have a driver-independent representation which should
permit generic code to control RandR 1.2 and startup configuration.
This commit is contained in:
Keith Packard 2006-11-30 14:09:31 -08:00
commit ff64bc7397
22 changed files with 1720 additions and 1015 deletions

View File

@ -82,6 +82,8 @@ i810_drv_la_SOURCES = \
i830_xf86Modes.h \
i830_xf86Modes.c \
i830_xf86cvt.c \
i830_xf86Crtc.h \
i830_xf86Crtc.c \
i915_3d.c \
i915_3d.h \
i915_reg.h \

View File

@ -1103,6 +1103,7 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
* This is used for load detection in combination with TVDAC_SENSE_MASK
*/
# define TV_TEST_MODE_MONITOR_DETECT (7 << 0)
# define TV_TEST_MODE_MASK (7 << 0)
/** @} */
/** @defgroup TV_DAC

View File

@ -58,7 +58,8 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#include "xf86int10.h"
#include "vbe.h"
#include "vgaHW.h"
#include "randrstr.h"
#include "i830_xf86Crtc.h"
#include "i830_randr.h"
#ifdef XF86DRI
#include "xf86drm.h"
@ -197,99 +198,24 @@ enum detect_status {
OUTPUT_STATUS_UNKNOWN
};
struct _I830OutputRec {
int type;
int pipe;
Bool enabled;
/**
* Marks that the output and associated pipe is temporarily enabled for
* load detection.
*/
Bool load_detect_temp;
typedef struct _I830CrtcPrivateRec {
int pipe;
Bool gammaEnabled;
} I830CrtcPrivateRec, *I830CrtcPrivatePtr;
/**
* Turns the output on/off, or sets intermediate power levels if available.
*
* Unsupported intermediate modes drop to the lower power setting. If the
* mode is DPMSModeOff, the output must be disabled, as the DPLL may be
* disabled afterwards.
*/
void (*dpms)(ScrnInfoPtr pScrn, I830OutputPtr output, int mode);
#define I830CrtcPrivate(c) ((I830CrtcPrivatePtr) (c)->driver_private)
/**
* Saves the output's state for restoration on VT switch.
*/
void (*save)(ScrnInfoPtr pScrn, I830OutputPtr output);
/**
* Restore's the output's state at VT switch.
*/
void (*restore)(ScrnInfoPtr pScrn, I830OutputPtr output);
/**
* Callback for testing a video mode for a given output.
*
* This function should only check for cases where a mode can't be supported
* on the pipe specifically, and not represent generic CRTC limitations.
*
* \return MODE_OK if the mode is valid, or another MODE_* otherwise.
*/
int (*mode_valid)(ScrnInfoPtr pScrn, I830OutputPtr output,
DisplayModePtr pMode);
/**
* Callback for setting up a video mode before any pipe/dpll changes.
*
* \param pMode the mode that will be set, or NULL if the mode to be set is
* unknown (such as the restore path of VT switching).
*/
void (*pre_set_mode)(ScrnInfoPtr pScrn, I830OutputPtr output,
DisplayModePtr pMode);
/**
* Callback for setting up a video mode after the DPLL update but before
* the plane is enabled.
*/
void (*post_set_mode)(ScrnInfoPtr pScrn, I830OutputPtr output,
DisplayModePtr pMode);
/**
* Probe for a connected output, and return detect_status.
*/
enum detect_status (*detect)(ScrnInfoPtr pScrn, I830OutputPtr output);
/**
* Query the device for the modes it provides.
*
* This function may also update MonInfo, mm_width, and mm_height.
*
* \return singly-linked list of modes or NULL if no modes found.
*/
DisplayModePtr (*get_modes)(ScrnInfoPtr pScrn, I830OutputPtr output);
/**
* List of available modes on this output.
*
* This should be the list from get_modes(), plus perhaps additional
* compatible modes added later.
*/
DisplayModePtr probed_modes;
/** EDID monitor information */
xf86MonPtr MonInfo;
/** Physical size of the output currently attached. */
int mm_width, mm_height;
I2CBusPtr pI2CBus;
I2CBusPtr pDDCBus;
struct _I830DVODriver *i2c_drv;
typedef struct _I830OutputPrivateRec {
int type;
I2CBusPtr pI2CBus;
I2CBusPtr pDDCBus;
struct _I830DVODriver *i2c_drv;
Bool load_detect_temp;
/** Output-private structure. Should replace i2c_drv */
void *dev_priv;
#ifdef RANDR_12_INTERFACE
RROutputPtr randr_output;
#endif
};
void *dev_priv;
} I830OutputPrivateRec, *I830OutputPrivatePtr;
#define I830OutputPrivate(o) ((I830OutputPrivatePtr) (o)->driver_private)
/** enumeration of 3d consumers so some can maintain invariant state. */
enum last_3d {
@ -314,6 +240,9 @@ typedef struct _I830PipeRec {
} I830PipeRec, *I830PipePtr;
typedef struct _I830Rec {
/* Must be first */
xf86CrtcConfigRec xf86_config;
unsigned char *MMIOBase;
unsigned char *FbBase;
int cpp;
@ -330,9 +259,6 @@ typedef struct _I830Rec {
int CloneVDisplay;
I830EntPtr entityPrivate;
#if 0
int pipe, origPipe;
#endif
int init;
unsigned int bufferOffset; /* for I830SelectBuffer */
@ -495,11 +421,6 @@ typedef struct _I830Rec {
Bool checkDevices;
/* [0] is Pipe A, [1] is Pipe B. */
int num_pipes;
/* [0] is display plane A, [1] is display plane B. */
I830PipeRec pipes[MAX_DISPLAY_PIPES];
/* Driver phase/state information */
Bool preinit;
Bool starting;
@ -516,8 +437,6 @@ typedef struct _I830Rec {
OsTimerPtr devicesTimer;
int ddc2;
int num_outputs;
struct _I830OutputRec output[MAX_OUTPUTS];
/* Panel size pulled from the BIOS */
int PanelXRes, PanelYRes;
@ -610,7 +529,7 @@ extern void I830PrintErrorState(ScrnInfoPtr pScrn);
extern void I965PrintErrorState(ScrnInfoPtr pScrn);
extern void I830Sync(ScrnInfoPtr pScrn);
extern void I830InitHWCursor(ScrnInfoPtr pScrn);
extern void I830SetPipeCursor (ScrnInfoPtr pScrn, int pipe, Bool force);
extern void I830SetPipeCursor (xf86CrtcPtr crtc, Bool force);
extern Bool I830CursorInit(ScreenPtr pScreen);
extern void IntelEmitInvarientState(ScrnInfoPtr pScrn);
extern void I830EmitInvarientState(ScrnInfoPtr pScrn);
@ -689,7 +608,7 @@ extern Bool I830I2CInit(ScrnInfoPtr pScrn, I2CBusPtr *bus_ptr, int i2c_reg,
/* i830_display.c */
Bool
i830PipeHasType (ScrnInfoPtr pScrn, int pipe, int type);
i830PipeHasType (xf86CrtcPtr crtc, int type);
/* i830_crt.c */
void i830_crt_init(ScrnInfoPtr pScrn);
@ -712,16 +631,7 @@ int I830ValidateXF86ModeList(ScrnInfoPtr pScrn, Bool first_time);
void i830_reprobe_output_modes(ScrnInfoPtr pScrn);
void i830_set_xf86_modes_from_outputs(ScrnInfoPtr pScrn);
void i830_set_default_screen_size(ScrnInfoPtr pScrn);
DisplayModePtr i830_ddc_get_modes(ScrnInfoPtr pScrn, I830OutputPtr output);
/* i830_randr.c */
Bool I830RandRCreateScreenResources (ScreenPtr pScreen);
Bool I830RandRInit(ScreenPtr pScreen, int rotation);
Bool I830RandRSetConfig(ScreenPtr pScreen, Rotation rotation, int rate,
RRScreenSizePtr pSize);
Rotation I830GetRotation(ScreenPtr pScreen);
void I830GetOriginalVirtualSize(ScrnInfoPtr pScrn, int *x, int *y);
Bool I830RandRPreInit (ScrnInfoPtr pScrn);
DisplayModePtr i830_ddc_get_modes(xf86OutputPtr output);
/* i830_tv.c */
void i830_tv_init(ScrnInfoPtr pScrn);

View File

@ -35,10 +35,11 @@
#include "i830_display.h"
static void
i830_crt_dpms(ScrnInfoPtr pScrn, I830OutputPtr output, int mode)
i830_crt_dpms(xf86OutputPtr output, int mode)
{
I830Ptr pI830 = I830PTR(pScrn);
CARD32 temp;
ScrnInfoPtr pScrn = output->scrn;
I830Ptr pI830 = I830PTR(pScrn);
CARD32 temp;
temp = INREG(ADPA);
temp &= ~(ADPA_HSYNC_CNTL_DISABLE | ADPA_VSYNC_CNTL_DISABLE);
@ -63,24 +64,25 @@ i830_crt_dpms(ScrnInfoPtr pScrn, I830OutputPtr output, int mode)
}
static void
i830_crt_save(ScrnInfoPtr pScrn, I830OutputPtr output)
i830_crt_save (xf86OutputPtr output)
{
I830Ptr pI830 = I830PTR(pScrn);
ScrnInfoPtr pScrn = output->scrn;
I830Ptr pI830 = I830PTR(pScrn);
pI830->saveADPA = INREG(ADPA);
}
static void
i830_crt_restore(ScrnInfoPtr pScrn, I830OutputPtr output)
i830_crt_restore (xf86OutputPtr output)
{
I830Ptr pI830 = I830PTR(pScrn);
ScrnInfoPtr pScrn = output->scrn;
I830Ptr pI830 = I830PTR(pScrn);
OUTREG(ADPA, pI830->saveADPA);
}
static int
i830_crt_mode_valid(ScrnInfoPtr pScrn, I830OutputPtr output,
DisplayModePtr pMode)
i830_crt_mode_valid(xf86OutputPtr output, DisplayModePtr pMode)
{
if (pMode->Flags & V_DBLSCAN)
return MODE_NO_DBLESCAN;
@ -92,19 +94,24 @@ i830_crt_mode_valid(ScrnInfoPtr pScrn, I830OutputPtr output,
}
static void
i830_crt_pre_set_mode(ScrnInfoPtr pScrn, I830OutputPtr output,
DisplayModePtr pMode)
i830_crt_pre_set_mode (xf86OutputPtr output, DisplayModePtr pMode)
{
}
static void
i830_crt_post_set_mode(ScrnInfoPtr pScrn, I830OutputPtr output,
DisplayModePtr pMode)
i830_crt_post_set_mode (xf86OutputPtr output, DisplayModePtr pMode)
{
I830Ptr pI830 = I830PTR(pScrn);
int dpll_md_reg = (output->pipe == 0) ? DPLL_A_MD : DPLL_B_MD;
CARD32 adpa, dpll_md;
ScrnInfoPtr pScrn = output->scrn;
I830Ptr pI830 = I830PTR(pScrn);
xf86CrtcPtr crtc = output->crtc;
I830CrtcPrivatePtr i830_crtc = crtc->driver_private;
int dpll_md_reg;
CARD32 adpa, dpll_md;
if (i830_crtc->pipe == 0)
dpll_md_reg = DPLL_A_MD;
else
dpll_md_reg = DPLL_B_MD;
/*
* Disable separate mode multiplier used when cloning SDVO to CRT
* XXX this needs to be adjusted when we really are cloning
@ -122,7 +129,7 @@ i830_crt_post_set_mode(ScrnInfoPtr pScrn, I830OutputPtr output,
if (pMode->Flags & V_PVSYNC)
adpa |= ADPA_VSYNC_ACTIVE_HIGH;
if (output->pipe == 0)
if (i830_crtc->pipe == 0)
adpa |= ADPA_PIPE_A_SELECT;
else
adpa |= ADPA_PIPE_B_SELECT;
@ -139,12 +146,13 @@ i830_crt_post_set_mode(ScrnInfoPtr pScrn, I830OutputPtr output,
* \return FALSE if CRT is disconnected.
*/
static Bool
i830_crt_detect_hotplug(ScrnInfoPtr pScrn)
i830_crt_detect_hotplug(xf86OutputPtr output)
{
I830Ptr pI830 = I830PTR(pScrn);
CARD32 temp;
const int timeout_ms = 1000;
int starttime, curtime;
ScrnInfoPtr pScrn = output->scrn;
I830Ptr pI830 = I830PTR(pScrn);
CARD32 temp;
const int timeout_ms = 1000;
int starttime, curtime;
temp = INREG(PORT_HOTPLUG_EN);
@ -177,20 +185,25 @@ i830_crt_detect_hotplug(ScrnInfoPtr pScrn)
* \return FALSE if CRT is disconnected.
*/
static Bool
i830_crt_detect_load(ScrnInfoPtr pScrn, I830OutputPtr output)
i830_crt_detect_load (xf86CrtcPtr crtc,
xf86OutputPtr output)
{
I830Ptr pI830 = I830PTR(pScrn);
CARD32 save_adpa, adpa, pipeconf, bclrpat;
CARD8 st00;
int pipeconf_reg, bclrpat_reg, dpll_reg;
int pipe;
ScrnInfoPtr pScrn = output->scrn;
I830Ptr pI830 = I830PTR(pScrn);
I830CrtcPrivatePtr i830_crtc = I830CrtcPrivate(crtc);
CARD32 save_adpa, adpa, pipeconf, bclrpat;
CARD8 st00;
int pipeconf_reg, bclrpat_reg, dpll_reg;
int pipe = i830_crtc->pipe;
pipe = output->pipe;
if (pipe == 0) {
if (pipe == 0)
{
bclrpat_reg = BCLRPAT_A;
pipeconf_reg = PIPEACONF;
dpll_reg = DPLL_A;
} else {
}
else
{
bclrpat_reg = BCLRPAT_B;
pipeconf_reg = PIPEBCONF;
dpll_reg = DPLL_B;
@ -244,17 +257,15 @@ i830_crt_detect_load(ScrnInfoPtr pScrn, I830OutputPtr output)
* \return FALSE if no DDC response was detected.
*/
static Bool
i830_crt_detect_ddc(ScrnInfoPtr pScrn)
i830_crt_detect_ddc(xf86OutputPtr output)
{
I830Ptr pI830 = I830PTR(pScrn);
struct _I830OutputRec *output;
I830OutputPrivatePtr i830_output = output->driver_private;
output = &pI830->output[0];
/* CRT should always be at 0, but check anyway */
if (output->type != I830_OUTPUT_ANALOG)
if (i830_output->type != I830_OUTPUT_ANALOG)
return FALSE;
return xf86I2CProbeAddress(output->pDDCBus, 0x00A0);
return xf86I2CProbeAddress(i830_output->pDDCBus, 0x00A0);
}
/**
@ -264,25 +275,50 @@ i830_crt_detect_ddc(ScrnInfoPtr pScrn)
* on active displays.
*/
static enum detect_status
i830_crt_detect(ScrnInfoPtr pScrn, I830OutputPtr output)
i830_crt_detect(xf86OutputPtr output)
{
I830Ptr pI830 = I830PTR(pScrn);
ScrnInfoPtr pScrn = output->scrn;
I830Ptr pI830 = I830PTR(pScrn);
xf86CrtcPtr crtc;
if (IS_I945G(pI830) || IS_I945GM(pI830) || IS_I965G(pI830)) {
if (i830_crt_detect_hotplug(pScrn))
if (i830_crt_detect_hotplug(output))
return OUTPUT_STATUS_CONNECTED;
else
return OUTPUT_STATUS_DISCONNECTED;
}
if (i830_crt_detect_ddc(pScrn))
if (i830_crt_detect_ddc(output))
return OUTPUT_STATUS_CONNECTED;
/* Use the load-detect method if we have no other way of telling. */
if (i830GetLoadDetectPipe(pScrn, output) != -1) {
Bool connected = i830_crt_detect_load(pScrn, output);
crtc = i830GetLoadDetectPipe (output);
if (crtc)
{
/* VESA 640x480x72Hz mode to set on the pipe */
static DisplayModeRec mode = {
NULL, NULL, "640x480", MODE_OK, M_T_DEFAULT,
31500,
640, 664, 704, 832, 0,
480, 489, 491, 520, 0,
V_NHSYNC | V_NVSYNC,
0, 0,
0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,
FALSE, FALSE, 0, NULL, 0, 0.0, 0.0
};
Bool connected;
I830OutputPrivatePtr intel_output = output->driver_private;
if (intel_output->load_detect_temp)
{
xf86SetModeCrtc (&mode, INTERLACE_HALVE_V);
i830PipeSetMode (crtc, &mode, FALSE);
}
connected = i830_crt_detect_load (crtc, output);
i830ReleaseLoadDetectPipe(pScrn, output);
i830ReleaseLoadDetectPipe (output);
if (connected)
return OUTPUT_STATUS_CONNECTED;
else
@ -293,16 +329,17 @@ i830_crt_detect(ScrnInfoPtr pScrn, I830OutputPtr output)
}
static DisplayModePtr
i830_crt_get_modes(ScrnInfoPtr pScrn, I830OutputPtr output)
i830_crt_get_modes(xf86OutputPtr output)
{
DisplayModePtr modes;
ScrnInfoPtr pScrn = output->scrn;
DisplayModePtr modes;
MonRec fixed_mon;
modes = i830_ddc_get_modes(pScrn, output);
modes = i830_ddc_get_modes(output);
if (modes != NULL)
return modes;
if (output->detect(pScrn, output) == OUTPUT_STATUS_DISCONNECTED)
if ((*output->funcs->detect)(output) == OUTPUT_STATUS_DISCONNECTED)
return NULL;
/* We've got a potentially-connected monitor that we can't DDC. Return a
@ -323,24 +360,43 @@ i830_crt_get_modes(ScrnInfoPtr pScrn, I830OutputPtr output)
return modes;
}
static void
i830_crt_destroy (xf86OutputPtr output)
{
if (output->driver_private)
xfree (output->driver_private);
}
static const xf86OutputFuncsRec i830_crt_output_funcs = {
.dpms = i830_crt_dpms,
.save = i830_crt_save,
.restore = i830_crt_restore,
.mode_valid = i830_crt_mode_valid,
.pre_set_mode = i830_crt_pre_set_mode,
.post_set_mode = i830_crt_post_set_mode,
.detect = i830_crt_detect,
.get_modes = i830_crt_get_modes,
.destroy = i830_crt_destroy
};
void
i830_crt_init(ScrnInfoPtr pScrn)
{
I830Ptr pI830 = I830PTR(pScrn);
xf86OutputPtr output;
I830OutputPrivatePtr i830_output;
pI830->output[pI830->num_outputs].type = I830_OUTPUT_ANALOG;
pI830->output[pI830->num_outputs].dpms = i830_crt_dpms;
pI830->output[pI830->num_outputs].save = i830_crt_save;
pI830->output[pI830->num_outputs].restore = i830_crt_restore;
pI830->output[pI830->num_outputs].mode_valid = i830_crt_mode_valid;
pI830->output[pI830->num_outputs].pre_set_mode = i830_crt_pre_set_mode;
pI830->output[pI830->num_outputs].post_set_mode = i830_crt_post_set_mode;
pI830->output[pI830->num_outputs].detect = i830_crt_detect;
pI830->output[pI830->num_outputs].get_modes = i830_crt_get_modes;
output = xf86OutputCreate (pScrn, &i830_crt_output_funcs, "VGA");
if (!output)
return;
i830_output = xnfcalloc (sizeof (I830OutputPrivateRec), 1);
if (!i830_output)
{
xf86OutputDestroy (output);
return;
}
i830_output->type = I830_OUTPUT_ANALOG;
output->driver_private = i830_output;
/* Set up the DDC bus. */
I830I2CInit(pScrn, &pI830->output[pI830->num_outputs].pDDCBus,
GPIOA, "CRTDDC_A");
pI830->num_outputs++;
I830I2CInit(pScrn, &i830_output->pDDCBus, GPIOA, "CRTDDC_A");
}

View File

@ -80,13 +80,16 @@ static Bool I830UseHWCursorARGB(ScreenPtr pScrn, CursorPtr pCurs);
#endif
static void
I830SetPipeCursorBase (ScrnInfoPtr pScrn, int pipe)
I830SetPipeCursorBase (xf86CrtcPtr crtc)
{
I830Ptr pI830 = I830PTR(pScrn);
int cursor_base = (pipe == 0 ? CURSOR_A_BASE : CURSOR_B_BASE);
I830MemRange *cursor_mem;
ScrnInfoPtr pScrn = crtc->scrn;
I830CrtcPrivatePtr intel_crtc = crtc->driver_private;
int pipe = intel_crtc->pipe;
I830Ptr pI830 = I830PTR(pScrn);
int cursor_base = (pipe == 0 ? CURSOR_A_BASE : CURSOR_B_BASE);
I830MemRange *cursor_mem;
if (pipe >= pI830->num_pipes)
if (pipe >= pI830->xf86_config.num_crtc)
FatalError("Bad pipe number for cursor base setting\n");
if (pI830->CursorIsARGB)
@ -102,18 +105,20 @@ I830SetPipeCursorBase (ScrnInfoPtr pScrn, int pipe)
}
void
I830SetPipeCursor (ScrnInfoPtr pScrn, int pipe, Bool force)
I830SetPipeCursor (xf86CrtcPtr crtc, Bool force)
{
I830Ptr pI830 = I830PTR(pScrn);
I830PipePtr pI830Pipe = &pI830->pipes[pipe];
CARD32 temp;
Bool show;
ScrnInfoPtr pScrn = crtc->scrn;
I830CrtcPrivatePtr intel_crtc = crtc->driver_private;
int pipe = intel_crtc->pipe;
I830Ptr pI830 = I830PTR(pScrn);
CARD32 temp;
Bool show;
if (!pI830Pipe->enabled)
if (!crtc->enabled)
return;
show = pI830->cursorOn && pI830Pipe->cursorInRange;
if (show && (force || !pI830Pipe->cursorShown))
show = pI830->cursorOn && crtc->cursorInRange;
if (show && (force || !crtc->cursorShown))
{
if (IS_MOBILE(pI830) || IS_I9XX(pI830)) {
int cursor_control;
@ -125,7 +130,7 @@ I830SetPipeCursor (ScrnInfoPtr pScrn, int pipe, Bool force)
temp &= ~(CURSOR_MODE | MCURSOR_PIPE_SELECT);
if (pI830->CursorIsARGB) {
temp |= CURSOR_MODE_64_ARGB_AX;
if (pI830Pipe->gammaEnabled)
if (intel_crtc->gammaEnabled)
temp |= MCURSOR_GAMMA_ENABLE;
} else
temp |= CURSOR_MODE_64_4C_AX;
@ -139,15 +144,15 @@ I830SetPipeCursor (ScrnInfoPtr pScrn, int pipe, Bool force)
temp |= CURSOR_ENABLE;
if (pI830->CursorIsARGB) {
temp |= CURSOR_FORMAT_ARGB;
if (pI830Pipe->gammaEnabled)
if (intel_crtc->gammaEnabled)
temp |= CURSOR_GAMMA_ENABLE;
} else
temp |= CURSOR_FORMAT_3C;
OUTREG(CURSOR_CONTROL, temp);
}
pI830Pipe->cursorShown = TRUE;
crtc->cursorShown = TRUE;
}
else if (!show && (force || pI830Pipe->cursorShown))
else if (!show && (force || crtc->cursorShown))
{
if (IS_MOBILE(pI830) || IS_I9XX(pI830))
{
@ -165,11 +170,11 @@ I830SetPipeCursor (ScrnInfoPtr pScrn, int pipe, Bool force)
temp &= ~(CURSOR_ENABLE|CURSOR_GAMMA_ENABLE);
OUTREG(CURSOR_CONTROL, temp);
}
pI830Pipe->cursorShown = FALSE;
crtc->cursorShown = FALSE;
}
/* Flush cursor changes. */
I830SetPipeCursorBase(pScrn, pipe);
I830SetPipeCursorBase(crtc);
}
void
@ -180,11 +185,12 @@ I830InitHWCursor(ScrnInfoPtr pScrn)
int i;
DPRINTF(PFX, "I830InitHWCursor\n");
for (i = 0; i < pI830->num_pipes; i++)
pI830->pipes[i].cursorShown = FALSE;
for (i = 0; i < pI830->xf86_config.num_crtc; i++)
pI830->xf86_config.crtc[i]->cursorShown = FALSE;
/* Initialise the HW cursor registers, leaving the cursor hidden. */
if (IS_MOBILE(pI830) || IS_I9XX(pI830)) {
for (i = 0; i < pI830->num_pipes; i++)
for (i = 0; i < pI830->xf86_config.num_crtc; i++)
{
int cursor_control = i == 0 ? CURSOR_A_CONTROL : CURSOR_B_CONTROL;
temp = INREG(cursor_control);
@ -198,7 +204,7 @@ I830InitHWCursor(ScrnInfoPtr pScrn)
temp |= CURSOR_MODE_64_4C_AX;
/* Need to set control, then address. */
OUTREG(cursor_control, temp);
I830SetPipeCursorBase(pScrn, i);
I830SetPipeCursorBase(pI830->xf86_config.crtc[i]);
}
} else {
temp = INREG(CURSOR_CONTROL);
@ -211,7 +217,7 @@ I830InitHWCursor(ScrnInfoPtr pScrn)
/* This initialises the format and leave the cursor disabled. */
OUTREG(CURSOR_CONTROL, temp);
/* Need to set address and size after disabling. */
I830SetPipeCursorBase(pScrn, 0);
I830SetPipeCursorBase(pI830->xf86_config.crtc[0]);
temp = ((I810_CURSOR_X & CURSOR_SIZE_MASK) << CURSOR_SIZE_HSHIFT) |
((I810_CURSOR_Y & CURSOR_SIZE_MASK) << CURSOR_SIZE_VSHIFT);
OUTREG(CURSOR_SIZE, temp);
@ -484,14 +490,14 @@ I830SetCursorPosition(ScrnInfoPtr pScrn, int x, int y)
x -= hotspotx;
y -= hotspoty;
for (pipe = 0; pipe < pI830->num_pipes; pipe++)
for (pipe = 0; pipe < pI830->xf86_config.num_crtc; pipe++)
{
I830PipePtr pI830Pipe = &pI830->pipes[pipe];
DisplayModePtr mode = &pI830Pipe->curMode;
int thisx = x - pI830Pipe->x;
int thisy = y - pI830Pipe->y;
xf86CrtcPtr crtc = pI830->xf86_config.crtc[pipe];
DisplayModePtr mode = &crtc->curMode;
int thisx = x - crtc->x;
int thisy = y - crtc->y;
if (!pI830Pipe->enabled)
if (!crtc->enabled)
continue;
/*
@ -527,9 +533,9 @@ I830SetCursorPosition(ScrnInfoPtr pScrn, int x, int y)
if (pipe == 1)
OUTREG(CURSOR_B_POSITION, temp);
pI830Pipe->cursorInRange = inrange;
crtc->cursorInRange = inrange;
I830SetPipeCursor (pScrn, pipe, FALSE);
I830SetPipeCursor (crtc, FALSE);
}
}
@ -550,8 +556,8 @@ I830ShowCursor(ScrnInfoPtr pScrn)
pI830->CursorMemARGB->Physical, pI830->CursorMemARGB->Start);
pI830->cursorOn = TRUE;
for (pipe = 0; pipe < pI830->num_pipes; pipe++)
I830SetPipeCursor (pScrn, pipe, TRUE);
for (pipe = 0; pipe < pI830->xf86_config.num_crtc; pipe++)
I830SetPipeCursor (pI830->xf86_config.crtc[pipe], TRUE);
}
static void
@ -563,14 +569,15 @@ I830HideCursor(ScrnInfoPtr pScrn)
DPRINTF(PFX, "I830HideCursor\n");
pI830->cursorOn = FALSE;
for (pipe = 0; pipe < pI830->num_pipes; pipe++)
I830SetPipeCursor (pScrn, pipe, TRUE);
for (pipe = 0; pipe < pI830->xf86_config.num_crtc; pipe++)
I830SetPipeCursor (pI830->xf86_config.crtc[pipe], TRUE);
}
static void
I830SetCursorColors(ScrnInfoPtr pScrn, int bg, int fg)
{
I830Ptr pI830 = I830PTR(pScrn);
int pipe;
#ifdef ARGB_CURSOR
/* Don't recolour cursors set with SetCursorARGB. */
@ -580,18 +587,17 @@ I830SetCursorColors(ScrnInfoPtr pScrn, int bg, int fg)
DPRINTF(PFX, "I830SetCursorColors\n");
if (pI830->pipes[0].enabled)
for (pipe = 0; pipe < pI830->xf86_config.num_crtc; pipe++)
{
OUTREG(CURSOR_A_PALETTE0, bg & 0x00ffffff);
OUTREG(CURSOR_A_PALETTE1, fg & 0x00ffffff);
OUTREG(CURSOR_A_PALETTE2, fg & 0x00ffffff);
OUTREG(CURSOR_A_PALETTE3, bg & 0x00ffffff);
}
if (pI830->pipes[1].enabled)
{
OUTREG(CURSOR_B_PALETTE0, bg & 0x00ffffff);
OUTREG(CURSOR_B_PALETTE1, fg & 0x00ffffff);
OUTREG(CURSOR_B_PALETTE2, fg & 0x00ffffff);
OUTREG(CURSOR_B_PALETTE3, bg & 0x00ffffff);
xf86CrtcPtr crtc = pI830->xf86_config.crtc[pipe];
int pal0 = pipe == 0 ? CURSOR_A_PALETTE0 : CURSOR_B_PALETTE0;
if (crtc->enabled)
{
OUTREG(pal0 + 0, bg & 0x00ffffff);
OUTREG(pal0 + 4, fg & 0x00ffffff);
OUTREG(pal0 + 8, fg & 0x00ffffff);
OUTREG(pal0 + 12, bg & 0x00ffffff);
}
}
}

View File

@ -61,20 +61,25 @@ i830PrintPll(char *prefix, int refclk, int m1, int m2, int n, int p1, int p2)
}
/**
* Returns whether any output on the specified pipe is an LVDS output
* Returns whether any output on the specified pipe is of the specified type
*/
Bool
i830PipeHasType (ScrnInfoPtr pScrn, int pipe, int type)
i830PipeHasType (xf86CrtcPtr crtc, int type)
{
I830Ptr pI830 = I830PTR(pScrn);
int i;
ScrnInfoPtr pScrn = crtc->scrn;
I830Ptr pI830 = I830PTR(pScrn);
int i;
for (i = 0; i < pI830->num_outputs; i++)
if (pI830->output[i].enabled && pI830->output[i].pipe == pipe)
for (i = 0; i < pI830->xf86_config.num_output; i++)
{
xf86OutputPtr output = pI830->xf86_config.output[i];
if (output->crtc == crtc)
{
if (pI830->output[i].type == type)
I830OutputPrivatePtr intel_output = output->driver_private;
if (intel_output->type == type)
return TRUE;
}
}
return FALSE;
}
@ -86,9 +91,10 @@ i830PipeHasType (ScrnInfoPtr pScrn, int pipe, int type)
* clk = refclk * (5 * m1 + m2) / n / (p1 * p2)
*/
static Bool
i830PllIsValid(ScrnInfoPtr pScrn, int pipe, int refclk, int m1, int m2,
i830PllIsValid(xf86CrtcPtr crtc, int refclk, int m1, int m2,
int n, int p1, int p2)
{
ScrnInfoPtr pScrn = crtc->scrn;
I830Ptr pI830 = I830PTR(pScrn);
int p, m, vco, dotclock;
int min_m1, max_m1, min_m2, max_m2, min_m, max_m, min_n, max_n;
@ -105,7 +111,7 @@ i830PllIsValid(ScrnInfoPtr pScrn, int pipe, int refclk, int m1, int m2,
max_n = 8;
min_p1 = 1;
max_p1 = 8;
if (i830PipeHasType (pScrn, pipe, I830_OUTPUT_LVDS)) {
if (i830PipeHasType (crtc, I830_OUTPUT_LVDS)) {
min_p = 7;
max_p = 98;
} else {
@ -171,9 +177,10 @@ i830PllIsValid(ScrnInfoPtr pScrn, int pipe, int refclk, int m1, int m2,
* clk = refclk * (5 * m1 + m2) / n / (p1 * p2)
*/
static Bool
i830FindBestPLL(ScrnInfoPtr pScrn, int pipe, int target, int refclk,
i830FindBestPLL(xf86CrtcPtr crtc, int target, int refclk,
int *outm1, int *outm2, int *outn, int *outp1, int *outp2)
{
ScrnInfoPtr pScrn = crtc->scrn;
I830Ptr pI830 = I830PTR(pScrn);
int m1, m2, n, p1, p2;
int err = target;
@ -188,7 +195,7 @@ i830FindBestPLL(ScrnInfoPtr pScrn, int pipe, int target, int refclk,
max_n = 8;
min_p1 = 1;
max_p1 = 8;
if (i830PipeHasType (pScrn, pipe, I830_OUTPUT_LVDS)) {
if (i830PipeHasType (crtc, I830_OUTPUT_LVDS)) {
/* The single-channel range is 25-112Mhz, and dual-channel
* is 80-224Mhz. Prefer single channel as much as possible.
*/
@ -224,7 +231,7 @@ i830FindBestPLL(ScrnInfoPtr pScrn, int pipe, int target, int refclk,
for (p1 = min_p1; p1 <= max_p1; p1++) {
int clock, this_err;
if (!i830PllIsValid(pScrn, pipe, refclk, m1, m2, n,
if (!i830PllIsValid(crtc, refclk, m1, m2, n,
p1, p2)) {
continue;
}
@ -255,10 +262,12 @@ i830WaitForVblank(ScrnInfoPtr pScreen)
}
void
i830PipeSetBase(ScrnInfoPtr pScrn, int pipe, int x, int y)
i830PipeSetBase(xf86CrtcPtr crtc, int x, int y)
{
ScrnInfoPtr pScrn = crtc->scrn;
I830Ptr pI830 = I830PTR(pScrn);
I830PipePtr pI830Pipe = &pI830->pipes[pipe];
I830CrtcPrivatePtr intel_crtc = crtc->driver_private;
int pipe = intel_crtc->pipe;
unsigned long Start;
int dspbase = (pipe == 0 ? DSPABASE : DSPBBASE);
int dspsurf = (pipe == 0 ? DSPASURF : DSPBSURF);
@ -277,8 +286,8 @@ i830PipeSetBase(ScrnInfoPtr pScrn, int pipe, int x, int y)
OUTREG(dspbase, Start + ((y * pScrn->displayWidth + x) * pI830->cpp));
}
pI830Pipe->x = x;
pI830Pipe->y = y;
crtc->x = x;
crtc->y = y;
}
/**
@ -291,19 +300,21 @@ i830PipeSetBase(ScrnInfoPtr pScrn, int pipe, int x, int y)
* - Closer in refresh rate to the requested mode.
*/
DisplayModePtr
i830PipeFindClosestMode(ScrnInfoPtr pScrn, int pipe, DisplayModePtr pMode)
i830PipeFindClosestMode(xf86CrtcPtr crtc, DisplayModePtr pMode)
{
ScrnInfoPtr pScrn = crtc->scrn;
I830Ptr pI830 = I830PTR(pScrn);
DisplayModePtr pBest = NULL, pScan = NULL;
int i;
/* Assume that there's only one output connected to the given CRTC. */
for (i = 0; i < pI830->num_outputs; i++) {
if (pI830->output[i].pipe == pipe &&
pI830->output[i].enabled &&
pI830->output[i].probed_modes != NULL)
for (i = 0; i < pI830->xf86_config.num_output; i++)
{
xf86OutputPtr output = pI830->xf86_config.output[i];
if (output->crtc == crtc && output->probed_modes != NULL)
{
pScan = pI830->output[i].probed_modes;
pScan = output->probed_modes;
break;
}
}
@ -311,9 +322,10 @@ i830PipeFindClosestMode(ScrnInfoPtr pScrn, int pipe, DisplayModePtr pMode)
* spam the desired mode in.
*/
if (pScan == NULL) {
I830CrtcPrivatePtr intel_crtc = crtc->driver_private;
xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
"No pipe mode list for pipe %d,"
"continuing with desired mode\n", pipe);
"continuing with desired mode\n", intel_crtc->pipe);
return pMode;
}
@ -367,6 +379,8 @@ i830PipeFindClosestMode(ScrnInfoPtr pScrn, int pipe, DisplayModePtr pMode)
" continuing with desired mode %dx%d@%.1f\n",
pMode->HDisplay, pMode->VDisplay, pMode->VRefresh);
} else if (!xf86ModesEqual(pBest, pMode)) {
I830CrtcPrivatePtr intel_crtc = crtc->driver_private;
int pipe = intel_crtc->pipe;
xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
"Choosing pipe %d's mode %dx%d@%.1f instead of xf86 "
"mode %dx%d@%.1f\n", pipe,
@ -382,13 +396,14 @@ i830PipeFindClosestMode(ScrnInfoPtr pScrn, int pipe, DisplayModePtr pMode)
*/
Bool
i830PipeInUse (ScrnInfoPtr pScrn, int pipe)
i830PipeInUse (xf86CrtcPtr crtc)
{
ScrnInfoPtr pScrn = crtc->scrn;
I830Ptr pI830 = I830PTR(pScrn);
int i;
for (i = 0; i < pI830->num_outputs; i++)
if (pI830->output[i].enabled && pI830->output[i].pipe == pipe)
for (i = 0; i < pI830->xf86_config.num_output; i++)
if (pI830->xf86_config.output[i]->crtc == crtc)
return TRUE;
return FALSE;
}
@ -402,11 +417,13 @@ i830PipeInUse (ScrnInfoPtr pScrn, int pipe)
* display data.
*/
Bool
i830PipeSetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode, int pipe,
i830PipeSetMode(xf86CrtcPtr crtc, DisplayModePtr pMode,
Bool plane_enable)
{
ScrnInfoPtr pScrn = crtc->scrn;
I830Ptr pI830 = I830PTR(pScrn);
I830PipePtr pI830Pipe = &pI830->pipes[pipe];
I830CrtcPrivatePtr intel_crtc = crtc->driver_private;
int pipe = intel_crtc->pipe;
int m1 = 0, m2 = 0, n = 0, p1 = 0, p2 = 0;
CARD32 dpll = 0, fp = 0, temp;
CARD32 htot, hblank, hsync, vtot, vblank, vsync, dspcntr;
@ -434,28 +451,34 @@ i830PipeSetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode, int pipe,
Bool didLock = FALSE;
#endif
if (xf86ModesEqual(&pI830Pipe->curMode, pMode))
if (xf86ModesEqual(&crtc->curMode, pMode))
return TRUE;
xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Requested pix clock: %d\n",
pMode->Clock);
pI830->pipes[pipe].enabled = i830PipeInUse (pScrn, pipe);
crtc->enabled = i830PipeInUse (crtc);
if (!pI830->pipes[pipe].enabled)
if (!crtc->enabled)
{
/* XXX disable crtc? */
return TRUE;
}
#ifdef XF86DRI
didLock = I830DRILock(pScrn);
#endif
for (i = 0; i < pI830->num_outputs; i++) {
if (pI830->output[i].pipe != pipe || !pI830->output[i].enabled)
for (i = 0; i < pI830->xf86_config.num_output; i++)
{
xf86OutputPtr output = pI830->xf86_config.output[i];
I830OutputPrivatePtr intel_output = output->driver_private;
if (output->crtc != crtc)
continue;
pI830->output[i].pre_set_mode(pScrn, &pI830->output[i], pMode);
(*output->funcs->pre_set_mode)(output, pMode);
switch (pI830->output[i].type) {
switch (intel_output->type) {
case I830_OUTPUT_LVDS:
is_lvds = TRUE;
break;
@ -549,7 +572,7 @@ i830PipeSetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode, int pipe,
} else {
refclk = 48000;
}
ok = i830FindBestPLL(pScrn, pipe, pixel_clock, refclk, &m1, &m2, &n,
ok = i830FindBestPLL(crtc, pixel_clock, refclk, &m1, &m2, &n,
&p1, &p2);
if (!ok) {
xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
@ -636,7 +659,7 @@ i830PipeSetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode, int pipe,
FatalError("unknown display bpp\n");
}
if (pI830Pipe->gammaEnabled) {
if (intel_crtc->gammaEnabled) {
dspcntr |= DISPPLANE_GAMMA_ENABLE;
}
@ -671,9 +694,10 @@ i830PipeSetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode, int pipe,
OUTREG(PFIT_CONTROL, 0);
}
for (i = 0; i < pI830->num_outputs; i++) {
if (pI830->output[i].pipe == pipe)
pI830->output[i].post_set_mode(pScrn, &pI830->output[i], pMode);
for (i = 0; i < pI830->xf86_config.num_output; i++) {
xf86OutputPtr output = pI830->xf86_config.output[i];
if (output->crtc == crtc)
(*output->funcs->post_set_mode)(output, pMode);
}
OUTREG(htot_reg, htot);
@ -685,7 +709,7 @@ i830PipeSetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode, int pipe,
OUTREG(dspstride_reg, pScrn->displayWidth * pI830->cpp);
OUTREG(dspsize_reg, dspsize);
OUTREG(dsppos_reg, 0);
i830PipeSetBase(pScrn, pipe, pI830Pipe->x, pI830Pipe->y);
i830PipeSetBase(crtc, crtc->x, crtc->y);
OUTREG(pipesrc_reg, pipesrc);
/* Then, turn the pipe on first */
@ -697,7 +721,7 @@ i830PipeSetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode, int pipe,
OUTREG(dspcntr_reg, dspcntr);
}
pI830Pipe->curMode = *pMode;
crtc->curMode = *pMode;
ret = TRUE;
done:
@ -712,28 +736,33 @@ void
i830DisableUnusedFunctions(ScrnInfoPtr pScrn)
{
I830Ptr pI830 = I830PTR(pScrn);
int output, pipe;
int o, pipe;
xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Disabling unused functions\n");
for (output = 0; output < pI830->num_outputs; output++) {
if (!pI830->output[output].enabled)
pI830->output[output].dpms(pScrn, &pI830->output[output], DPMSModeOff);
for (o = 0; o < pI830->xf86_config.num_output; o++)
{
xf86OutputPtr output = pI830->xf86_config.output[o];
if (!output->crtc)
(*output->funcs->dpms)(output, DPMSModeOff);
}
/* Now, any unused plane, pipe, and DPLL (FIXME: except for DVO, i915
* internal TV) should have no outputs trying to pull data out of it, so
* we're ready to turn those off.
*/
for (pipe = 0; pipe < pI830->num_pipes; pipe++) {
I830PipePtr pI830Pipe = &pI830->pipes[pipe];
for (pipe = 0; pipe < pI830->xf86_config.num_crtc; pipe++)
{
xf86CrtcPtr crtc = pI830->xf86_config.crtc[pipe];
I830CrtcPrivatePtr intel_crtc = crtc->driver_private;
int pipe = intel_crtc->pipe;
int dspcntr_reg = pipe == 0 ? DSPACNTR : DSPBCNTR;
int pipeconf_reg = pipe == 0 ? PIPEACONF : PIPEBCONF;
int dpll_reg = pipe == 0 ? DPLL_A : DPLL_B;
CARD32 dspcntr, pipeconf, dpll;
char *pipe_name = pipe == 0 ? "A" : "B";
if (pI830Pipe->enabled)
if (crtc->enabled)
continue;
dspcntr = INREG(dspcntr_reg);
@ -761,7 +790,7 @@ i830DisableUnusedFunctions(ScrnInfoPtr pScrn)
OUTREG(dpll_reg, dpll & ~DPLL_VCO_ENABLE);
}
memset(&pI830Pipe->curMode, 0, sizeof(pI830Pipe->curMode));
memset(&crtc->curMode, 0, sizeof(crtc->curMode));
}
}
@ -778,11 +807,12 @@ i830SetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode)
DPRINTF(PFX, "i830SetMode\n");
for (i = 0; i < pI830->num_pipes; i++)
for (i = 0; i < pI830->xf86_config.num_crtc; i++)
{
ok = i830PipeSetMode(pScrn,
i830PipeFindClosestMode(pScrn, i, pMode),
i, TRUE);
xf86CrtcPtr crtc = pI830->xf86_config.crtc[i];
ok = i830PipeSetMode(crtc,
i830PipeFindClosestMode(crtc, pMode),
TRUE);
if (!ok)
goto done;
}
@ -802,7 +832,9 @@ i830SetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode)
/* If we might have enabled/disabled some pipes, we need to reset
* cloning mode support.
*/
if (pI830->pipes[0].enabled && pI830->pipes[1].enabled)
if (pI830->xf86_config.num_crtc >= 2 &&
pI830->xf86_config.crtc[0]->enabled &&
pI830->xf86_config.crtc[1]->enabled)
pI830->Clone = TRUE;
else
pI830->Clone = FALSE;
@ -833,7 +865,8 @@ i830DescribeOutputConfiguration(ScrnInfoPtr pScrn)
xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Output configuration:\n");
for (i = 0; i < pI830->num_pipes; i++) {
for (i = 0; i < pI830->xf86_config.num_crtc; i++) {
xf86CrtcPtr crtc = pI830->xf86_config.crtc[i];
CARD32 dspcntr = INREG(DSPACNTR + (DSPBCNTR - DSPACNTR) * i);
CARD32 pipeconf = INREG(PIPEACONF + (PIPEBCONF - PIPEACONF) * i);
Bool hw_plane_enable = (dspcntr & DISPLAY_PLANE_ENABLE) != 0;
@ -841,53 +874,37 @@ i830DescribeOutputConfiguration(ScrnInfoPtr pScrn)
xf86DrvMsg(pScrn->scrnIndex, X_INFO,
" Pipe %c is %s\n",
'A' + i, pI830->pipes[i].enabled ? "on" : "off");
'A' + i, crtc->enabled ? "on" : "off");
xf86DrvMsg(pScrn->scrnIndex, X_INFO,
" Display plane %c is now %s and connected to pipe %c.\n",
'A' + i,
pI830->pipes[i].enabled ? "enabled" : "disabled",
crtc->enabled ? "enabled" : "disabled",
dspcntr & DISPPLANE_SEL_PIPE_MASK ? 'B' : 'A');
if (hw_pipe_enable != pI830->pipes[i].enabled) {
if (hw_pipe_enable != crtc->enabled) {
xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
" Hardware claims pipe %c is %s while software "
"believes it is %s\n",
'A' + i, hw_pipe_enable ? "on" : "off",
pI830->pipes[i].enabled ? "on" : "off");
crtc->enabled ? "on" : "off");
}
if (hw_plane_enable != pI830->pipes[i].enabled) {
if (hw_plane_enable != crtc->enabled) {
xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
" Hardware claims plane %c is %s while software "
"believes it is %s\n",
'A' + i, hw_plane_enable ? "on" : "off",
pI830->pipes[i].enabled ? "on" : "off");
crtc->enabled ? "on" : "off");
}
}
for (i = 0; i < pI830->num_outputs; i++) {
const char *name = NULL;
switch (pI830->output[i].type) {
case I830_OUTPUT_ANALOG:
name = "CRT";
break;
case I830_OUTPUT_LVDS:
name = "LVDS";
break;
case I830_OUTPUT_SDVO:
name = "SDVO";
break;
case I830_OUTPUT_DVO:
name = "DVO";
break;
case I830_OUTPUT_TVOUT:
name = "TV";
break;
}
for (i = 0; i < pI830->xf86_config.num_output; i++) {
xf86OutputPtr output = pI830->xf86_config.output[i];
xf86CrtcPtr crtc = output->crtc;
I830CrtcPrivatePtr intel_crtc = crtc ? crtc->driver_private : NULL;
xf86DrvMsg(pScrn->scrnIndex, X_INFO,
" Output %s is %sabled and connected to pipe %c\n",
name, pI830->output[i].enabled ? "en" : "dis",
pI830->output[i].pipe == 0 ? 'A' : 'B');
" Output %s is connected to pipe %s\n",
output->name, intel_crtc == NULL ? "none" :
(intel_crtc->pipe == 0 ? "A" : "B"));
}
}
@ -902,74 +919,46 @@ i830DescribeOutputConfiguration(ScrnInfoPtr pScrn)
* configured for it. In the future, it could choose to temporarily disable
* some outputs to free up a pipe for its use.
*
* \return monitor number, or -1 if no pipes are available.
* \return crtc, or NULL if no pipes are available.
*/
int
i830GetLoadDetectPipe(ScrnInfoPtr pScrn, I830OutputPtr output)
xf86CrtcPtr
i830GetLoadDetectPipe(xf86OutputPtr output)
{
I830Ptr pI830 = I830PTR(pScrn);
int i;
/* VESA 640x480x72Hz mode to set on the pipe */
DisplayModeRec mode = {
NULL, NULL, "640x480", MODE_OK, M_T_DEFAULT,
31500,
640, 664, 704, 832, 0,
480, 489, 491, 520, 0,
V_NHSYNC | V_NVSYNC,
0, 0,
0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,
FALSE, FALSE, 0, NULL, 0, 0.0, 0.0
};
ScrnInfoPtr pScrn = output->scrn;
I830Ptr pI830 = I830PTR(pScrn);
I830OutputPrivatePtr intel_output = output->driver_private;
xf86CrtcPtr crtc;
int i;
/* If the output is not marked disabled, check if it's already assigned
* to an active pipe, and is alone on that pipe. If so, we're done.
*/
if (output->enabled) {
int pipeconf_reg = (output->pipe == 0) ? PIPEACONF : PIPEBCONF;
if (output->crtc)
return output->crtc;
if (INREG(pipeconf_reg) & PIPEACONF_ENABLE) {
/* Actually, maybe we don't need to be all alone on the pipe.
* The worst that should happen is false positives. Need to test,
* but actually fixing this during server startup is messy.
*/
#if 0
for (i = 0; i < pI830->num_outputs; i++) {
if (&pI830->output[i] != output &&
pI830->output[i].pipe == output->pipe)
{
return -1;
}
}
#endif
return output->pipe;
}
}
for (i = 0; i < pI830->num_pipes; i++)
if (!i830PipeInUse(pScrn, i))
for (i = 0; i < pI830->xf86_config.num_crtc; i++)
if (!i830PipeInUse(pI830->xf86_config.crtc[i]))
break;
if (i == pI830->num_pipes)
return -1;
if (i == pI830->xf86_config.num_crtc)
return NULL;
output->load_detect_temp = TRUE;
output->pipe = i;
output->enabled = TRUE;
crtc = pI830->xf86_config.crtc[i];
xf86SetModeCrtc(&mode, INTERLACE_HALVE_V);
output->crtc = crtc;
intel_output->load_detect_temp = TRUE;
i830PipeSetMode(pScrn, &mode, i, FALSE);
return i;
return crtc;
}
void
i830ReleaseLoadDetectPipe(ScrnInfoPtr pScrn, I830OutputPtr output)
i830ReleaseLoadDetectPipe(xf86OutputPtr output)
{
if (output->load_detect_temp) {
output->enabled = FALSE;
ScrnInfoPtr pScrn = output->scrn;
I830OutputPrivatePtr intel_output = output->driver_private;
if (intel_output->load_detect_temp)
{
output->crtc = NULL;
intel_output->load_detect_temp = FALSE;
i830DisableUnusedFunctions(pScrn);
output->load_detect_temp = FALSE;
}
}

View File

@ -29,17 +29,18 @@
/* i830_display.c */
DisplayModePtr
i830PipeFindClosestMode(ScrnInfoPtr pScrn, int pipe, DisplayModePtr pMode);
Bool i830PipeSetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode, int pipe,
i830PipeFindClosestMode(xf86CrtcPtr crtc, DisplayModePtr pMode);
Bool i830PipeSetMode(xf86CrtcPtr crtc, DisplayModePtr pMode,
Bool plane_enable);
void i830DisableUnusedFunctions(ScrnInfoPtr pScrn);
Bool i830SetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode);
void i830PipeSetBase(ScrnInfoPtr pScrn, int pipe, int x, int y);
void i830PipeSetBase(xf86CrtcPtr crtc, int x, int y);
void i830WaitForVblank(ScrnInfoPtr pScrn);
void i830DescribeOutputConfiguration(ScrnInfoPtr pScrn);
int i830GetLoadDetectPipe(ScrnInfoPtr pScrn, I830OutputPtr output);
void i830ReleaseLoadDetectPipe(ScrnInfoPtr pScrn, I830OutputPtr output);
Bool i830PipeInUse(ScrnInfoPtr pScrn, int pipe);
xf86CrtcPtr i830GetLoadDetectPipe(xf86OutputPtr output);
void i830ReleaseLoadDetectPipe(xf86OutputPtr output);
Bool i830PipeInUse(xf86CrtcPtr crtc);
/** @{
*/
@ -51,4 +52,3 @@ DisplayModePtr i830_xf86CVTMode(int HDisplay, int VDisplay, float VRefresh,
#define xf86CVTMode i830_xf86CVTMode
#endif /* XORG_VERSION_CURRENT <= XORG_VERSION_NUMERIC(7,1,99,2) */
/** @} */

View File

@ -1513,13 +1513,9 @@ I830DRISetVBlankInterrupt (ScrnInfoPtr pScrn, Bool on)
if (pI830->directRenderingEnabled && pI830->drmMinor >= 5) {
if (on) {
if (pI830->pipes[1].enabled) {
if (pI830->drmMinor >= 6)
pipe.pipe = DRM_I830_VBLANK_PIPE_A | DRM_I830_VBLANK_PIPE_B;
else
pipe.pipe = DRM_I830_VBLANK_PIPE_B;
if (pI830->xf86_config.num_crtc > 1 && pI830->xf86_config.crtc[1]->enabled)
pipe.pipe = DRM_I830_VBLANK_PIPE_B;
} else
else
pipe.pipe = DRM_I830_VBLANK_PIPE_A;
} else {
pipe.pipe = 0;

View File

@ -592,8 +592,10 @@ I830LoadPalette(ScrnInfoPtr pScrn, int numColors, int *indices,
DPRINTF(PFX, "I830LoadPalette: numColors: %d\n", numColors);
pI830 = I830PTR(pScrn);
for(p=0; p < pI830->num_pipes; p++) {
I830PipePtr pI830Pipe = &pI830->pipes[p];
for(p=0; p < pI830->xf86_config.num_crtc; p++)
{
xf86CrtcPtr crtc = pI830->xf86_config.crtc[p];
I830CrtcPrivatePtr intel_crtc = crtc->driver_private;
if (p == 0) {
palreg = PALETTE_A;
@ -607,10 +609,10 @@ I830LoadPalette(ScrnInfoPtr pScrn, int numColors, int *indices,
dspsurf = DSPBSURF;
}
if (pI830Pipe->enabled == 0)
if (crtc->enabled == 0)
continue;
pI830Pipe->gammaEnabled = 1;
intel_crtc->gammaEnabled = 1;
/* To ensure gamma is enabled we need to turn off and on the plane */
temp = INREG(dspreg);
@ -709,6 +711,32 @@ I830SetupOutputs(ScrnInfoPtr pScrn)
i830_tv_init(pScrn);
}
/**
* Setup the CRTCs
*/
static const xf86CrtcFuncsRec i830_crtc_funcs = {
};
static void
I830SetupCrtcs(ScrnInfoPtr pScrn, int num_pipe)
{
int p;
for (p = 0; p < num_pipe; p++)
{
xf86CrtcPtr crtc = xf86CrtcCreate (pScrn, &i830_crtc_funcs);
I830CrtcPrivatePtr intel_crtc;
if (!crtc)
break;
intel_crtc = xnfcalloc (sizeof (I830CrtcPrivateRec), 1);
intel_crtc->pipe = p;
crtc->driver_private = intel_crtc;
}
}
static void
I830PreInitDDC(ScrnInfoPtr pScrn)
{
@ -727,8 +755,6 @@ I830PreInitDDC(ScrnInfoPtr pScrn)
if (xf86LoadSubModule(pScrn, "i2c")) {
xf86LoaderReqSymLists(I810i2cSymbols, NULL);
I830SetupOutputs(pScrn);
pI830->ddc2 = TRUE;
} else {
pI830->ddc2 = FALSE;
@ -850,6 +876,7 @@ I830PreInit(ScrnInfoPtr pScrn, int flags)
pointer pVBEModule = NULL;
Bool enable;
const char *chipname;
int num_pipe;
#ifdef XF86DRI
unsigned long savedMMSize;
#endif
@ -1157,14 +1184,14 @@ I830PreInit(ScrnInfoPtr pScrn, int flags)
}
if (pI830->PciInfo->chipType == PCI_CHIP_E7221_G)
pI830->num_pipes = 1;
num_pipe = 1;
else
if (IS_MOBILE(pI830) || IS_I9XX(pI830))
pI830->num_pipes = 2;
num_pipe = 2;
else
pI830->num_pipes = 1;
num_pipe = 1;
xf86DrvMsg(pScrn->scrnIndex, X_INFO, "%d display pipe%s available.\n",
pI830->num_pipes, pI830->num_pipes > 1 ? "s" : "");
num_pipe, num_pipe > 1 ? "s" : "");
/*
* Get the pre-allocated (stolen) memory size.
@ -1311,9 +1338,11 @@ I830PreInit(ScrnInfoPtr pScrn, int flags)
}
I830PreInitDDC(pScrn);
I830SetupOutputs(pScrn);
I830SetupCrtcs(pScrn, num_pipe);
if (xf86ReturnOptValBool(pI830->Options, OPTION_CLONE, FALSE)) {
if (pI830->num_pipes == 1) {
if (num_pipe == 1) {
xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
"Can't enable Clone Mode because this is a single pipe device\n");
PreInitCleanup(pScrn);
@ -1333,33 +1362,44 @@ I830PreInit(ScrnInfoPtr pScrn, int flags)
/* Perform the pipe assignment of outputs. This is a kludge until
* we have better configuration support in the generic RandR code
*/
for (i = 0; i < pI830->num_outputs; i++) {
pI830->output[i].enabled = FALSE;
for (i = 0; i < pI830->xf86_config.num_output; i++)
{
xf86OutputPtr output = pI830->xf86_config.output[i];
I830OutputPrivatePtr intel_output = output->driver_private;
xf86CrtcPtr crtc;
int p;
switch (pI830->output[i].type) {
output->crtc = NULL;
switch (intel_output->type) {
case I830_OUTPUT_LVDS:
/* LVDS must live on pipe B for two-pipe devices */
pI830->output[i].pipe = pI830->num_pipes - 1;
pI830->output[i].enabled = TRUE;
crtc = pI830->xf86_config.crtc[pI830->xf86_config.num_crtc - 1];
if (!i830PipeInUse (crtc))
output->crtc = crtc;
break;
case I830_OUTPUT_ANALOG:
case I830_OUTPUT_DVO:
case I830_OUTPUT_SDVO:
if (pI830->output[i].detect(pScrn, &pI830->output[i]) !=
OUTPUT_STATUS_DISCONNECTED) {
if (!i830PipeInUse(pScrn, 0)) {
pI830->output[i].pipe = 0;
pI830->output[i].enabled = TRUE;
} else if (!i830PipeInUse(pScrn, 1)) {
pI830->output[i].pipe = 1;
pI830->output[i].enabled = TRUE;
if ((*output->funcs->detect)(output) != OUTPUT_STATUS_DISCONNECTED)
{
for (p = 0; p < pI830->xf86_config.num_crtc; p++)
{
crtc = pI830->xf86_config.crtc[p];
if (!i830PipeInUse(crtc))
{
output->crtc = crtc;
break;
}
}
}
break;
case I830_OUTPUT_TVOUT:
if (!i830PipeInUse(pScrn, 0)) {
pI830->output[i].pipe = 0;
pI830->output[i].enabled = TRUE;
crtc = pI830->xf86_config.crtc[0];
if ((*output->funcs->detect)(output) != OUTPUT_STATUS_DISCONNECTED &&
!i830PipeInUse(crtc))
{
output->crtc = crtc;
}
break;
default:
@ -1368,10 +1408,12 @@ I830PreInit(ScrnInfoPtr pScrn, int flags)
}
}
for (i = 0; i < pI830->num_pipes; i++) {
pI830->pipes[i].enabled = i830PipeInUse(pScrn, i);
for (i = 0; i < pI830->xf86_config.num_crtc; i++)
{
xf86CrtcPtr crtc = pI830->xf86_config.crtc[i];
crtc->enabled = i830PipeInUse(crtc);
}
pI830->rotation = RR_Rotate_0;
if ((s = xf86GetOptValString(pI830->Options, OPTION_ROTATE))) {
pI830->InitialRotation = 0;
@ -1614,7 +1656,7 @@ I830PreInit(ScrnInfoPtr pScrn, int flags)
xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
"Maximum frambuffer space: %d kByte\n", pScrn->videoRam);
if (!I830RandRPreInit (pScrn))
if (!xf86RandR12PreInit (pScrn))
{
xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No valid modes.\n");
PreInitCleanup(pScrn);
@ -2129,7 +2171,7 @@ SaveHWState(ScrnInfoPtr pScrn)
temp = INREG(PIPEACONF);
xf86DrvMsg(pScrn->scrnIndex, X_INFO, "PIPEACONF is 0x%08lx\n",
(unsigned long) temp);
if (pI830->num_pipes == 2) {
if (pI830->xf86_config.num_crtc == 2) {
temp = INREG(PIPEBCONF);
xf86DrvMsg(pScrn->scrnIndex, X_INFO, "PIPEBCONF is 0x%08lx\n",
(unsigned long) temp);
@ -2161,7 +2203,7 @@ SaveHWState(ScrnInfoPtr pScrn)
pI830->savePaletteA[i] = INREG(PALETTE_A + (i << 2));
}
if(pI830->num_pipes == 2) {
if(pI830->xf86_config.num_crtc == 2) {
pI830->savePIPEBCONF = INREG(PIPEBCONF);
pI830->savePIPEBSRC = INREG(PIPEBSRC);
pI830->saveDSPBCNTR = INREG(DSPBCNTR);
@ -2205,9 +2247,10 @@ SaveHWState(ScrnInfoPtr pScrn)
pI830->savePFIT_CONTROL = INREG(PFIT_CONTROL);
for (i = 0; i < pI830->num_outputs; i++) {
if (pI830->output[i].save != NULL)
pI830->output[i].save(pScrn, &pI830->output[i]);
for (i = 0; i < pI830->xf86_config.num_output; i++) {
xf86OutputPtr output = pI830->xf86_config.output[i];
if (output->funcs->save)
(*output->funcs->save) (output);
}
vgaHWUnlock(hwp);
@ -2246,8 +2289,9 @@ RestoreHWState(ScrnInfoPtr pScrn)
OUTREG(PIPEBCONF, temp & ~PIPEBCONF_ENABLE);
/* Disable outputs if necessary */
for (i = 0; i < pI830->num_outputs; i++) {
pI830->output[i].pre_set_mode(pScrn, &pI830->output[i], NULL);
for (i = 0; i < pI830->xf86_config.num_output; i++) {
xf86OutputPtr output = pI830->xf86_config.output[i];
(*output->funcs->pre_set_mode) (output, NULL);
}
i830WaitForVblank(pScrn);
@ -2272,7 +2316,7 @@ RestoreHWState(ScrnInfoPtr pScrn)
OUTREG(PALETTE_A + (i << 2), pI830->savePaletteA[i]);
}
if(pI830->num_pipes == 2) {
if(pI830->xf86_config.num_crtc == 2) {
OUTREG(FPB0, pI830->saveFPB0);
OUTREG(FPB1, pI830->saveFPB1);
OUTREG(DPLL_B, pI830->saveDPLL_B);
@ -2296,8 +2340,9 @@ RestoreHWState(ScrnInfoPtr pScrn)
OUTREG(PFIT_CONTROL, pI830->savePFIT_CONTROL);
for (i = 0; i < pI830->num_outputs; i++) {
pI830->output[i].restore(pScrn, &pI830->output[i]);
for (i = 0; i < pI830->xf86_config.num_output; i++) {
xf86OutputPtr output = pI830->xf86_config.output[i];
(*output->funcs->restore) (output);
}
if (IS_I965G(pI830)) {
@ -2666,7 +2711,7 @@ I830CreateScreenResources (ScreenPtr pScreen)
if (!(*pScreen->CreateScreenResources)(pScreen))
return FALSE;
if (!I830RandRCreateScreenResources (pScreen))
if (!xf86RandR12CreateScreenResources (pScreen))
return FALSE;
return TRUE;
@ -3222,10 +3267,11 @@ I830ScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv)
xf86DisableRandR(); /* Disable built-in RandR extension */
shadowSetup(pScreen);
/* support all rotations */
xf86RandR12Init (pScreen);
if (IS_I965G(pI830)) {
I830RandRInit(pScreen, RR_Rotate_0); /* only 0 degrees for I965G */
xf86RandR12SetRotations (pScreen, RR_Rotate_0); /* only 0 degrees for I965G */
} else {
I830RandRInit(pScreen, RR_Rotate_0 | RR_Rotate_90 | RR_Rotate_180 | RR_Rotate_270);
xf86RandR12SetRotations (pScreen, RR_Rotate_0 | RR_Rotate_90 | RR_Rotate_180 | RR_Rotate_270);
}
pI830->PointerMoved = pScrn->PointerMoved;
pScrn->PointerMoved = I830PointerMoved;
@ -3344,9 +3390,12 @@ i830AdjustFrame(int scrnIndex, int x, int y, int flags)
pI830->AccelInfoRec->NeedToSync = FALSE;
}
for (i = 0; i < pI830->num_pipes; i++)
if (pI830->pipes[i].enabled)
i830PipeSetBase(pScrn, i, x, y);
for (i = 0; i < pI830->xf86_config.num_crtc; i++)
{
xf86CrtcPtr crtc = pI830->xf86_config.crtc[i];
if (crtc->enabled)
i830PipeSetBase(crtc, x, y);
}
}
static void
@ -3457,19 +3506,19 @@ I830EnterVT(int scrnIndex, int flags)
ResetState(pScrn, FALSE);
SetHWOperatingState(pScrn);
for (i = 0; i < pI830->num_pipes; i++)
for (i = 0; i < pI830->xf86_config.num_crtc; i++)
{
I830PipePtr pipe = &pI830->pipes[i];
xf86CrtcPtr crtc = pI830->xf86_config.crtc[i];
/* Mark that we'll need to re-set the mode for sure */
memset(&pipe->curMode, 0, sizeof(pipe->curMode));
if (!pipe->desiredMode.CrtcHDisplay)
{
pipe->desiredMode = *i830PipeFindClosestMode (pScrn, i,
pScrn->currentMode);
}
if (!i830PipeSetMode (pScrn, &pipe->desiredMode, i, TRUE))
memset(&crtc->curMode, 0, sizeof(crtc->curMode));
if (!crtc->desiredMode.CrtcHDisplay)
crtc->desiredMode = *i830PipeFindClosestMode (crtc, pScrn->currentMode);
if (!i830PipeSetMode (crtc, &crtc->desiredMode, TRUE))
return FALSE;
i830PipeSetBase(pScrn, i, pipe->x, pipe->y);
i830PipeSetBase(crtc, crtc->x, crtc->y);
}
i830DisableUnusedFunctions(pScrn);
@ -3624,7 +3673,7 @@ I830SaveScreen(ScreenPtr pScreen, int mode)
DPRINTF(PFX, "I830SaveScreen: %d, on is %s\n", mode, BOOLTOSTRING(on));
if (pScrn->vtSema) {
for (i = 0; i < pI830->num_pipes; i++) {
for (i = 0; i < pI830->xf86_config.num_crtc; i++) {
if (i == 0) {
ctrl = DSPACNTR;
base = DSPABASE;
@ -3634,7 +3683,7 @@ I830SaveScreen(ScreenPtr pScreen, int mode)
base = DSPBADDR;
surf = DSPBSURF;
}
if (pI830->pipes[i].enabled) {
if (pI830->xf86_config.crtc[i]->enabled) {
temp = INREG(ctrl);
if (on)
temp |= DISPLAY_PLANE_ENABLE;
@ -3671,11 +3720,16 @@ I830DisplayPowerManagementSet(ScrnInfoPtr pScrn, int PowerManagementMode,
int i;
CARD32 temp, ctrl, base;
for (i = 0; i < pI830->num_outputs; i++) {
pI830->output[i].dpms(pScrn, &pI830->output[i], PowerManagementMode);
for (i = 0; i < pI830->xf86_config.num_output; i++) {
xf86OutputPtr output = pI830->xf86_config.output[i];
(*output->funcs->dpms) (output, PowerManagementMode);
}
for (i = 0; i < pI830->num_pipes; i++) {
for (i = 0; i < pI830->xf86_config.num_crtc; i++)
{
xf86CrtcPtr crtc = pI830->xf86_config.crtc[i];
if (i == 0) {
ctrl = DSPACNTR;
base = DSPABASE;
@ -3683,7 +3737,8 @@ I830DisplayPowerManagementSet(ScrnInfoPtr pScrn, int PowerManagementMode,
ctrl = DSPBCNTR;
base = DSPBADDR;
}
if (pI830->pipes[i].enabled) {
/* XXX pipe disable too? */
if (crtc->enabled) {
temp = INREG(ctrl);
if (PowerManagementMode == DPMSModeOn)
temp |= DISPLAY_PLANE_ENABLE;
@ -3896,7 +3951,7 @@ i830MonitorDetectDebugger(ScrnInfoPtr pScrn)
if (!pScrn->vtSema)
return 1000;
for (i = 0; i < pI830->num_outputs; i++) {
for (i = 0; i < pI830->xf86_config.num_output; i++) {
enum output_status ret;
char *result;

View File

@ -57,18 +57,21 @@ struct _I830DVODriver i830_dvo_drivers[] =
#define I830_NUM_DVO_DRIVERS (sizeof(i830_dvo_drivers)/sizeof(struct _I830DVODriver))
static void
i830_dvo_dpms(ScrnInfoPtr pScrn, I830OutputPtr output, int mode)
i830_dvo_dpms(xf86OutputPtr output, int mode)
{
I830OutputPrivatePtr intel_output = output->driver_private;
if (mode == DPMSModeOn)
output->i2c_drv->vid_rec->Power(output->i2c_drv->dev_priv, TRUE);
(*intel_output->i2c_drv->vid_rec->Power)(intel_output->i2c_drv->dev_priv, TRUE);
else
output->i2c_drv->vid_rec->Power(output->i2c_drv->dev_priv, FALSE);
(*intel_output->i2c_drv->vid_rec->Power)(intel_output->i2c_drv->dev_priv, FALSE);
}
static void
i830_dvo_save(ScrnInfoPtr pScrn, I830OutputPtr output)
i830_dvo_save(xf86OutputPtr output)
{
I830Ptr pI830 = I830PTR(pScrn);
ScrnInfoPtr pScrn = output->scrn;
I830Ptr pI830 = I830PTR(pScrn);
I830OutputPrivatePtr intel_output = output->driver_private;
/* Each output should probably just save the registers it touches, but for
* now, use more overkill.
@ -77,61 +80,68 @@ i830_dvo_save(ScrnInfoPtr pScrn, I830OutputPtr output)
pI830->saveDVOB = INREG(DVOB);
pI830->saveDVOC = INREG(DVOC);
output->i2c_drv->vid_rec->SaveRegs(output->i2c_drv->dev_priv);
(*intel_output->i2c_drv->vid_rec->SaveRegs)(intel_output->i2c_drv->dev_priv);
}
static void
i830_dvo_restore(ScrnInfoPtr pScrn, I830OutputPtr output)
i830_dvo_restore(xf86OutputPtr output)
{
I830Ptr pI830 = I830PTR(pScrn);
ScrnInfoPtr pScrn = output->scrn;
I830Ptr pI830 = I830PTR(pScrn);
I830OutputPrivatePtr intel_output = output->driver_private;
OUTREG(DVOA, pI830->saveDVOA);
OUTREG(DVOB, pI830->saveDVOB);
OUTREG(DVOC, pI830->saveDVOC);
output->i2c_drv->vid_rec->RestoreRegs(output->i2c_drv->dev_priv);
(*intel_output->i2c_drv->vid_rec->RestoreRegs)(intel_output->i2c_drv->dev_priv);
}
static int
i830_dvo_mode_valid(ScrnInfoPtr pScrn, I830OutputPtr output,
DisplayModePtr pMode)
i830_dvo_mode_valid(xf86OutputPtr output, DisplayModePtr pMode)
{
I830OutputPrivatePtr intel_output = output->driver_private;
if (pMode->Flags & V_DBLSCAN)
return MODE_NO_DBLESCAN;
/* XXX: Validate clock range */
if (output->i2c_drv->vid_rec->ModeValid(output->i2c_drv->dev_priv, pMode))
if ((*intel_output->i2c_drv->vid_rec->ModeValid)(intel_output->i2c_drv->dev_priv, pMode))
return MODE_OK;
else
return MODE_BAD;
}
static void
i830_dvo_pre_set_mode(ScrnInfoPtr pScrn, I830OutputPtr output,
DisplayModePtr pMode)
i830_dvo_pre_set_mode(xf86OutputPtr output, DisplayModePtr pMode)
{
I830Ptr pI830 = I830PTR(pScrn);
ScrnInfoPtr pScrn = output->scrn;
I830Ptr pI830 = I830PTR(pScrn);
I830OutputPrivatePtr intel_output = output->driver_private;
output->i2c_drv->vid_rec->Mode(output->i2c_drv->dev_priv, pMode);
(*intel_output->i2c_drv->vid_rec->Mode)(intel_output->i2c_drv->dev_priv, pMode);
OUTREG(DVOC, INREG(DVOC) & ~DVO_ENABLE);
}
static void
i830_dvo_post_set_mode(ScrnInfoPtr pScrn, I830OutputPtr output,
DisplayModePtr pMode)
i830_dvo_post_set_mode(xf86OutputPtr output, DisplayModePtr pMode)
{
I830Ptr pI830 = I830PTR(pScrn);
CARD32 dvo;
int dpll_reg = (output->pipe == 0) ? DPLL_A : DPLL_B;
ScrnInfoPtr pScrn = output->scrn;
I830Ptr pI830 = I830PTR(pScrn);
xf86CrtcPtr crtc = output->crtc;
I830CrtcPrivatePtr intel_crtc = crtc->driver_private;
int pipe = intel_crtc->pipe;
CARD32 dvo;
int dpll_reg = (pipe == 0) ? DPLL_A : DPLL_B;
/* Save the data order, since I don't know what it should be set to. */
dvo = INREG(DVOC) & (DVO_PRESERVE_MASK | DVO_DATA_ORDER_GBRG);
dvo |= DVO_ENABLE;
dvo |= DVO_DATA_ORDER_FP | DVO_BORDER_ENABLE | DVO_BLANK_ACTIVE_HIGH;
if (output->pipe == 1)
if (pipe == 1)
dvo |= DVO_PIPE_B_SELECT;
if (pMode->Flags & V_PHSYNC)
@ -155,7 +165,7 @@ i830_dvo_post_set_mode(ScrnInfoPtr pScrn, I830OutputPtr output,
* Unimplemented.
*/
static enum detect_status
i830_dvo_detect(ScrnInfoPtr pScrn, I830OutputPtr output)
i830_dvo_detect(xf86OutputPtr output)
{
return OUTPUT_STATUS_UNKNOWN;
}
@ -191,46 +201,81 @@ I830I2CDetectDVOControllers(ScrnInfoPtr pScrn, I2CBusPtr pI2CBus,
return FALSE;
}
static void
i830_dvo_destroy (xf86OutputPtr output)
{
I830OutputPrivatePtr intel_output = output->driver_private;
if (intel_output)
{
if (intel_output->pI2CBus)
xf86DestroyI2CBusRec (intel_output->pI2CBus, TRUE, TRUE);
if (intel_output->pDDCBus)
xf86DestroyI2CBusRec (intel_output->pDDCBus, TRUE, TRUE);
/* XXX sub module cleanup? */
xfree (intel_output);
}
}
static const xf86OutputFuncsRec i830_dvo_output_funcs = {
.dpms = i830_dvo_dpms,
.save = i830_dvo_save,
.restore = i830_dvo_restore,
.mode_valid = i830_dvo_mode_valid,
.pre_set_mode = i830_dvo_pre_set_mode,
.post_set_mode = i830_dvo_post_set_mode,
.detect = i830_dvo_detect,
.get_modes = i830_ddc_get_modes,
.destroy = i830_dvo_destroy
};
void
i830_dvo_init(ScrnInfoPtr pScrn)
{
I830Ptr pI830 = I830PTR(pScrn);
Bool ret;
int i = pI830->num_outputs;
xf86OutputPtr output;
I830OutputPrivatePtr intel_output;
int ret;
pI830->output[i].type = I830_OUTPUT_DVO;
pI830->output[i].dpms = i830_dvo_dpms;
pI830->output[i].save = i830_dvo_save;
pI830->output[i].restore = i830_dvo_restore;
pI830->output[i].mode_valid = i830_dvo_mode_valid;
pI830->output[i].pre_set_mode = i830_dvo_pre_set_mode;
pI830->output[i].post_set_mode = i830_dvo_post_set_mode;
pI830->output[i].detect = i830_dvo_detect;
pI830->output[i].get_modes = i830_ddc_get_modes;
/* Set up the I2C and DDC buses */
ret = I830I2CInit(pScrn, &pI830->output[i].pI2CBus, GPIOE, "DVOI2C_E");
if (!ret)
output = xf86OutputCreate (pScrn, &i830_dvo_output_funcs,
"ADD AGP card");
if (!output)
return;
intel_output = xnfcalloc (sizeof (I830OutputPrivateRec), 1);
if (!intel_output)
{
xf86OutputDestroy (output);
return;
}
intel_output->type = I830_OUTPUT_DVO;
output->driver_private = intel_output;
/* Set up the I2C and DDC buses */
ret = I830I2CInit(pScrn, &intel_output->pI2CBus, GPIOE, "DVOI2C_E");
if (!ret)
{
xf86OutputDestroy (output);
return;
}
ret = I830I2CInit(pScrn, &pI830->output[i].pDDCBus, GPIOD, "DVODDC_D");
if (!ret) {
xf86DestroyI2CBusRec(pI830->output[i].pI2CBus, TRUE, TRUE);
ret = I830I2CInit(pScrn, &intel_output->pDDCBus, GPIOD, "DVODDC_D");
if (!ret)
{
xf86OutputDestroy (output);
return;
}
/* Now, try to find a controller */
ret = I830I2CDetectDVOControllers(pScrn, pI830->output[i].pI2CBus,
&pI830->output[i].i2c_drv);
if (ret) {
ret = I830I2CDetectDVOControllers(pScrn, intel_output->pI2CBus,
&intel_output->i2c_drv);
if (ret)
{
xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Found i2c %s on %08lX\n",
pI830->output[i].i2c_drv->modulename,
pI830->output[i].pI2CBus->DriverPrivate.uval);
} else {
xf86DestroyI2CBusRec(pI830->output[i].pI2CBus, TRUE, TRUE);
xf86DestroyI2CBusRec(pI830->output[i].pDDCBus, TRUE, TRUE);
intel_output->i2c_drv->modulename,
intel_output->pI2CBus->DriverPrivate.uval);
}
else
{
xf86OutputDestroy (output);
return;
}
pI830->num_outputs++;
}

View File

@ -73,8 +73,10 @@ i830SetLVDSPanelPower(ScrnInfoPtr pScrn, Bool on)
}
static void
i830_lvds_dpms(ScrnInfoPtr pScrn, I830OutputPtr output, int mode)
i830_lvds_dpms (xf86OutputPtr output, int mode)
{
ScrnInfoPtr pScrn = output->scrn;
if (mode == DPMSModeOn)
i830SetLVDSPanelPower(pScrn, TRUE);
else
@ -82,9 +84,10 @@ i830_lvds_dpms(ScrnInfoPtr pScrn, I830OutputPtr output, int mode)
}
static void
i830_lvds_save(ScrnInfoPtr pScrn, I830OutputPtr output)
i830_lvds_save (xf86OutputPtr output)
{
I830Ptr pI830 = I830PTR(pScrn);
ScrnInfoPtr pScrn = output->scrn;
I830Ptr pI830 = I830PTR(pScrn);
pI830->savePP_ON = INREG(LVDSPP_ON);
pI830->savePP_OFF = INREG(LVDSPP_OFF);
@ -106,9 +109,10 @@ i830_lvds_save(ScrnInfoPtr pScrn, I830OutputPtr output)
}
static void
i830_lvds_restore(ScrnInfoPtr pScrn, I830OutputPtr output)
i830_lvds_restore(xf86OutputPtr output)
{
I830Ptr pI830 = I830PTR(pScrn);
ScrnInfoPtr pScrn = output->scrn;
I830Ptr pI830 = I830PTR(pScrn);
OUTREG(BLC_PWM_CTL, pI830->saveBLC_PWM_CTL);
OUTREG(LVDSPP_ON, pI830->savePP_ON);
@ -123,16 +127,15 @@ i830_lvds_restore(ScrnInfoPtr pScrn, I830OutputPtr output)
}
static int
i830_lvds_mode_valid(ScrnInfoPtr pScrn, I830OutputPtr output,
DisplayModePtr pMode)
i830_lvds_mode_valid(xf86OutputPtr output, DisplayModePtr pMode)
{
return MODE_OK;
}
static void
i830_lvds_pre_set_mode(ScrnInfoPtr pScrn, I830OutputPtr output,
DisplayModePtr pMode)
i830_lvds_pre_set_mode(xf86OutputPtr output, DisplayModePtr pMode)
{
ScrnInfoPtr pScrn = output->scrn;
/* Always make sure the LVDS is off before we play with DPLLs and pipe
* configuration. We can skip this in some cases (for example, going
* between hi-res modes with automatic panel scaling are fine), but be
@ -142,11 +145,11 @@ i830_lvds_pre_set_mode(ScrnInfoPtr pScrn, I830OutputPtr output,
}
static void
i830_lvds_post_set_mode(ScrnInfoPtr pScrn, I830OutputPtr output,
DisplayModePtr pMode)
i830_lvds_post_set_mode(xf86OutputPtr output, DisplayModePtr pMode)
{
I830Ptr pI830 = I830PTR(pScrn);
CARD32 pfit_control;
ScrnInfoPtr pScrn = output->scrn;
I830Ptr pI830 = I830PTR(pScrn);
CARD32 pfit_control;
/* Enable automatic panel scaling so that non-native modes fill the
* screen. Should be enabled before the pipe is enabled, according to
@ -182,7 +185,7 @@ i830_lvds_post_set_mode(ScrnInfoPtr pScrn, I830OutputPtr output,
* been set up if the LVDS was actually connected anyway.
*/
static enum detect_status
i830_lvds_detect(ScrnInfoPtr pScrn, I830OutputPtr output)
i830_lvds_detect(xf86OutputPtr output)
{
return OUTPUT_STATUS_CONNECTED;
}
@ -191,13 +194,14 @@ i830_lvds_detect(ScrnInfoPtr pScrn, I830OutputPtr output)
* Return the list of DDC modes if available, or the BIOS fixed mode otherwise.
*/
static DisplayModePtr
i830_lvds_get_modes(ScrnInfoPtr pScrn, I830OutputPtr output)
i830_lvds_get_modes(xf86OutputPtr output)
{
I830Ptr pI830 = I830PTR(pScrn);
DisplayModePtr modes, new;
char stmp[32];
ScrnInfoPtr pScrn = output->scrn;
I830Ptr pI830 = I830PTR(pScrn);
DisplayModePtr modes, new;
char stmp[32];
modes = i830_ddc_get_modes(pScrn, output);
modes = i830_ddc_get_modes(output);
if (modes != NULL)
return modes;
@ -220,10 +224,34 @@ i830_lvds_get_modes(ScrnInfoPtr pScrn, I830OutputPtr output)
return new;
}
static void
i830_lvds_destroy (xf86OutputPtr output)
{
I830OutputPrivatePtr intel_output = output->driver_private;
if (intel_output)
xfree (intel_output);
}
static const xf86OutputFuncsRec i830_lvds_output_funcs = {
.dpms = i830_lvds_dpms,
.save = i830_lvds_save,
.restore = i830_lvds_restore,
.mode_valid = i830_lvds_mode_valid,
.pre_set_mode = i830_lvds_pre_set_mode,
.post_set_mode = i830_lvds_post_set_mode,
.detect = i830_lvds_detect,
.get_modes = i830_lvds_get_modes,
.destroy = i830_lvds_destroy
};
void
i830_lvds_init(ScrnInfoPtr pScrn)
{
I830Ptr pI830 = I830PTR(pScrn);
I830Ptr pI830 = I830PTR(pScrn);
xf86OutputPtr output;
I830OutputPrivatePtr intel_output;
/* Get the LVDS fixed mode out of the BIOS. We should support LVDS with
* the BIOS being unavailable or broken, but lack the configuration options
@ -258,21 +286,20 @@ i830_lvds_init(ScrnInfoPtr pScrn)
}
}
pI830->output[pI830->num_outputs].type = I830_OUTPUT_LVDS;
pI830->output[pI830->num_outputs].dpms = i830_lvds_dpms;
pI830->output[pI830->num_outputs].save = i830_lvds_save;
pI830->output[pI830->num_outputs].restore = i830_lvds_restore;
pI830->output[pI830->num_outputs].mode_valid = i830_lvds_mode_valid;
pI830->output[pI830->num_outputs].pre_set_mode = i830_lvds_pre_set_mode;
pI830->output[pI830->num_outputs].post_set_mode = i830_lvds_post_set_mode;
pI830->output[pI830->num_outputs].detect = i830_lvds_detect;
pI830->output[pI830->num_outputs].get_modes = i830_lvds_get_modes;
output = xf86OutputCreate (pScrn, &i830_lvds_output_funcs, "Built-in LCD panel");
if (!output)
return;
intel_output = xnfcalloc (sizeof (I830OutputPrivateRec), 1);
if (!intel_output)
{
xf86OutputDestroy (output);
return;
}
intel_output->type = I830_OUTPUT_LVDS;
output->driver_private = intel_output;
/* Set up the LVDS DDC channel. Most panels won't support it, but it can
* be useful if available.
*/
I830I2CInit(pScrn, &pI830->output[pI830->num_outputs].pDDCBus,
GPIOC, "LVDSDDC_C");
pI830->num_outputs++;
I830I2CInit(pScrn, &intel_output->pDDCBus, GPIOC, "LVDSDDC_C");
}

View File

@ -113,47 +113,44 @@ i830_reprobe_output_modes(ScrnInfoPtr pScrn)
int i;
/* Re-probe the list of modes for each output. */
for (i = 0; i < pI830->num_outputs; i++) {
for (i = 0; i < pI830->xf86_config.num_output; i++)
{
xf86OutputPtr output = pI830->xf86_config.output[i];
DisplayModePtr mode;
while (pI830->output[i].probed_modes != NULL) {
xf86DeleteMode(&pI830->output[i].probed_modes,
pI830->output[i].probed_modes);
}
while (output->probed_modes != NULL)
xf86DeleteMode(&output->probed_modes, output->probed_modes);
pI830->output[i].probed_modes =
pI830->output[i].get_modes(pScrn, &pI830->output[i]);
output->probed_modes = (*output->funcs->get_modes) (output);
/* Set the DDC properties to whatever first output has DDC information.
*/
if (pI830->output[i].MonInfo != NULL && !properties_set) {
xf86SetDDCproperties(pScrn, pI830->output[i].MonInfo);
if (output->MonInfo != NULL && !properties_set) {
xf86SetDDCproperties(pScrn, output->MonInfo);
properties_set = TRUE;
}
if (pI830->output[i].probed_modes != NULL) {
if (output->probed_modes != NULL)
{
/* silently prune modes down to ones matching the user's
* configuration.
*/
i830xf86ValidateModesUserConfig(pScrn,
pI830->output[i].probed_modes);
i830xf86PruneInvalidModes(pScrn, &pI830->output[i].probed_modes,
FALSE);
i830xf86ValidateModesUserConfig(pScrn, output->probed_modes);
i830xf86PruneInvalidModes(pScrn, &output->probed_modes, FALSE);
}
#ifdef DEBUG_REPROBE
if (pI830->output[i].probed_modes != NULL) {
if (output->probed_modes != NULL) {
xf86DrvMsg(pScrn->scrnIndex, X_INFO,
"Printing probed modes for output %s\n",
i830_output_type_names[pI830->output[i].type]);
output->name);
} else {
xf86DrvMsg(pScrn->scrnIndex, X_INFO,
"No remaining probed modes for output %s\n",
i830_output_type_names[pI830->output[i].type]);
output->name);
}
#endif
for (mode = pI830->output[i].probed_modes; mode != NULL;
mode = mode->next)
for (mode = output->probed_modes; mode != NULL; mode = mode->next)
{
/* The code to choose the best mode per pipe later on will require
* VRefresh to be set.
@ -200,15 +197,15 @@ i830_set_xf86_modes_from_outputs(ScrnInfoPtr pScrn)
* pScrn->modes should only be used for XF86VidMode now, which we don't
* care about enough to make some sort of unioned list.
*/
for (i = 0; i < pI830->num_outputs; i++) {
if (pI830->output[i].probed_modes != NULL) {
pScrn->modes =
xf86DuplicateModes(pScrn, pI830->output[i].probed_modes);
for (i = 0; i < pI830->xf86_config.num_output; i++) {
xf86OutputPtr output = pI830->xf86_config.output[i];
if (output->probed_modes != NULL) {
pScrn->modes = xf86DuplicateModes(pScrn, output->probed_modes);
break;
}
}
I830GetOriginalVirtualSize(pScrn, &originalVirtualX, &originalVirtualY);
xf86RandR12GetOriginalVirtualSize(pScrn, &originalVirtualX, &originalVirtualY);
/* Disable modes in the XFree86 DDX list that are larger than the current
* virtual size.
@ -253,11 +250,11 @@ i830_set_default_screen_size(ScrnInfoPtr pScrn)
/* Set up a virtual size that will cover any clone mode we'd want to
* set for the currently-connected outputs.
*/
for (i = 0; i < pI830->num_outputs; i++) {
for (i = 0; i < pI830->xf86_config.num_output; i++) {
xf86OutputPtr output = pI830->xf86_config.output[i];
DisplayModePtr mode;
for (mode = pI830->output[i].probed_modes; mode != NULL;
mode = mode->next)
for (mode = output->probed_modes; mode != NULL; mode = mode->next)
{
if (mode->HDisplay > maxX)
maxX = mode->HDisplay;
@ -304,8 +301,7 @@ I830ValidateXF86ModeList(ScrnInfoPtr pScrn, Bool first_time)
#define EDID_ATOM_NAME "EDID_DATA"
static void
i830_ddc_set_edid_property(ScrnInfoPtr pScrn, I830OutputPtr output,
void *data, int data_len)
i830_ddc_set_edid_property(xf86OutputPtr output, void *data, int data_len)
{
Atom edid_atom = MakeAtom(EDID_ATOM_NAME, sizeof(EDID_ATOM_NAME), TRUE);
@ -326,16 +322,18 @@ i830_ddc_set_edid_property(ScrnInfoPtr pScrn, I830OutputPtr output,
* Generic get_modes function using DDC, used by many outputs.
*/
DisplayModePtr
i830_ddc_get_modes(ScrnInfoPtr pScrn, I830OutputPtr output)
i830_ddc_get_modes(xf86OutputPtr output)
{
ScrnInfoPtr pScrn = output->scrn;
I830OutputPrivatePtr intel_output = output->driver_private;
xf86MonPtr ddc_mon;
DisplayModePtr ddc_modes, mode;
int i;
ddc_mon = xf86DoEDID_DDC2(pScrn->scrnIndex, output->pDDCBus);
ddc_mon = xf86DoEDID_DDC2(pScrn->scrnIndex, intel_output->pDDCBus);
if (ddc_mon == NULL) {
#ifdef RANDR_12_INTERFACE
i830_ddc_set_edid_property(pScrn, output, NULL, 0);
i830_ddc_set_edid_property(output, NULL, 0);
#endif
return NULL;
}
@ -346,24 +344,23 @@ i830_ddc_get_modes(ScrnInfoPtr pScrn, I830OutputPtr output)
#ifdef RANDR_12_INTERFACE
if (output->MonInfo->ver.version == 1) {
i830_ddc_set_edid_property(pScrn, output, ddc_mon->rawData, 128);
i830_ddc_set_edid_property(output, ddc_mon->rawData, 128);
} else if (output->MonInfo->ver.version == 2) {
i830_ddc_set_edid_property(pScrn, output, ddc_mon->rawData, 256);
i830_ddc_set_edid_property(output, ddc_mon->rawData, 256);
} else {
i830_ddc_set_edid_property(pScrn, output, NULL, 0);
i830_ddc_set_edid_property(output, NULL, 0);
}
#endif
/* Debug info for now, at least */
xf86DrvMsg(pScrn->scrnIndex, X_INFO, "EDID for output %s\n",
i830_output_type_names[output->type]);
xf86DrvMsg(pScrn->scrnIndex, X_INFO, "EDID for output %s\n", output->name);
xf86PrintEDID(output->MonInfo);
ddc_modes = xf86DDCGetModes(pScrn->scrnIndex, ddc_mon);
/* Strip out any modes that can't be supported on this output. */
for (mode = ddc_modes; mode != NULL; mode = mode->next) {
int status = output->mode_valid(pScrn, output, mode);
int status = (*output->funcs->mode_valid)(output, mode);
if (status != MODE_OK)
mode->status = status;

View File

@ -39,11 +39,12 @@
#include <randrstr.h>
#include <X11/extensions/render.h>
#include "i830.h"
#include "i830_xf86Modes.h"
#include "i830_xf86Crtc.h"
#include "i830_randr.h"
#include "i830_display.h"
#include "i830.h"
typedef struct _i830RandRInfo {
typedef struct _xf86RandR12Info {
int virtualX;
int virtualY;
int mmWidth;
@ -52,24 +53,21 @@ typedef struct _i830RandRInfo {
int maxY;
Rotation rotation; /* current mode */
Rotation supported_rotations; /* driver supported */
#ifdef RANDR_12_INTERFACE
DisplayModePtr modes[MAX_DISPLAY_PIPES];
#endif
} XF86RandRInfoRec, *XF86RandRInfoPtr;
#ifdef RANDR_12_INTERFACE
static Bool I830RandRInit12 (ScreenPtr pScreen);
static Bool I830RandRCreateScreenResources12 (ScreenPtr pScreen);
static Bool xf86RandR12Init12 (ScreenPtr pScreen);
static Bool xf86RandR12CreateScreenResources12 (ScreenPtr pScreen);
#endif
static int i830RandRIndex;
static int i830RandRGeneration;
static int xf86RandR12Index;
static int xf86RandR12Generation;
#define XF86RANDRINFO(p) \
((XF86RandRInfoPtr)(p)->devPrivates[i830RandRIndex].ptr)
((XF86RandRInfoPtr)(p)->devPrivates[xf86RandR12Index].ptr)
static int
I830RandRModeRefresh (DisplayModePtr mode)
xf86RandR12ModeRefresh (DisplayModePtr mode)
{
if (mode->VRefresh)
return (int) (mode->VRefresh + 0.5);
@ -78,7 +76,7 @@ I830RandRModeRefresh (DisplayModePtr mode)
}
static Bool
I830RandRGetInfo (ScreenPtr pScreen, Rotation *rotations)
xf86RandR12GetInfo (ScreenPtr pScreen, Rotation *rotations)
{
RRScreenSizePtr pSize;
ScrnInfoPtr scrp = XF86SCRNINFO(pScreen);
@ -100,7 +98,7 @@ I830RandRGetInfo (ScreenPtr pScreen, Rotation *rotations)
for (mode = scrp->modes; ; mode = mode->next)
{
int refresh = I830RandRModeRefresh (mode);
int refresh = xf86RandR12ModeRefresh (mode);
if (randrp->maxX == 0 || randrp->maxY == 0)
{
if (maxX < mode->HDisplay)
@ -154,7 +152,7 @@ I830RandRGetInfo (ScreenPtr pScreen, Rotation *rotations)
}
static Bool
I830RandRSetMode (ScreenPtr pScreen,
xf86RandR12SetMode (ScreenPtr pScreen,
DisplayModePtr mode,
Bool useVirtual,
int mmWidth,
@ -243,7 +241,7 @@ I830RandRSetMode (ScreenPtr pScreen,
}
Bool
I830RandRSetConfig (ScreenPtr pScreen,
xf86RandR12SetConfig (ScreenPtr pScreen,
Rotation rotation,
int rate,
RRScreenSizePtr pSize)
@ -276,7 +274,7 @@ I830RandRSetConfig (ScreenPtr pScreen,
}
if (mode->HDisplay == pSize->width &&
mode->VDisplay == pSize->height &&
(rate == 0 || I830RandRModeRefresh (mode) == rate))
(rate == 0 || xf86RandR12ModeRefresh (mode) == rate))
break;
if (mode->next == scrp->modes)
{
@ -302,7 +300,7 @@ I830RandRSetConfig (ScreenPtr pScreen,
randrp->maxY = maxY;
}
if (!I830RandRSetMode (pScreen, mode, useVirtual, pSize->mmWidth,
if (!xf86RandR12SetMode (pScreen, mode, useVirtual, pSize->mmWidth,
pSize->mmHeight)) {
randrp->rotation = oldRotation;
return FALSE;
@ -325,7 +323,7 @@ I830RandRSetConfig (ScreenPtr pScreen,
}
Rotation
I830GetRotation(ScreenPtr pScreen)
xf86RandR12GetRotation(ScreenPtr pScreen)
{
XF86RandRInfoPtr randrp = XF86RANDRINFO(pScreen);
@ -333,19 +331,23 @@ I830GetRotation(ScreenPtr pScreen)
}
Bool
I830RandRCreateScreenResources (ScreenPtr pScreen)
xf86RandR12CreateScreenResources (ScreenPtr pScreen)
{
#if 0
ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
I830Ptr pI830 = I830PTR(pScrn);
I830Ptr pI830 = I830PTR(pScrn);
#endif
#ifdef PANORAMIX
/* XXX disable RandR when using Xinerama */
if (!noPanoramiXExtension)
return TRUE;
#endif
#if RANDR_12_INTERFACE
if (I830RandRCreateScreenResources12 (pScreen))
if (xf86RandR12CreateScreenResources12 (pScreen))
return TRUE;
#endif
#if 0
/* XXX deal with initial rotation */
if (pI830->rotation != RR_Rotate_0) {
RRScreenSize p;
Rotation requestedRotation = pI830->rotation;
@ -359,15 +361,16 @@ I830RandRCreateScreenResources (ScreenPtr pScreen)
p.mmHeight = pScreen->mmHeight;
pI830->starting = TRUE; /* abuse this for dual head & rotation */
I830RandRSetConfig (pScreen, requestedRotation, 0, &p);
xf86RandR12SetConfig (pScreen, requestedRotation, 0, &p);
pI830->starting = FALSE;
}
#endif
return TRUE;
}
Bool
I830RandRInit (ScreenPtr pScreen, int rotation)
xf86RandR12Init (ScreenPtr pScreen)
{
rrScrPrivPtr rp;
XF86RandRInfoPtr randrp;
@ -377,10 +380,10 @@ I830RandRInit (ScreenPtr pScreen, int rotation)
if (!noPanoramiXExtension)
return TRUE;
#endif
if (i830RandRGeneration != serverGeneration)
if (xf86RandR12Generation != serverGeneration)
{
i830RandRIndex = AllocateScreenPrivateIndex();
i830RandRGeneration = serverGeneration;
xf86RandR12Index = AllocateScreenPrivateIndex();
xf86RandR12Generation = serverGeneration;
}
randrp = xalloc (sizeof (XF86RandRInfoRec));
@ -393,8 +396,8 @@ I830RandRInit (ScreenPtr pScreen, int rotation)
return FALSE;
}
rp = rrGetScrPriv(pScreen);
rp->rrGetInfo = I830RandRGetInfo;
rp->rrSetConfig = I830RandRSetConfig;
rp->rrGetInfo = xf86RandR12GetInfo;
rp->rrSetConfig = xf86RandR12SetConfig;
randrp->virtualX = -1;
randrp->virtualY = -1;
@ -403,25 +406,33 @@ I830RandRInit (ScreenPtr pScreen, int rotation)
randrp->rotation = RR_Rotate_0; /* initial rotated mode */
randrp->supported_rotations = rotation;
randrp->supported_rotations = RR_Rotate_0;
randrp->maxX = randrp->maxY = 0;
pScreen->devPrivates[i830RandRIndex].ptr = randrp;
pScreen->devPrivates[xf86RandR12Index].ptr = randrp;
#if RANDR_12_INTERFACE
if (!I830RandRInit12 (pScreen))
if (!xf86RandR12Init12 (pScreen))
return FALSE;
#endif
return TRUE;
}
void
I830GetOriginalVirtualSize(ScrnInfoPtr pScrn, int *x, int *y)
xf86RandR12SetRotations (ScreenPtr pScreen, Rotation rotations)
{
XF86RandRInfoPtr randrp = XF86RANDRINFO(pScreen);
randrp->supported_rotations = rotations;
}
void
xf86RandR12GetOriginalVirtualSize(ScrnInfoPtr pScrn, int *x, int *y)
{
ScreenPtr pScreen = screenInfo.screens[pScrn->scrnIndex];
if (i830RandRGeneration != serverGeneration ||
if (xf86RandR12Generation != serverGeneration ||
XF86RANDRINFO(pScreen)->virtualX == -1)
{
*x = pScrn->virtualX;
@ -436,7 +447,7 @@ I830GetOriginalVirtualSize(ScrnInfoPtr pScrn, int *x, int *y)
#if RANDR_12_INTERFACE
static Bool
I830RandRScreenSetSize (ScreenPtr pScreen,
xf86RandR12ScreenSetSize (ScreenPtr pScreen,
CARD16 width,
CARD16 height,
CARD32 mmWidth,
@ -472,155 +483,131 @@ I830RandRScreenSetSize (ScreenPtr pScreen,
}
static Bool
I830RandRCrtcNotify (RRCrtcPtr crtc)
xf86RandR12CrtcNotify (RRCrtcPtr randr_crtc)
{
ScreenPtr pScreen = crtc->pScreen;
ScreenPtr pScreen = randr_crtc->pScreen;
ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
I830Ptr pI830 = I830PTR(pScrn);
RRModePtr mode = NULL;
RRModePtr randr_mode = NULL;
int x;
int y;
Rotation rotation;
int numOutputs;
RROutputPtr outputs[MAX_OUTPUTS];
struct _I830OutputRec *output;
RROutputPtr rrout;
int pipe = (int) crtc->devPrivate;
I830PipePtr pI830Pipe = &pI830->pipes[pipe];
RROutputPtr randr_outputs[MAX_OUTPUTS];
RROutputPtr randr_output;
xf86CrtcPtr crtc = randr_crtc->devPrivate;
xf86OutputPtr output;
int i, j;
DisplayModePtr pipeMode = &pI830Pipe->curMode;
DisplayModePtr curMode = &crtc->curMode;
x = pI830Pipe->x;
y = pI830Pipe->y;
x = crtc->x;
y = crtc->y;
rotation = RR_Rotate_0;
numOutputs = 0;
mode = NULL;
for (i = 0; i < pI830->num_outputs; i++)
randr_mode = NULL;
for (i = 0; i < pI830->xf86_config.num_output; i++)
{
output = &pI830->output[i];
if (output->enabled && output->pipe == pipe)
output = pI830->xf86_config.output[i];
if (output->crtc == crtc)
{
rrout = output->randr_output;
outputs[numOutputs++] = rrout;
randr_output = output->randr_output;
randr_outputs[numOutputs++] = randr_output;
/*
* We make copies of modes, so pointer equality
* isn't sufficient
*/
for (j = 0; j < rrout->numModes; j++)
for (j = 0; j < randr_output->numModes; j++)
{
DisplayModePtr outMode = rrout->modes[j]->devPrivate;
if (xf86ModesEqual(pipeMode, outMode))
DisplayModePtr outMode = randr_output->modes[j]->devPrivate;
if (xf86ModesEqual(curMode, outMode))
{
mode = rrout->modes[j];
randr_mode = randr_output->modes[j];
break;
}
}
}
}
return RRCrtcNotify (crtc, mode, x, y, rotation, numOutputs, outputs);
return RRCrtcNotify (randr_crtc, randr_mode, x, y,
rotation, numOutputs, randr_outputs);
}
static Bool
I830RandRCrtcSet (ScreenPtr pScreen,
RRCrtcPtr crtc,
RRModePtr mode,
xf86RandR12CrtcSet (ScreenPtr pScreen,
RRCrtcPtr randr_crtc,
RRModePtr randr_mode,
int x,
int y,
Rotation rotation,
int num_randr_outputs,
RROutputPtr *randr_outputs)
{
XF86RandRInfoPtr randrp = XF86RANDRINFO(pScreen);
ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
I830Ptr pI830 = I830PTR(pScrn);
int pipe = (int) (crtc->devPrivate);
I830PipePtr pI830Pipe = &pI830->pipes[pipe];
DisplayModePtr display_mode = mode ? mode->devPrivate : NULL;
xf86CrtcPtr crtc = randr_crtc->devPrivate;
DisplayModePtr mode = randr_mode ? randr_mode->devPrivate : NULL;
Bool changed = FALSE;
Bool disable = FALSE;
int o, ro;
struct {
int pipe;
int enabled;
} save_output[MAX_OUTPUTS];
Bool save_enabled = pI830Pipe->enabled;
xf86CrtcPtr save_crtcs[MAX_OUTPUTS];
Bool save_enabled = crtc->enabled;
if (display_mode != randrp->modes[pipe])
{
if (!xf86ModesEqual (&crtc->curMode, mode))
changed = TRUE;
if (!display_mode)
disable = TRUE;
}
for (o = 0; o < pI830->num_outputs; o++)
for (o = 0; o < pI830->xf86_config.num_output; o++)
{
I830OutputPtr output = &pI830->output[o];
RROutputPtr randr_output = NULL;
xf86OutputPtr output = pI830->xf86_config.output[o];
xf86CrtcPtr new_crtc;
save_crtcs[o] = output->crtc;
save_output[o].enabled = output->enabled;
save_output[o].pipe = output->pipe;
if (output->crtc == crtc)
new_crtc = NULL;
else
new_crtc = output->crtc;
for (ro = 0; ro < num_randr_outputs; ro++)
{
if (output->randr_output == randr_outputs[ro])
{
randr_output = randr_outputs[ro];
new_crtc = crtc;
break;
}
}
if (randr_output)
if (new_crtc != output->crtc)
{
if (output->pipe != pipe || !output->enabled)
{
output->pipe = pipe;
output->enabled = TRUE;
changed = TRUE;
}
}
else
{
/* Disable outputs which were on this pipe */
if (output->enabled && output->pipe == pipe)
{
output->enabled = FALSE;
changed = TRUE;
disable = TRUE;
}
changed = TRUE;
output->crtc = new_crtc;
}
}
if (changed)
{
pI830Pipe->enabled = mode != NULL;
crtc->enabled = mode != NULL;
/* Sync the engine before adjust mode */
if (pI830->AccelInfoRec && pI830->AccelInfoRec->NeedToSync) {
(*pI830->AccelInfoRec->Sync)(pScrn);
pI830->AccelInfoRec->NeedToSync = FALSE;
}
if (display_mode)
if (mode)
{
if (!i830PipeSetMode (pScrn, display_mode, pipe, TRUE))
if (!i830PipeSetMode (crtc, mode, TRUE))
{
pI830Pipe->enabled = save_enabled;
for (o = 0; o < pI830->num_outputs; o++)
crtc->enabled = save_enabled;
for (o = 0; o < pI830->xf86_config.num_output; o++)
{
I830OutputPtr output = &pI830->output[o];
output->enabled = save_output[o].enabled;
output->pipe = save_output[o].pipe;
xf86OutputPtr output = pI830->xf86_config.output[o];
output->crtc = save_crtcs[o];
}
return FALSE;
}
pI830Pipe->desiredMode = *display_mode;
i830PipeSetBase(pScrn, pipe, x, y);
crtc->desiredMode = *mode;
i830PipeSetBase(crtc, x, y);
}
randrp->modes[pipe] = display_mode;
if (disable)
i830DisableUnusedFunctions (pScrn);
i830DisableUnusedFunctions (pScrn);
}
return I830RandRCrtcNotify (crtc);
return xf86RandR12CrtcNotify (randr_crtc);
}
static Bool
I830RandRCrtcSetGamma (ScreenPtr pScreen,
xf86RandR12CrtcSetGamma (ScreenPtr pScreen,
RRCrtcPtr crtc)
{
return FALSE;
@ -690,29 +677,27 @@ I830xf86RROutputSetModes (RROutputPtr randr_output, DisplayModePtr modes)
* Mirror the current mode configuration to RandR
*/
static Bool
I830RandRSetInfo12 (ScrnInfoPtr pScrn)
xf86RandR12SetInfo12 (ScrnInfoPtr pScrn)
{
I830Ptr pI830 = I830PTR(pScrn);
RROutputPtr clones[MAX_OUTPUTS];
RRCrtcPtr crtcs[MAX_DISPLAY_PIPES];
int ncrtc;
I830OutputPtr output;
int o, c, p;
int clone_types;
int crtc_types;
int subpixel;
RRCrtcPtr randr_crtc;
RROutputPtr randr_output;
int nclone;
for (o = 0; o < pI830->num_outputs; o++)
for (o = 0; o < pI830->xf86_config.num_output; o++)
{
output = &pI830->output[o];
randr_output = output->randr_output;
xf86OutputPtr output = pI830->xf86_config.output[o];
I830OutputPrivatePtr intel_output = output->driver_private;
/*
* Valid crtcs
*/
switch (output->type) {
switch (intel_output->type) {
case I830_OUTPUT_DVO:
case I830_OUTPUT_SDVO:
crtc_types = ((1 << 0)|
@ -747,12 +732,12 @@ I830RandRSetInfo12 (ScrnInfoPtr pScrn)
break;
}
ncrtc = 0;
for (p = 0; p < pI830->num_pipes; p++)
for (p = 0; p < pI830->xf86_config.num_crtc; p++)
if (crtc_types & (1 << p))
crtcs[ncrtc++] = pI830->pipes[p].randr_crtc;
crtcs[ncrtc++] = pI830->xf86_config.crtc[p]->randr_crtc;
if (output->enabled)
randr_crtc = pI830->pipes[output->pipe].randr_crtc;
if (output->crtc)
randr_crtc = output->crtc->randr_crtc;
else
randr_crtc = NULL;
@ -765,7 +750,7 @@ I830RandRSetInfo12 (ScrnInfoPtr pScrn)
output->mm_height);
I830xf86RROutputSetModes (output->randr_output, output->probed_modes);
switch (output->detect(pScrn, output)) {
switch ((*output->funcs->detect)(output)) {
case OUTPUT_STATUS_CONNECTED:
RROutputSetConnection (output->randr_output, RR_Connected);
break;
@ -783,10 +768,13 @@ I830RandRSetInfo12 (ScrnInfoPtr pScrn)
* Valid clones
*/
nclone = 0;
for (c = 0; c < pI830->num_outputs; c++)
for (c = 0; c < pI830->xf86_config.num_output; c++)
{
if (o != c && ((1 << pI830->output[c].type) & clone_types))
clones[nclone++] = pI830->output[c].randr_output;
xf86OutputPtr clone = pI830->xf86_config.output[c];
I830OutputPrivatePtr intel_clone = clone->driver_private;
if (o != c && ((1 << intel_clone->type) & clone_types))
clones[nclone++] = clone->randr_output;
}
if (!RROutputSetClones (output->randr_output, clones, nclone))
return FALSE;
@ -799,53 +787,38 @@ I830RandRSetInfo12 (ScrnInfoPtr pScrn)
* that to RandR
*/
static Bool
I830RandRGetInfo12 (ScreenPtr pScreen, Rotation *rotations)
xf86RandR12GetInfo12 (ScreenPtr pScreen, Rotation *rotations)
{
ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
i830_reprobe_output_modes(pScrn);
return I830RandRSetInfo12 (pScrn);
return xf86RandR12SetInfo12 (pScrn);
}
static Bool
I830RandRCreateObjects12 (ScrnInfoPtr pScrn)
xf86RandR12CreateObjects12 (ScrnInfoPtr pScrn)
{
I830Ptr pI830 = I830PTR(pScrn);
int p;
int o;
if (!RRInit ())
return FALSE;
/*
* Create RandR resources, then probe them
* Configure crtcs
*/
for (p = 0; p < pI830->num_pipes; p++)
for (p = 0; p < pI830->xf86_config.num_crtc; p++)
{
I830PipePtr pipe = &pI830->pipes[p];
RRCrtcPtr randr_crtc = RRCrtcCreate ((void *) p);
xf86CrtcPtr crtc = pI830->xf86_config.crtc[p];
if (!randr_crtc)
return FALSE;
RRCrtcGammaSetSize (randr_crtc, 256);
pipe->randr_crtc = randr_crtc;
RRCrtcGammaSetSize (crtc->randr_crtc, 256);
}
for (o = 0; o < pI830->num_outputs; o++)
{
I830OutputPtr output = &pI830->output[o];
const char *name = i830_output_type_names[output->type];
RROutputPtr randr_output = RROutputCreate (name, strlen (name),
(void *) o);
if (!randr_output)
return FALSE;
output->randr_output = randr_output;
}
return TRUE;
}
static Bool
I830RandRCreateScreenResources12 (ScreenPtr pScreen)
xf86RandR12CreateScreenResources12 (ScreenPtr pScreen)
{
XF86RandRInfoPtr randrp = XF86RANDRINFO(pScreen);
ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
@ -856,27 +829,28 @@ I830RandRCreateScreenResources12 (ScreenPtr pScreen)
/*
* Attach RandR objects to screen
*/
for (p = 0; p < pI830->num_pipes; p++)
if (!RRCrtcAttachScreen (pI830->pipes[p].randr_crtc, pScreen))
for (p = 0; p < pI830->xf86_config.num_crtc; p++)
if (!RRCrtcAttachScreen (pI830->xf86_config.crtc[p]->randr_crtc, pScreen))
return FALSE;
for (o = 0; o < pI830->num_outputs; o++)
if (!RROutputAttachScreen (pI830->output[o].randr_output, pScreen))
for (o = 0; o < pI830->xf86_config.num_output; o++)
if (!RROutputAttachScreen (pI830->xf86_config.output[o]->randr_output, pScreen))
return FALSE;
/*
* Compute width of screen
*/
width = 0; height = 0;
for (p = 0; p < pI830->num_pipes; p++)
for (p = 0; p < pI830->xf86_config.num_crtc; p++)
{
I830PipePtr pipe = &pI830->pipes[p];
int pipe_width = pipe->x + pipe->curMode.HDisplay;
int pipe_height = pipe->y + pipe->curMode.VDisplay;
if (pipe->enabled && pipe_width > width)
width = pipe_width;
if (pipe->enabled && pipe_height > height)
height = pipe_height;
xf86CrtcPtr crtc = pI830->xf86_config.crtc[p];
int crtc_width = crtc->x + crtc->curMode.HDisplay;
int crtc_height = crtc->y + crtc->curMode.VDisplay;
if (crtc->enabled && crtc_width > width)
width = crtc_width;
if (crtc->enabled && crtc_height > height)
height = crtc_height;
}
if (width && height)
@ -892,15 +866,15 @@ I830RandRCreateScreenResources12 (ScreenPtr pScreen)
xf86DrvMsg(pScrn->scrnIndex, X_INFO,
"Setting screen physical size to %d x %d\n",
mmWidth, mmHeight);
I830RandRScreenSetSize (pScreen,
xf86RandR12ScreenSetSize (pScreen,
width,
height,
mmWidth,
mmHeight);
}
for (p = 0; p < pI830->num_pipes; p++)
I830RandRCrtcNotify (pI830->pipes[p].randr_crtc);
for (p = 0; p < pI830->xf86_config.num_crtc; p++)
xf86RandR12CrtcNotify (pI830->xf86_config.crtc[p]->randr_crtc);
if (randrp->virtualX == -1 || randrp->virtualY == -1)
{
@ -914,22 +888,22 @@ I830RandRCreateScreenResources12 (ScreenPtr pScreen)
}
static void
I830RandRPointerMoved (int scrnIndex, int x, int y)
xf86RandR12PointerMoved (int scrnIndex, int x, int y)
{
}
static Bool
I830RandRInit12 (ScreenPtr pScreen)
xf86RandR12Init12 (ScreenPtr pScreen)
{
ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
rrScrPrivPtr rp = rrGetScrPriv(pScreen);
rp->rrGetInfo = I830RandRGetInfo12;
rp->rrScreenSetSize = I830RandRScreenSetSize;
rp->rrCrtcSet = I830RandRCrtcSet;
rp->rrCrtcSetGamma = I830RandRCrtcSetGamma;
rp->rrGetInfo = xf86RandR12GetInfo12;
rp->rrScreenSetSize = xf86RandR12ScreenSetSize;
rp->rrCrtcSet = xf86RandR12CrtcSet;
rp->rrCrtcSetGamma = xf86RandR12CrtcSetGamma;
rp->rrSetConfig = NULL;
pScrn->PointerMoved = I830RandRPointerMoved;
pScrn->PointerMoved = xf86RandR12PointerMoved;
return TRUE;
}
@ -1003,7 +977,7 @@ static int
I830RRPickCrtcs (RROutputPtr *outputs,
RRCrtcPtr *best_crtcs,
RRModePtr *modes,
int num_outputs,
int num_output,
int n)
{
int c, o, l;
@ -1015,7 +989,7 @@ I830RRPickCrtcs (RROutputPtr *outputs,
int score;
int my_score;
if (n == num_outputs)
if (n == num_output)
return 0;
output = outputs[n];
@ -1024,11 +998,11 @@ I830RRPickCrtcs (RROutputPtr *outputs,
*/
best_crtcs[n] = NULL;
best_crtc = NULL;
best_score = I830RRPickCrtcs (outputs, best_crtcs, modes, num_outputs, n+1);
best_score = I830RRPickCrtcs (outputs, best_crtcs, modes, num_output, n+1);
if (modes[n] == NULL)
return best_score;
crtcs = xalloc (num_outputs * sizeof (RRCrtcPtr));
crtcs = xalloc (num_output * sizeof (RRCrtcPtr));
if (!crtcs)
return best_score;
@ -1074,12 +1048,12 @@ I830RRPickCrtcs (RROutputPtr *outputs,
crtcs[n] = crtc;
memcpy (crtcs, best_crtcs, n * sizeof (RRCrtcPtr));
score = my_score + I830RRPickCrtcs (outputs, crtcs, modes,
num_outputs, n+1);
num_output, n+1);
if (score >= best_score)
{
best_crtc = crtc;
best_score = score;
memcpy (best_crtcs, crtcs, num_outputs * sizeof (RRCrtcPtr));
memcpy (best_crtcs, crtcs, num_output * sizeof (RRCrtcPtr));
}
}
xfree (crtcs);
@ -1090,18 +1064,18 @@ static Bool
I830RRInitialConfiguration (RROutputPtr *outputs,
RRCrtcPtr *crtcs,
RRModePtr *modes,
int num_outputs)
int num_output)
{
int o;
RRModePtr target_mode = NULL;
for (o = 0; o < num_outputs; o++)
for (o = 0; o < num_output; o++)
modes[o] = NULL;
/*
* Let outputs with preferred modes drive screen size
*/
for (o = 0; o < num_outputs; o++)
for (o = 0; o < num_output; o++)
{
RROutputPtr output = outputs[o];
@ -1117,7 +1091,7 @@ I830RRInitialConfiguration (RROutputPtr *outputs,
}
if (!target_mode)
{
for (o = 0; o < num_outputs; o++)
for (o = 0; o < num_output; o++)
{
RROutputPtr output = outputs[o];
if (output->connection != RR_Disconnected)
@ -1131,7 +1105,7 @@ I830RRInitialConfiguration (RROutputPtr *outputs,
}
}
}
for (o = 0; o < num_outputs; o++)
for (o = 0; o < num_output; o++)
{
RROutputPtr output = outputs[o];
@ -1139,7 +1113,7 @@ I830RRInitialConfiguration (RROutputPtr *outputs,
modes[o] = I830ClosestMode (output, target_mode);
}
if (!I830RRPickCrtcs (outputs, crtcs, modes, num_outputs, 0))
if (!I830RRPickCrtcs (outputs, crtcs, modes, num_output, 0))
return FALSE;
return TRUE;
@ -1151,7 +1125,7 @@ I830RRInitialConfiguration (RROutputPtr *outputs,
*/
static void
I830RRDefaultScreenLimits (RROutputPtr *outputs, int num_outputs,
I830RRDefaultScreenLimits (RROutputPtr *outputs, int num_output,
RRCrtcPtr *crtcs, int num_crtc,
int *widthp, int *heightp)
{
@ -1166,7 +1140,7 @@ I830RRDefaultScreenLimits (RROutputPtr *outputs, int num_outputs,
RRCrtcPtr crtc = crtcs[c];
int crtc_width = 1600, crtc_height = 1200;
for (o = 0; o < num_outputs; o++)
for (o = 0; o < num_output; o++)
{
RROutputPtr output = outputs[o];
@ -1195,7 +1169,7 @@ I830RRDefaultScreenLimits (RROutputPtr *outputs, int num_outputs,
#endif
Bool
I830RandRPreInit (ScrnInfoPtr pScrn)
xf86RandR12PreInit (ScrnInfoPtr pScrn)
{
I830Ptr pI830 = I830PTR(pScrn);
#if RANDR_12_INTERFACE
@ -1208,35 +1182,35 @@ I830RandRPreInit (ScrnInfoPtr pScrn)
int c;
#endif
if (pI830->num_outputs <= 0)
if (pI830->xf86_config.num_output <= 0)
return FALSE;
i830_reprobe_output_modes(pScrn);
#if RANDR_12_INTERFACE
if (!I830RandRCreateObjects12 (pScrn))
if (!xf86RandR12CreateObjects12 (pScrn))
return FALSE;
/*
* Configure output modes
*/
if (!I830RandRSetInfo12 (pScrn))
if (!xf86RandR12SetInfo12 (pScrn))
return FALSE;
/*
* With RandR info set up, let RandR choose
* the initial configuration
*/
for (o = 0; o < pI830->num_outputs; o++)
outputs[o] = pI830->output[o].randr_output;
for (c = 0; c < pI830->num_pipes; c++)
crtcs[c] = pI830->pipes[c].randr_crtc;
for (o = 0; o < pI830->xf86_config.num_output; o++)
outputs[o] = pI830->xf86_config.output[o]->randr_output;
for (c = 0; c < pI830->xf86_config.num_crtc; c++)
crtcs[c] = pI830->xf86_config.crtc[c]->randr_crtc;
if (!I830RRInitialConfiguration (outputs, output_crtcs, output_modes,
pI830->num_outputs))
pI830->xf86_config.num_output))
return FALSE;
I830RRDefaultScreenLimits (outputs, pI830->num_outputs,
crtcs, pI830->num_pipes,
I830RRDefaultScreenLimits (outputs, pI830->xf86_config.num_output,
crtcs, pI830->xf86_config.num_crtc,
&width, &height);
if (width > pScrn->virtualX)
@ -1251,32 +1225,21 @@ I830RandRPreInit (ScrnInfoPtr pScrn)
/* XXX override xf86 common frame computation code */
pScrn->display->frameX0 = 0;
pScrn->display->frameY0 = 0;
for (o = 0; o < pI830->num_outputs; o++)
for (o = 0; o < pI830->xf86_config.num_output; o++)
{
RRModePtr randr_mode = output_modes[o];
DisplayModePtr mode;
RRCrtcPtr randr_crtc = output_crtcs[o];
int pipe;
Bool enabled;
xf86OutputPtr output = pI830->xf86_config.output[o];
RRModePtr randr_mode = output_modes[o];
RRCrtcPtr randr_crtc = output_crtcs[o];
DisplayModePtr mode;
if (randr_mode)
if (randr_mode && randr_crtc)
{
xf86CrtcPtr crtc = randr_crtc->devPrivate;
mode = (DisplayModePtr) randr_mode->devPrivate;
else
mode = NULL;
if (randr_crtc)
{
pipe = (int) randr_crtc->devPrivate;
enabled = TRUE;
crtc->desiredMode = *mode;
output->crtc = crtc;
}
else
{
pipe = 0;
enabled = FALSE;
}
if (mode)
pI830->pipes[pipe].desiredMode = *mode;
pI830->output[o].pipe = pipe;
pI830->output[o].enabled = enabled;
}
#endif
i830_set_xf86_modes_from_outputs (pScrn);

37
src/i830_randr.h Normal file
View File

@ -0,0 +1,37 @@
/*
* Copyright © 2006 Keith Packard
*
* Permission to use, copy, modify, distribute, and sell this software and its
* documentation for any purpose is hereby granted without fee, provided that
* the above copyright notice appear in all copies and that both that copyright
* notice and this permission notice appear in supporting documentation, and
* that the name of the copyright holders not be used in advertising or
* publicity pertaining to distribution of the software without specific,
* written prior permission. The copyright holders make no representations
* about the suitability of this software for any purpose. It is provided "as
* is" without express or implied warranty.
*
* THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
* EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
* DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
* OF THIS SOFTWARE.
*/
#ifndef _XF86_RANDR_H_
#define _XF86_RANDR_H_
#include <randrstr.h>
#include <X11/extensions/render.h>
Bool xf86RandR12CreateScreenResources (ScreenPtr pScreen);
Bool xf86RandR12Init(ScreenPtr pScreen);
void xf86RandR12SetRotations (ScreenPtr pScreen, Rotation rotation);
Bool xf86RandR12SetConfig(ScreenPtr pScreen, Rotation rotation, int rate,
RRScreenSizePtr pSize);
Rotation xf86RandR12GetRotation(ScreenPtr pScreen);
void xf86RandR12GetOriginalVirtualSize(ScrnInfoPtr pScrn, int *x, int *y);
Bool xf86RandR12PreInit (ScrnInfoPtr pScrn);
#endif /* _XF86_RANDR_H_ */

View File

@ -677,7 +677,7 @@ I830Rotate(ScrnInfoPtr pScrn, DisplayModePtr mode)
pScrn2 = pScrn;
}
pI830->rotation = I830GetRotation(pScrn->pScreen);
pI830->rotation = xf86RandR12GetRotation(pScrn->pScreen);
/* Check if we've still got the same orientation, or same mode */
if (pI830->rotation == oldRotation && pI830->currentMode == mode)

View File

@ -80,39 +80,42 @@ struct i830_sdvo_priv {
};
/** Read a single byte from the given address on the SDVO device. */
static Bool i830_sdvo_read_byte(I830OutputPtr output, int addr,
static Bool i830_sdvo_read_byte(xf86OutputPtr output, int addr,
unsigned char *ch)
{
struct i830_sdvo_priv *dev_priv = output->dev_priv;
I830OutputPrivatePtr intel_output = output->driver_private;
struct i830_sdvo_priv *dev_priv = intel_output->dev_priv;
if (!xf86I2CReadByte(&dev_priv->d, addr, ch)) {
xf86DrvMsg(output->pI2CBus->scrnIndex, X_ERROR,
xf86DrvMsg(intel_output->pI2CBus->scrnIndex, X_ERROR,
"Unable to read from %s slave 0x%02x.\n",
output->pI2CBus->BusName, dev_priv->d.SlaveAddr);
intel_output->pI2CBus->BusName, dev_priv->d.SlaveAddr);
return FALSE;
}
return TRUE;
}
/** Read a single byte from the given address on the SDVO device. */
static Bool i830_sdvo_read_byte_quiet(I830OutputPtr output, int addr,
static Bool i830_sdvo_read_byte_quiet(xf86OutputPtr output, int addr,
unsigned char *ch)
{
struct i830_sdvo_priv *dev_priv = output->dev_priv;
I830OutputPrivatePtr intel_output = output->driver_private;
struct i830_sdvo_priv *dev_priv = intel_output->dev_priv;
return xf86I2CReadByte(&dev_priv->d, addr, ch);
}
/** Write a single byte to the given address on the SDVO device. */
static Bool i830_sdvo_write_byte(I830OutputPtr output,
static Bool i830_sdvo_write_byte(xf86OutputPtr output,
int addr, unsigned char ch)
{
struct i830_sdvo_priv *dev_priv = output->dev_priv;
I830OutputPrivatePtr intel_output = output->driver_private;
struct i830_sdvo_priv *dev_priv = intel_output->dev_priv;
if (!xf86I2CWriteByte(&dev_priv->d, addr, ch)) {
xf86DrvMsg(output->pI2CBus->scrnIndex, X_ERROR,
"Unable to write to %s Slave %02x.\n",
output->pI2CBus->BusName, dev_priv->d.SlaveAddr);
xf86DrvMsg(intel_output->pI2CBus->scrnIndex, X_ERROR,
"Unable to write to %s Slave 0x%02x.\n",
intel_output->pI2CBus->BusName, dev_priv->d.SlaveAddr);
return FALSE;
}
return TRUE;
@ -173,16 +176,17 @@ static I2CSlaveAddr slaveAddr;
* Writes out the data given in args (up to 8 bytes), followed by the opcode.
*/
static void
i830_sdvo_write_cmd(I830OutputPtr output, CARD8 cmd, void *args, int args_len)
i830_sdvo_write_cmd(xf86OutputPtr output, CARD8 cmd, void *args, int args_len)
{
int i;
struct i830_sdvo_priv *dev_priv = output->dev_priv;
I830OutputPrivatePtr intel_output = output->driver_private;
struct i830_sdvo_priv *dev_priv = intel_output->dev_priv;
int i;
if (slaveAddr && slaveAddr != dev_priv->d.SlaveAddr)
ErrorF ("Mismatch slave addr %x != %x\n", slaveAddr, dev_priv->d.SlaveAddr);
/* Write the SDVO command logging */
xf86DrvMsg(output->pI2CBus->scrnIndex, X_INFO, "%s: W: %02X ", SDVO_NAME(dev_priv), cmd);
xf86DrvMsg(intel_output->pI2CBus->scrnIndex, X_INFO, "%s: W: %02X ", SDVO_NAME(dev_priv), cmd);
for (i = 0; i < args_len; i++)
LogWrite(1, "%02X ", ((CARD8 *)args)[i]);
for (; i < 8; i++)
@ -219,10 +223,11 @@ static const char *cmd_status_names[] = {
* Reads back response_len bytes from the SDVO device, and returns the status.
*/
static CARD8
i830_sdvo_read_response(I830OutputPtr output, void *response, int response_len)
i830_sdvo_read_response(xf86OutputPtr output, void *response, int response_len)
{
int i;
CARD8 status;
I830OutputPrivatePtr intel_output = output->driver_private;
int i;
CARD8 status;
/* Read the command response */
for (i = 0; i < response_len; i++) {
@ -234,8 +239,8 @@ i830_sdvo_read_response(I830OutputPtr output, void *response, int response_len)
i830_sdvo_read_byte(output, SDVO_I2C_CMD_STATUS, &status);
/* Write the SDVO command logging */
xf86DrvMsg(output->pI2CBus->scrnIndex, X_INFO,
"%s: R: ", SDVO_NAME(SDVO_PRIV(output)));
xf86DrvMsg(intel_output->pI2CBus->scrnIndex, X_INFO,
"%s: R: ", SDVO_NAME(SDVO_PRIV(intel_output)));
for (i = 0; i < response_len; i++)
LogWrite(1, "%02X ", ((CARD8 *)response)[i]);
for (; i < 8; i++)
@ -267,13 +272,13 @@ i830_sdvo_get_pixel_multiplier(DisplayModePtr pMode)
* STOP. PROM access is terminated by accessing an internal register.
*/
static void
i830_sdvo_set_control_bus_switch(I830OutputPtr output, CARD8 target)
i830_sdvo_set_control_bus_switch(xf86OutputPtr output, CARD8 target)
{
i830_sdvo_write_cmd(output, SDVO_CMD_SET_CONTROL_BUS_SWITCH, &target, 1);
}
static Bool
i830_sdvo_set_target_input(I830OutputPtr output, Bool target_0, Bool target_1)
i830_sdvo_set_target_input(xf86OutputPtr output, Bool target_0, Bool target_1)
{
struct i830_sdvo_set_target_input_args targets = {0};
CARD8 status;
@ -299,7 +304,7 @@ i830_sdvo_set_target_input(I830OutputPtr output, Bool target_0, Bool target_1)
* which should be checked against the docs.
*/
static Bool
i830_sdvo_get_trained_inputs(I830OutputPtr output, Bool *input_1, Bool *input_2)
i830_sdvo_get_trained_inputs(xf86OutputPtr output, Bool *input_1, Bool *input_2)
{
struct i830_sdvo_get_trained_inputs_response response;
CARD8 status;
@ -317,7 +322,7 @@ i830_sdvo_get_trained_inputs(I830OutputPtr output, Bool *input_1, Bool *input_2)
}
static Bool
i830_sdvo_get_active_outputs(I830OutputPtr output,
i830_sdvo_get_active_outputs(xf86OutputPtr output,
CARD16 *outputs)
{
CARD8 status;
@ -329,7 +334,7 @@ i830_sdvo_get_active_outputs(I830OutputPtr output,
}
static Bool
i830_sdvo_set_active_outputs(I830OutputPtr output,
i830_sdvo_set_active_outputs(xf86OutputPtr output,
CARD16 outputs)
{
CARD8 status;
@ -345,7 +350,7 @@ i830_sdvo_set_active_outputs(I830OutputPtr output,
* Returns the pixel clock range limits of the current target input in kHz.
*/
static Bool
i830_sdvo_get_input_pixel_clock_range(I830OutputPtr output, int *clock_min,
i830_sdvo_get_input_pixel_clock_range(xf86OutputPtr output, int *clock_min,
int *clock_max)
{
struct i830_sdvo_pixel_clock_range clocks;
@ -366,7 +371,7 @@ i830_sdvo_get_input_pixel_clock_range(I830OutputPtr output, int *clock_min,
}
static Bool
i830_sdvo_set_target_output(I830OutputPtr output, CARD16 outputs)
i830_sdvo_set_target_output(xf86OutputPtr output, CARD16 outputs)
{
CARD8 status;
@ -380,7 +385,7 @@ i830_sdvo_set_target_output(I830OutputPtr output, CARD16 outputs)
/** Fetches either input or output timings to *dtd, depending on cmd. */
static Bool
i830_sdvo_get_timing(I830OutputPtr output, CARD8 cmd, struct i830_sdvo_dtd *dtd)
i830_sdvo_get_timing(xf86OutputPtr output, CARD8 cmd, struct i830_sdvo_dtd *dtd)
{
CARD8 status;
@ -400,20 +405,20 @@ i830_sdvo_get_timing(I830OutputPtr output, CARD8 cmd, struct i830_sdvo_dtd *dtd)
}
static Bool
i830_sdvo_get_input_timing(I830OutputPtr output, struct i830_sdvo_dtd *dtd)
i830_sdvo_get_input_timing(xf86OutputPtr output, struct i830_sdvo_dtd *dtd)
{
return i830_sdvo_get_timing(output, SDVO_CMD_GET_INPUT_TIMINGS_PART1, dtd);
}
static Bool
i830_sdvo_get_output_timing(I830OutputPtr output, struct i830_sdvo_dtd *dtd)
i830_sdvo_get_output_timing(xf86OutputPtr output, struct i830_sdvo_dtd *dtd)
{
return i830_sdvo_get_timing(output, SDVO_CMD_GET_OUTPUT_TIMINGS_PART1, dtd);
}
/** Sets either input or output timings from *dtd, depending on cmd. */
static Bool
i830_sdvo_set_timing(I830OutputPtr output, CARD8 cmd, struct i830_sdvo_dtd *dtd)
i830_sdvo_set_timing(xf86OutputPtr output, CARD8 cmd, struct i830_sdvo_dtd *dtd)
{
CARD8 status;
@ -431,20 +436,20 @@ i830_sdvo_set_timing(I830OutputPtr output, CARD8 cmd, struct i830_sdvo_dtd *dtd)
}
static Bool
i830_sdvo_set_input_timing(I830OutputPtr output, struct i830_sdvo_dtd *dtd)
i830_sdvo_set_input_timing(xf86OutputPtr output, struct i830_sdvo_dtd *dtd)
{
return i830_sdvo_set_timing(output, SDVO_CMD_SET_INPUT_TIMINGS_PART1, dtd);
}
static Bool
i830_sdvo_set_output_timing(I830OutputPtr output, struct i830_sdvo_dtd *dtd)
i830_sdvo_set_output_timing(xf86OutputPtr output, struct i830_sdvo_dtd *dtd)
{
return i830_sdvo_set_timing(output, SDVO_CMD_SET_OUTPUT_TIMINGS_PART1, dtd);
}
#if 0
static Bool
i830_sdvo_create_preferred_input_timing(I830OutputPtr output, CARD16 clock,
i830_sdvo_create_preferred_input_timing(xf86OutputPtr output, CARD16 clock,
CARD16 width, CARD16 height)
{
struct i830_sdvo_priv *dev_priv = output->dev_priv;
@ -488,9 +493,10 @@ i830_sdvo_get_preferred_input_timing(I830OutputPtr output,
/** Returns the SDVO_CLOCK_RATE_MULT_* for the current clock multiplier */
static int
i830_sdvo_get_clock_rate_mult(I830OutputPtr output)
i830_sdvo_get_clock_rate_mult(xf86OutputPtr output)
{
struct i830_sdvo_priv *dev_priv = output->dev_priv;
I830OutputPrivatePtr intel_output = output->driver_private;
struct i830_sdvo_priv *dev_priv = intel_output->dev_priv;
CARD8 response;
CARD8 status;
@ -516,7 +522,7 @@ i830_sdvo_get_clock_rate_mult(I830OutputPtr output)
* is actually turned on.
*/
static Bool
i830_sdvo_set_clock_rate_mult(I830OutputPtr output, CARD8 val)
i830_sdvo_set_clock_rate_mult(xf86OutputPtr output, CARD8 val)
{
CARD8 status;
@ -529,11 +535,12 @@ i830_sdvo_set_clock_rate_mult(I830OutputPtr output, CARD8 val)
}
static void
i830_sdvo_pre_set_mode(ScrnInfoPtr pScrn, I830OutputPtr output,
DisplayModePtr mode)
i830_sdvo_pre_set_mode(xf86OutputPtr output, DisplayModePtr mode)
{
ScrnInfoPtr pScrn = output->scrn;
I830Ptr pI830 = I830PTR(pScrn);
struct i830_sdvo_priv *dev_priv = output->dev_priv;
I830OutputPrivatePtr intel_output = output->driver_private;
struct i830_sdvo_priv *dev_priv = intel_output->dev_priv;
CARD16 width;
CARD16 height;
CARD16 h_blank_len, h_sync_len, v_blank_len, v_sync_len;
@ -630,15 +637,18 @@ i830_sdvo_pre_set_mode(ScrnInfoPtr pScrn, I830OutputPtr output,
}
static void
i830_sdvo_post_set_mode(ScrnInfoPtr pScrn, I830OutputPtr output,
DisplayModePtr mode)
i830_sdvo_post_set_mode(xf86OutputPtr output, DisplayModePtr mode)
{
ScrnInfoPtr pScrn = output->scrn;
I830OutputPrivatePtr intel_output = output->driver_private;
struct i830_sdvo_priv *dev_priv = intel_output->dev_priv;
xf86CrtcPtr crtc = output->crtc;
I830CrtcPrivatePtr intel_crtc = crtc->driver_private;
I830Ptr pI830 = I830PTR(pScrn);
struct i830_sdvo_priv *dev_priv = output->dev_priv;
Bool input1, input2;
CARD32 dpll, sdvox;
int dpll_reg = (output->pipe == 0) ? DPLL_A : DPLL_B;
int dpll_md_reg = (output->pipe == 0) ? DPLL_A_MD : DPLL_B_MD;
int dpll_reg = (intel_crtc->pipe == 0) ? DPLL_A : DPLL_B;
int dpll_md_reg = (intel_crtc->pipe == 0) ? DPLL_A_MD : DPLL_B_MD;
int sdvo_pixel_multiply;
int i;
CARD8 status;
@ -654,7 +664,7 @@ i830_sdvo_post_set_mode(ScrnInfoPtr pScrn, I830OutputPtr output,
break;
}
sdvox |= SDVO_ENABLE | (9 << 19) | SDVO_BORDER_ENABLE;
if (output->pipe == 1)
if (intel_crtc->pipe == 1)
sdvox |= SDVO_PIPE_B_SELECT;
dpll = INREG(dpll_reg);
@ -690,10 +700,12 @@ i830_sdvo_post_set_mode(ScrnInfoPtr pScrn, I830OutputPtr output,
}
static void
i830_sdvo_dpms(ScrnInfoPtr pScrn, I830OutputPtr output, int mode)
i830_sdvo_dpms(xf86OutputPtr output, int mode)
{
ScrnInfoPtr pScrn = output->scrn;
I830OutputPrivatePtr intel_output = output->driver_private;
struct i830_sdvo_priv *dev_priv = intel_output->dev_priv;
I830Ptr pI830 = I830PTR(pScrn);
struct i830_sdvo_priv *dev_priv = output->dev_priv;
if (mode != DPMSModeOn) {
i830_sdvo_set_active_outputs(output, 0);
@ -705,11 +717,13 @@ i830_sdvo_dpms(ScrnInfoPtr pScrn, I830OutputPtr output, int mode)
}
static void
i830_sdvo_save(ScrnInfoPtr pScrn, I830OutputPtr output)
i830_sdvo_save(xf86OutputPtr output)
{
I830Ptr pI830 = I830PTR(pScrn);
struct i830_sdvo_priv *dev_priv = output->dev_priv;
int o;
ScrnInfoPtr pScrn = output->scrn;
I830OutputPrivatePtr intel_output = output->driver_private;
struct i830_sdvo_priv *dev_priv = intel_output->dev_priv;
I830Ptr pI830 = I830PTR(pScrn);
int o;
/* XXX: We should save the in/out mapping. */
@ -740,11 +754,13 @@ i830_sdvo_save(ScrnInfoPtr pScrn, I830OutputPtr output)
}
static void
i830_sdvo_restore(ScrnInfoPtr pScrn, I830OutputPtr output)
i830_sdvo_restore(xf86OutputPtr output)
{
I830Ptr pI830 = I830PTR(pScrn);
struct i830_sdvo_priv *dev_priv = output->dev_priv;
int o;
ScrnInfoPtr pScrn = output->scrn;
I830OutputPrivatePtr intel_output = output->driver_private;
struct i830_sdvo_priv *dev_priv = intel_output->dev_priv;
I830Ptr pI830 = I830PTR(pScrn);
int o;
if (dev_priv->caps.sdvo_inputs_mask & 0x1) {
i830_sdvo_set_target_input(output, TRUE, FALSE);
@ -773,10 +789,10 @@ i830_sdvo_restore(ScrnInfoPtr pScrn, I830OutputPtr output)
}
static int
i830_sdvo_mode_valid(ScrnInfoPtr pScrn, I830OutputPtr output,
DisplayModePtr pMode)
i830_sdvo_mode_valid(xf86OutputPtr output, DisplayModePtr pMode)
{
struct i830_sdvo_priv *dev_priv = output->dev_priv;
I830OutputPrivatePtr intel_output = output->driver_private;
struct i830_sdvo_priv *dev_priv = intel_output->dev_priv;
if (pMode->Flags & V_DBLSCAN)
return MODE_NO_DBLESCAN;
@ -791,7 +807,7 @@ i830_sdvo_mode_valid(ScrnInfoPtr pScrn, I830OutputPtr output,
}
static Bool
i830_sdvo_get_capabilities(I830OutputPtr output, struct i830_sdvo_caps *caps)
i830_sdvo_get_capabilities(xf86OutputPtr output, struct i830_sdvo_caps *caps)
{
CARD8 status;
@ -807,9 +823,10 @@ i830_sdvo_get_capabilities(I830OutputPtr output, struct i830_sdvo_caps *caps)
static Bool
i830_sdvo_ddc_i2c_get_byte(I2CDevPtr d, I2CByte *data, Bool last)
{
I830OutputPtr output = d->pI2CBus->DriverPrivate.ptr;
I2CBusPtr i2cbus = output->pI2CBus, savebus;
Bool ret;
xf86OutputPtr output = d->DriverPrivate.ptr;
I830OutputPrivatePtr intel_output = output->driver_private;
I2CBusPtr i2cbus = intel_output->pI2CBus, savebus;
Bool ret;
savebus = d->pI2CBus;
d->pI2CBus = i2cbus;
@ -823,9 +840,10 @@ i830_sdvo_ddc_i2c_get_byte(I2CDevPtr d, I2CByte *data, Bool last)
static Bool
i830_sdvo_ddc_i2c_put_byte(I2CDevPtr d, I2CByte c)
{
I830OutputPtr output = d->pI2CBus->DriverPrivate.ptr;
I2CBusPtr i2cbus = output->pI2CBus, savebus;
Bool ret;
xf86OutputPtr output = d->DriverPrivate.ptr;
I830OutputPrivatePtr intel_output = output->driver_private;
I2CBusPtr i2cbus = intel_output->pI2CBus, savebus;
Bool ret;
savebus = d->pI2CBus;
d->pI2CBus = i2cbus;
@ -845,8 +863,9 @@ i830_sdvo_ddc_i2c_put_byte(I2CDevPtr d, I2CByte c)
static Bool
i830_sdvo_ddc_i2c_start(I2CBusPtr b, int timeout)
{
I830OutputPtr output = b->DriverPrivate.ptr;
I2CBusPtr i2cbus = output->pI2CBus;
xf86OutputPtr output = b->DriverPrivate.ptr;
I830OutputPrivatePtr intel_output = output->driver_private;
I2CBusPtr i2cbus = intel_output->pI2CBus;
i830_sdvo_set_control_bus_switch(output, SDVO_CONTROL_BUS_DDC2);
return i2cbus->I2CStart(i2cbus, timeout);
@ -856,8 +875,9 @@ i830_sdvo_ddc_i2c_start(I2CBusPtr b, int timeout)
static void
i830_sdvo_ddc_i2c_stop(I2CDevPtr d)
{
I830OutputPtr output = d->pI2CBus->DriverPrivate.ptr;
I2CBusPtr i2cbus = output->pI2CBus, savebus;
xf86OutputPtr output = d->DriverPrivate.ptr;
I830OutputPrivatePtr intel_output = output->driver_private;
I2CBusPtr i2cbus = intel_output->pI2CBus, savebus;
savebus = d->pI2CBus;
d->pI2CBus = i2cbus;
@ -892,18 +912,19 @@ i830_sdvo_ddc_i2c_address(I2CDevPtr d, I2CSlaveAddr addr)
}
static void
i830_sdvo_dump_cmd(I830OutputPtr output, int opcode)
i830_sdvo_dump_cmd(xf86OutputPtr output, int opcode)
{
CARD8 response[8];
CARD8 response[8];
i830_sdvo_write_cmd(output, opcode, NULL, 0);
i830_sdvo_read_response(output, response, 8);
}
static void
i830_sdvo_dump_device(I830OutputPtr output)
i830_sdvo_dump_device(xf86OutputPtr output)
{
struct i830_sdvo_priv *dev_priv = output->dev_priv;
I830OutputPrivatePtr intel_output = output->driver_private;
struct i830_sdvo_priv *dev_priv = intel_output->dev_priv;
ErrorF("Dump %s\n", dev_priv->d.DevName);
i830_sdvo_dump_cmd(output, SDVO_CMD_GET_DEVICE_CAPS);
@ -935,9 +956,13 @@ i830_sdvo_dump(ScrnInfoPtr pScrn)
I830Ptr pI830 = I830PTR(pScrn);
int i;
for (i = 0; i < pI830->num_outputs; i++) {
if (pI830->output[i].type == I830_OUTPUT_SDVO)
i830_sdvo_dump_device(&pI830->output[i]);
for (i = 0; i < pI830->xf86_config.num_output; i++)
{
xf86OutputPtr output = pI830->xf86_config.output[i];
I830OutputPrivatePtr intel_output = output->driver_private;
if (intel_output->type == I830_OUTPUT_SDVO)
i830_sdvo_dump_device(output);
}
}
@ -951,7 +976,7 @@ i830_sdvo_dump(ScrnInfoPtr pScrn)
* Takes 14ms on average on my i945G.
*/
static enum detect_status
i830_sdvo_detect(ScrnInfoPtr pScrn, I830OutputPtr output)
i830_sdvo_detect(xf86OutputPtr output)
{
CARD8 response[2];
CARD8 status;
@ -968,25 +993,59 @@ i830_sdvo_detect(ScrnInfoPtr pScrn, I830OutputPtr output)
return OUTPUT_STATUS_DISCONNECTED;
}
static void
i830_sdvo_destroy (xf86OutputPtr output)
{
I830OutputPrivatePtr intel_output = output->driver_private;
if (intel_output)
{
struct i830_sdvo_priv *dev_priv = intel_output->dev_priv;
xf86DestroyI2CBusRec (intel_output->pDDCBus, FALSE, FALSE);
xf86DestroyI2CDevRec (&dev_priv->d, FALSE);
xf86DestroyI2CBusRec (dev_priv->d.pI2CBus, TRUE, TRUE);
xfree (intel_output);
}
}
static const xf86OutputFuncsRec i830_sdvo_output_funcs = {
.dpms = i830_sdvo_dpms,
.save = i830_sdvo_save,
.restore = i830_sdvo_restore,
.mode_valid = i830_sdvo_mode_valid,
.pre_set_mode = i830_sdvo_pre_set_mode,
.post_set_mode = i830_sdvo_post_set_mode,
.detect = i830_sdvo_detect,
.get_modes = i830_ddc_get_modes,
.destroy = i830_sdvo_destroy
};
void
i830_sdvo_init(ScrnInfoPtr pScrn, int output_device)
{
I830Ptr pI830 = I830PTR(pScrn);
I830OutputPtr output = &pI830->output[pI830->num_outputs];
struct i830_sdvo_priv *dev_priv;
int i;
unsigned char ch[0x40];
I2CBusPtr i2cbus = NULL, ddcbus;
xf86OutputPtr output;
I830OutputPrivatePtr intel_output;
struct i830_sdvo_priv *dev_priv;
int i;
unsigned char ch[0x40];
I2CBusPtr i2cbus = NULL, ddcbus;
output->type = I830_OUTPUT_SDVO;
output->dpms = i830_sdvo_dpms;
output->save = i830_sdvo_save;
output->restore = i830_sdvo_restore;
output->mode_valid = i830_sdvo_mode_valid;
output->pre_set_mode = i830_sdvo_pre_set_mode;
output->post_set_mode = i830_sdvo_post_set_mode;
output->detect = i830_sdvo_detect;
output->get_modes = i830_ddc_get_modes;
output = xf86OutputCreate (pScrn, &i830_sdvo_output_funcs,
"ADD2 PCIE card");
if (!output)
return;
intel_output = xnfcalloc (sizeof (I830OutputPrivateRec) +
sizeof (struct i830_sdvo_priv), 1);
if (!intel_output)
{
xf86OutputDestroy (output);
return;
}
output->driver_private = intel_output;
dev_priv = (struct i830_sdvo_priv *) (intel_output + 1);
intel_output->type = I830_OUTPUT_SDVO;
/* While it's the same bus, we just initialize a new copy to avoid trouble
* with tracking refcounting ourselves, since the XFree86 DDX bits don't.
@ -997,12 +1056,8 @@ i830_sdvo_init(ScrnInfoPtr pScrn, int output_device)
I830I2CInit(pScrn, &i2cbus, GPIOE, "SDVOCTRL_E for SDVOC");
if (i2cbus == NULL)
return;
/* Allocate the SDVO output private data */
dev_priv = xcalloc(1, sizeof(struct i830_sdvo_priv));
if (dev_priv == NULL) {
xf86DestroyI2CBusRec(i2cbus, TRUE, TRUE);
{
xf86OutputDestroy (output);
return;
}
@ -1017,17 +1072,17 @@ i830_sdvo_init(ScrnInfoPtr pScrn, int output_device)
dev_priv->d.DriverPrivate.ptr = output;
dev_priv->output_device = output_device;
if (!xf86I2CDevInit(&dev_priv->d)) {
if (!xf86I2CDevInit(&dev_priv->d))
{
xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
"Failed to initialize %s I2C device\n",
SDVO_NAME(dev_priv));
xf86DestroyI2CBusRec(i2cbus, TRUE, TRUE);
xfree(dev_priv);
xf86OutputDestroy (output);
return;
}
output->pI2CBus = i2cbus;
output->dev_priv = dev_priv;
intel_output->pI2CBus = i2cbus;
intel_output->dev_priv = dev_priv;
/* Read the regs to test if we can talk to the device */
for (i = 0; i < 0x40; i++) {
@ -1035,9 +1090,7 @@ i830_sdvo_init(ScrnInfoPtr pScrn, int output_device)
xf86DrvMsg(pScrn->scrnIndex, X_INFO,
"No SDVO device found on SDVO%c\n",
output_device == SDVOB ? 'B' : 'C');
xf86DestroyI2CDevRec(&dev_priv->d, FALSE);
xf86DestroyI2CBusRec(i2cbus, TRUE, TRUE);
xfree(dev_priv);
xf86OutputDestroy (output);
return;
}
}
@ -1048,10 +1101,9 @@ i830_sdvo_init(ScrnInfoPtr pScrn, int output_device)
* Start, extra attempts should be harmless.
*/
ddcbus = xf86CreateI2CBusRec();
if (ddcbus == NULL) {
xf86DestroyI2CDevRec(&dev_priv->d, FALSE);
xf86DestroyI2CBusRec(i2cbus, TRUE, TRUE);
xfree(dev_priv);
if (ddcbus == NULL)
{
xf86OutputDestroy (output);
return;
}
if (output_device == SDVOB)
@ -1064,14 +1116,17 @@ i830_sdvo_init(ScrnInfoPtr pScrn, int output_device)
ddcbus->I2CStart = i830_sdvo_ddc_i2c_start;
ddcbus->I2CStop = i830_sdvo_ddc_i2c_stop;
ddcbus->I2CAddress = i830_sdvo_ddc_i2c_address;
ddcbus->DriverPrivate.ptr = &pI830->output[pI830->num_outputs];
if (!xf86I2CBusInit(ddcbus)) {
xf86DestroyI2CDevRec(&dev_priv->d, FALSE);
xf86DestroyI2CBusRec(i2cbus, TRUE, TRUE);
xfree(dev_priv);
ddcbus->DriverPrivate.ptr = output;
if (!xf86I2CBusInit(ddcbus))
{
xf86OutputDestroy (output);
return;
}
output->pDDCBus = ddcbus;
intel_output->pI2CBus = i2cbus;
intel_output->pDDCBus = ddcbus;
intel_output->dev_priv = dev_priv;
i830_sdvo_get_capabilities(output, &dev_priv->caps);
@ -1085,7 +1140,7 @@ i830_sdvo_init(ScrnInfoPtr pScrn, int output_device)
unsigned char bytes[2];
memcpy (bytes, &dev_priv->caps.output_flags, 2);
xf86DrvMsg(output->pI2CBus->scrnIndex, X_ERROR,
xf86DrvMsg(intel_output->pI2CBus->scrnIndex, X_ERROR,
"%s: No active TMDS outputs (0x%02x%02x)\n",
SDVO_NAME(dev_priv),
bytes[0], bytes[1]);
@ -1111,6 +1166,4 @@ i830_sdvo_init(ScrnInfoPtr pScrn, int output_device)
(dev_priv->caps.sdvo_inputs_mask & 0x2) ? 'Y' : 'N',
dev_priv->caps.output_flags & SDVO_OUTPUT_TMDS0 ? 'Y' : 'N',
dev_priv->caps.output_flags & SDVO_OUTPUT_TMDS1 ? 'Y' : 'N');
pI830->num_outputs++;
}

View File

@ -38,6 +38,7 @@
#include "i830_display.h"
enum tv_type {
TV_TYPE_NONE,
TV_TYPE_UNKNOWN,
TV_TYPE_COMPOSITE,
TV_TYPE_SVIDEO,
@ -46,6 +47,7 @@ enum tv_type {
/** Private structure for the integrated TV support */
struct i830_tv_priv {
int type;
CARD32 save_TV_H_CTL_1;
CARD32 save_TV_H_CTL_2;
CARD32 save_TV_H_CTL_3;
@ -141,67 +143,10 @@ const struct tv_mode {
}
};
static int
i830_tv_detect_type(ScrnInfoPtr pScrn, I830OutputPtr output)
{
CARD32 save_tv_ctl, save_tv_dac;
CARD32 tv_ctl, tv_dac;
I830Ptr pI830 = I830PTR(pScrn);
save_tv_ctl = INREG(TV_CTL);
save_tv_dac = INREG(TV_DAC);
/* First, we have to disable the encoder but source from the right pipe,
* which is already enabled.
*/
tv_ctl = INREG(TV_CTL) & ~(TV_ENC_ENABLE | TV_ENC_PIPEB_SELECT);
if (output->pipe == 1)
tv_ctl |= TV_ENC_PIPEB_SELECT;
OUTREG(TV_CTL, tv_ctl);
/* Then set the voltage overrides. */
tv_dac = DAC_CTL_OVERRIDE | DAC_A_0_7_V | DAC_B_0_7_V | DAC_C_0_7_V;
OUTREG(TV_DAC, tv_dac);
/* Enable sensing of the load. */
tv_ctl |= TV_TEST_MODE_MONITOR_DETECT;
OUTREG(TV_CTL, tv_ctl);
tv_dac |= TVDAC_STATE_CHG_EN | TVDAC_A_SENSE_CTL | TVDAC_B_SENSE_CTL |
TVDAC_C_SENSE_CTL;
OUTREG(TV_DAC, tv_dac);
/* Wait for things to take effect. */
i830WaitForVblank(pScrn);
tv_dac = INREG(TV_DAC);
OUTREG(TV_DAC, save_tv_dac);
OUTREG(TV_CTL, save_tv_ctl);
if ((tv_dac & TVDAC_SENSE_MASK) == (TVDAC_B_SENSE | TVDAC_C_SENSE)) {
xf86DrvMsg(pScrn->scrnIndex, X_INFO,
"Detected Composite TV connection\n");
return TV_TYPE_COMPOSITE;
} else if ((tv_dac & TVDAC_SENSE_MASK) == TVDAC_A_SENSE) {
xf86DrvMsg(pScrn->scrnIndex, X_INFO,
"Detected S-Video TV connection\n");
return TV_TYPE_SVIDEO;
} else if ((tv_dac & TVDAC_SENSE_MASK) == 0) {
xf86DrvMsg(pScrn->scrnIndex, X_INFO,
"Detected Component TV connection\n");
return TV_TYPE_COMPONENT;
} else {
xf86DrvMsg(pScrn->scrnIndex, X_INFO,
"Couldn't detect TV connection\n");
return TV_TYPE_UNKNOWN;
}
}
static void
i830_tv_dpms(ScrnInfoPtr pScrn, I830OutputPtr output, int mode)
i830_tv_dpms(xf86OutputPtr output, int mode)
{
ScrnInfoPtr pScrn = output->scrn;
I830Ptr pI830 = I830PTR(pScrn);
switch(mode) {
@ -217,10 +162,12 @@ i830_tv_dpms(ScrnInfoPtr pScrn, I830OutputPtr output, int mode)
}
static void
i830_tv_save(ScrnInfoPtr pScrn, I830OutputPtr output)
i830_tv_save(xf86OutputPtr output)
{
I830Ptr pI830 = I830PTR(pScrn);
struct i830_tv_priv *dev_priv = output->dev_priv;
ScrnInfoPtr pScrn = output->scrn;
I830Ptr pI830 = I830PTR(pScrn);
I830OutputPrivatePtr intel_output = output->driver_private;
struct i830_tv_priv *dev_priv = intel_output->dev_priv;
dev_priv->save_TV_H_CTL_1 = INREG(TV_H_CTL_1);
dev_priv->save_TV_H_CTL_2 = INREG(TV_H_CTL_2);
@ -241,10 +188,12 @@ i830_tv_save(ScrnInfoPtr pScrn, I830OutputPtr output)
}
static void
i830_tv_restore(ScrnInfoPtr pScrn, I830OutputPtr output)
i830_tv_restore(xf86OutputPtr output)
{
I830Ptr pI830 = I830PTR(pScrn);
struct i830_tv_priv *dev_priv = output->dev_priv;
ScrnInfoPtr pScrn = output->scrn;
I830Ptr pI830 = I830PTR(pScrn);
I830OutputPrivatePtr intel_output = output->driver_private;
struct i830_tv_priv *dev_priv = intel_output->dev_priv;
OUTREG(TV_H_CTL_1, dev_priv->save_TV_H_CTL_1);
OUTREG(TV_H_CTL_2, dev_priv->save_TV_H_CTL_2);
@ -265,16 +214,15 @@ i830_tv_restore(ScrnInfoPtr pScrn, I830OutputPtr output)
}
static int
i830_tv_mode_valid(ScrnInfoPtr pScrn, I830OutputPtr output,
DisplayModePtr pMode)
i830_tv_mode_valid(xf86OutputPtr output, DisplayModePtr pMode)
{
return MODE_OK;
}
static void
i830_tv_pre_set_mode(ScrnInfoPtr pScrn, I830OutputPtr output,
DisplayModePtr pMode)
i830_tv_pre_set_mode(xf86OutputPtr output, DisplayModePtr pMode)
{
ScrnInfoPtr pScrn = output->scrn;
I830Ptr pI830 = I830PTR(pScrn);
/* Disable the encoder while we set up the pipe. */
@ -348,18 +296,22 @@ static const CARD32 v_chroma[43] = {
};
static void
i830_tv_post_set_mode(ScrnInfoPtr pScrn, I830OutputPtr output,
DisplayModePtr pMode)
i830_tv_post_set_mode(xf86OutputPtr output, DisplayModePtr pMode)
{
I830Ptr pI830 = I830PTR(pScrn);
enum tv_type type;
const struct tv_mode *tv_mode;
ScrnInfoPtr pScrn = output->scrn;
I830Ptr pI830 = I830PTR(pScrn);
xf86CrtcPtr crtc = output->crtc;
I830OutputPrivatePtr intel_output = output->driver_private;
I830CrtcPrivatePtr intel_crtc = crtc->driver_private;
struct i830_tv_priv *dev_priv = intel_output->dev_priv;
enum tv_type type;
const struct tv_mode *tv_mode;
const struct tv_sc_mode *sc_mode;
CARD32 tv_ctl, tv_filter_ctl;
CARD32 hctl1, hctl2, hctl3;
CARD32 vctl1, vctl2, vctl3, vctl4, vctl5, vctl6, vctl7;
CARD32 scctl1, scctl2, scctl3;
int i;
CARD32 tv_ctl, tv_filter_ctl;
CARD32 hctl1, hctl2, hctl3;
CARD32 vctl1, vctl2, vctl3, vctl4, vctl5, vctl6, vctl7;
CARD32 scctl1, scctl2, scctl3;
int i;
/* Need to actually choose or construct the appropriate
* mode. For now, just set the first one in the list, with
@ -368,7 +320,7 @@ i830_tv_post_set_mode(ScrnInfoPtr pScrn, I830OutputPtr output,
tv_mode = &tv_modes[0];
sc_mode = &tv_sc_modes[TV_SC_NTSC_MJ];
type = i830_tv_detect_type(pScrn, output);
type = dev_priv->type;
hctl1 = (tv_mode->hsync_end << TV_HSYNC_END_SHIFT) |
(tv_mode->htotal << TV_HTOTAL_SHIFT);
@ -408,7 +360,7 @@ i830_tv_post_set_mode(ScrnInfoPtr pScrn, I830OutputPtr output,
(tv_mode->vburst_end_f4 << TV_VBURST_END_F4_SHIFT);
tv_ctl = TV_ENC_ENABLE;
if (output->pipe == 1)
if (intel_crtc->pipe == 1)
tv_ctl |= TV_ENC_PIPEB_SELECT;
switch (type) {
@ -494,6 +446,99 @@ i830_tv_post_set_mode(ScrnInfoPtr pScrn, I830OutputPtr output,
OUTREG(TV_CTL, tv_ctl);
}
static const DisplayModeRec tvModes[] = {
{
.name = "NTSC 480i",
.Clock = 108000,
.HDisplay = 1024,
.HSyncStart = 1048,
.HSyncEnd = 1184,
.HTotal = 1344,
.VDisplay = 768,
.VSyncStart = 771,
.VSyncEnd = 777,
.VTotal = 806,
.type = M_T_DEFAULT
}
};
/**
* Detects TV presence by checking for load.
*
* Requires that the current pipe's DPLL is active.
* \return TRUE if TV is connected.
* \return FALSE if TV is disconnected.
*/
static int
i830_tv_detect_type (xf86CrtcPtr crtc,
xf86OutputPtr output)
{
ScrnInfoPtr pScrn = output->scrn;
I830Ptr pI830 = I830PTR(pScrn);
I830OutputPrivatePtr intel_output = output->driver_private;
struct i830_tv_priv *dev_priv = intel_output->dev_priv;
CARD32 tv_ctl, save_tv_ctl;
CARD32 tv_dac, save_tv_dac;
int type = TV_TYPE_UNKNOWN;
tv_dac = INREG(TV_DAC);
/*
* Detect TV by polling)
*/
if (intel_output->load_detect_temp)
{
/* TV not currently running, prod it with destructive detect */
save_tv_dac = tv_dac;
tv_ctl = INREG(TV_CTL);
save_tv_ctl = tv_ctl;
tv_ctl &= ~TV_ENC_ENABLE;
tv_ctl &= ~TV_TEST_MODE_MASK;
tv_ctl |= TV_TEST_MODE_MONITOR_DETECT;
tv_dac &= ~TVDAC_SENSE_MASK;
tv_dac |= (TVDAC_STATE_CHG_EN |
TVDAC_A_SENSE_CTL |
TVDAC_B_SENSE_CTL |
TVDAC_C_SENSE_CTL);
tv_dac = DAC_CTL_OVERRIDE | DAC_A_0_7_V | DAC_B_0_7_V | DAC_C_0_7_V;
OUTREG(TV_CTL, tv_ctl);
OUTREG(TV_DAC, tv_dac);
i830WaitForVblank(pScrn);
tv_dac = INREG(TV_DAC);
OUTREG(TV_DAC, save_tv_dac);
OUTREG(TV_CTL, save_tv_ctl);
}
/*
* A B C
* 0 1 1 Composite
* 1 0 X svideo
* 0 0 0 Component
*/
if ((tv_dac & TVDAC_SENSE_MASK) == (TVDAC_B_SENSE | TVDAC_C_SENSE)) {
xf86DrvMsg(pScrn->scrnIndex, X_INFO,
"Detected Composite TV connection\n");
type = TV_TYPE_COMPOSITE;
} else if ((tv_dac & (TVDAC_A_SENSE|TVDAC_B_SENSE)) == TVDAC_A_SENSE) {
xf86DrvMsg(pScrn->scrnIndex, X_INFO,
"Detected S-Video TV connection\n");
type = TV_TYPE_SVIDEO;
} else if ((tv_dac & TVDAC_SENSE_MASK) == 0) {
xf86DrvMsg(pScrn->scrnIndex, X_INFO,
"Detected Component TV connection\n");
type = TV_TYPE_COMPONENT;
} else {
xf86DrvMsg(pScrn->scrnIndex, X_INFO,
"Couldn't detect TV connection\n");
type = TV_TYPE_NONE;
}
dev_priv->type = type;
return type;
}
/**
* Detect the TV connection.
*
@ -501,9 +546,34 @@ i830_tv_post_set_mode(ScrnInfoPtr pScrn, I830OutputPtr output,
* we have a pipe programmed in order to probe the TV.
*/
static enum detect_status
i830_tv_detect(ScrnInfoPtr pScrn, I830OutputPtr output)
i830_tv_detect(xf86OutputPtr output)
{
return OUTPUT_STATUS_CONNECTED;
xf86CrtcPtr crtc;
DisplayModeRec mode;
I830OutputPrivatePtr intel_output = output->driver_private;
int type;
crtc = i830GetLoadDetectPipe (output);
if (!crtc)
return OUTPUT_STATUS_UNKNOWN;
if (intel_output->load_detect_temp)
{
mode = tvModes[0];
xf86SetModeCrtc (&mode, INTERLACE_HALVE_V);
i830PipeSetMode (crtc, &mode, FALSE);
}
type = i830_tv_detect_type (crtc, output);
i830ReleaseLoadDetectPipe (output);
switch (type) {
case TV_TYPE_NONE:
return OUTPUT_STATUS_DISCONNECTED;
case TV_TYPE_UNKNOWN:
return OUTPUT_STATUS_UNKNOWN;
default:
return OUTPUT_STATUS_CONNECTED;
}
}
/**
@ -513,8 +583,9 @@ i830_tv_detect(ScrnInfoPtr pScrn, I830OutputPtr output)
* how to probe modes off of TV connections.
*/
static DisplayModePtr
i830_tv_get_modes(ScrnInfoPtr pScrn, I830OutputPtr output)
i830_tv_get_modes(xf86OutputPtr output)
{
ScrnInfoPtr pScrn = output->scrn;
I830Ptr pI830 = I830PTR(pScrn);
DisplayModePtr new;
char stmp[32];
@ -553,36 +624,52 @@ i830_tv_get_modes(ScrnInfoPtr pScrn, I830OutputPtr output)
return new;
}
static void
i830_tv_destroy (xf86OutputPtr output)
{
if (output->driver_private)
xfree (output->driver_private);
}
static const xf86OutputFuncsRec i830_tv_output_funcs = {
.dpms = i830_tv_dpms,
.save = i830_tv_save,
.restore = i830_tv_restore,
.mode_valid = i830_tv_mode_valid,
.pre_set_mode = i830_tv_pre_set_mode,
.post_set_mode = i830_tv_post_set_mode,
.detect = i830_tv_detect,
.get_modes = i830_tv_get_modes,
.destroy = i830_tv_destroy
};
void
i830_tv_init(ScrnInfoPtr pScrn)
{
I830Ptr pI830 = I830PTR(pScrn);
I830OutputPtr output = &pI830->output[pI830->num_outputs];
struct i830_tv_priv *dev_priv;
I830Ptr pI830 = I830PTR(pScrn);
xf86OutputPtr output;
I830OutputPrivatePtr intel_output;
struct i830_tv_priv *dev_priv;
if ((INREG(TV_CTL) & TV_FUSE_STATE_MASK) == TV_FUSE_STATE_DISABLED)
return;
output->type = I830_OUTPUT_TVOUT;
output->pipe = 0;
output->enabled = FALSE;
output->load_detect_temp = FALSE;
output = xf86OutputCreate (pScrn, &i830_tv_output_funcs, "TV");
output->dpms = i830_tv_dpms;
output->save = i830_tv_save;
output->restore = i830_tv_restore;
output->mode_valid = i830_tv_mode_valid;
output->pre_set_mode = i830_tv_pre_set_mode;
output->post_set_mode = i830_tv_post_set_mode;
output->detect = i830_tv_detect;
output->get_modes = i830_tv_get_modes;
dev_priv = xnfcalloc(1, sizeof(struct i830_tv_priv));
if (dev_priv == NULL)
if (!output)
return;
output->dev_priv = dev_priv;
ErrorF ("TV out is output %d\n", pI830->num_outputs);
pI830->num_outputs++;
intel_output = xnfcalloc (sizeof (I830OutputPrivateRec) +
sizeof (struct i830_tv_priv), 1);
if (!intel_output)
{
xf86OutputDestroy (output);
return;
}
dev_priv = (struct i830_tv_priv *) (intel_output + 1);
intel_output->type = I830_OUTPUT_SDVO;
intel_output->dev_priv = dev_priv;
dev_priv->type = TV_TYPE_UNKNOWN;
output->driver_private = intel_output;
}

View File

@ -3593,7 +3593,7 @@ I830VideoSwitchModeAfter(ScrnInfoPtr pScrn, DisplayModePtr mode)
}
/* Check we have an LFP connected */
if (i830PipeHasType (pScrn, pPriv->pipe, I830_OUTPUT_LVDS))
if (i830PipeHasType (pI830->xf86_config.crtc[pPriv->pipe], I830_OUTPUT_LVDS))
{
size = pPriv->pipe ? INREG(PIPEBSRC) : INREG(PIPEASRC);
hsize = (size >> 16) & 0x7FF;

140
src/i830_xf86Crtc.c Normal file
View File

@ -0,0 +1,140 @@
/*
* $Id: $
*
* Copyright © 2006 Keith Packard
*
* Permission to use, copy, modify, distribute, and sell this software and its
* documentation for any purpose is hereby granted without fee, provided that
* the above copyright notice appear in all copies and that both that
* copyright notice and this permission notice appear in supporting
* documentation, and that the name of Keith Packard not be used in
* advertising or publicity pertaining to distribution of the software without
* specific, written prior permission. Keith Packard makes no
* representations about the suitability of this software for any purpose. It
* is provided "as is" without express or implied warranty.
*
* KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
* EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
* DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
* PERFORMANCE OF THIS SOFTWARE.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <stddef.h>
#include <string.h>
#include <stdio.h>
#include "xf86.h"
#include "i830_xf86Crtc.h"
/*
* Crtc functions
*/
xf86CrtcPtr
xf86CrtcCreate (ScrnInfoPtr scrn,
const xf86CrtcFuncsRec *funcs)
{
xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
xf86CrtcPtr crtc;
crtc = xcalloc (sizeof (xf86CrtcRec), 1);
if (!crtc)
return NULL;
crtc->scrn = scrn;
crtc->funcs = funcs;
#ifdef RANDR_12_INTERFACE
crtc->randr_crtc = RRCrtcCreate (crtc);
if (!crtc->randr_crtc)
{
xfree (crtc);
return NULL;
}
#endif
xf86_config->crtc[xf86_config->num_crtc++] = crtc;
return crtc;
}
void
xf86CrtcDestroy (xf86CrtcPtr crtc)
{
xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(crtc->scrn);
int c;
(*crtc->funcs->destroy) (crtc);
#ifdef RANDR_12_INTERFACE
RRCrtcDestroy (crtc->randr_crtc);
#endif
for (c = 0; c < xf86_config->num_crtc; c++)
if (xf86_config->crtc[c] == crtc)
{
memmove (&xf86_config->crtc[c],
&xf86_config->crtc[c+1],
xf86_config->num_crtc - (c + 1));
xf86_config->num_crtc--;
break;
}
xfree (crtc);
}
/*
* Output functions
*/
xf86OutputPtr
xf86OutputCreate (ScrnInfoPtr scrn,
const xf86OutputFuncsRec *funcs,
const char *name)
{
xf86OutputPtr output;
xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
int len = strlen (name);
output = xcalloc (sizeof (xf86OutputRec) + len + 1, 1);
if (!output)
return NULL;
output->scrn = scrn;
output->funcs = funcs;
output->name = (char *) (output + 1);
strcpy (output->name, name);
#ifdef RANDR_12_INTERFACE
output->randr_output = RROutputCreate (name, strlen (name), output);
if (!output->randr_output)
{
xfree (output);
return NULL;
}
#endif
xf86_config->output[xf86_config->num_output++] = output;
return output;
}
void
xf86OutputDestroy (xf86OutputPtr output)
{
ScrnInfoPtr scrn = output->scrn;
xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
int o;
(*output->funcs->destroy) (output);
#ifdef RANDR_12_INTERFACE
RROutputDestroy (output->randr_output);
#endif
while (output->probed_modes)
xf86DeleteMode (&output->probed_modes, output->probed_modes);
for (o = 0; o < xf86_config->num_output; o++)
if (xf86_config->output[o] == output)
{
memmove (&xf86_config->output[o],
&xf86_config->output[o+1],
xf86_config->num_output - (o + 1));
xf86_config->num_output--;
break;
}
xfree (output);
}

310
src/i830_xf86Crtc.h Normal file
View File

@ -0,0 +1,310 @@
/*
* Copyright © 2006 Keith Packard
*
* Permission to use, copy, modify, distribute, and sell this software and its
* documentation for any purpose is hereby granted without fee, provided that
* the above copyright notice appear in all copies and that both that copyright
* notice and this permission notice appear in supporting documentation, and
* that the name of the copyright holders not be used in advertising or
* publicity pertaining to distribution of the software without specific,
* written prior permission. The copyright holders make no representations
* about the suitability of this software for any purpose. It is provided "as
* is" without express or implied warranty.
*
* THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
* EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
* DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
* OF THIS SOFTWARE.
*/
#ifndef _XF86CRTC_H_
#define _XF86CRTC_H_
#include <edid.h>
#include "randrstr.h"
#include "i830_xf86Modes.h"
typedef struct _xf86Crtc xf86CrtcRec, *xf86CrtcPtr;
typedef struct _xf86CrtcFuncs {
/**
* Turns the crtc on/off, or sets intermediate power levels if available.
*
* Unsupported intermediate modes drop to the lower power setting. If the
* mode is DPMSModeOff, the crtc must be disabled, as the DPLL may be
* disabled afterwards.
*/
void
(*dpms)(xf86CrtcPtr crtc,
int mode);
/**
* Saves the crtc's state for restoration on VT switch.
*/
void
(*save)(xf86CrtcPtr crtc);
/**
* Restore's the crtc's state at VT switch.
*/
void
(*restore)(xf86CrtcPtr crtc);
/**
* Clean up driver-specific bits of the crtc
*/
void
(*destroy) (xf86CrtcPtr crtc);
} xf86CrtcFuncsRec, *xf86CrtcFuncsPtr;
struct _xf86Crtc {
/**
* Associated ScrnInfo
*/
ScrnInfoPtr scrn;
/**
* Active state of this CRTC
*
* Set when this CRTC is driving one or more outputs
*/
Bool enabled;
/**
* Position on screen
*
* Locates this CRTC within the frame buffer
*/
int x, y;
/** Track whether cursor is within CRTC range */
Bool cursorInRange;
/** Track state of cursor associated with this CRTC */
Bool cursorShown;
/**
* Active mode
*
* This reflects the mode as set in the CRTC currently
* It will be cleared when the VT is not active or
* during server startup
*/
DisplayModeRec curMode;
/**
* Desired mode
*
* This is set to the requested mode, independent of
* whether the VT is active. In particular, it receives
* the startup configured mode and saves the active mode
* on VT switch.
*/
DisplayModeRec desiredMode;
/** crtc-specific functions */
const xf86CrtcFuncsRec *funcs;
/**
* Driver private
*
* Holds driver-private information
*/
void *driver_private;
#ifdef RANDR_12_INTERFACE
/**
* RandR crtc
*
* When RandR 1.2 is available, this
* points at the associated crtc object
*/
RRCrtcPtr randr_crtc;
#else
void *randr_crtc;
#endif
};
typedef struct _xf86Output xf86OutputRec, *xf86OutputPtr;
typedef struct _xf86OutputFuncs {
/**
* Turns the output on/off, or sets intermediate power levels if available.
*
* Unsupported intermediate modes drop to the lower power setting. If the
* mode is DPMSModeOff, the output must be disabled, as the DPLL may be
* disabled afterwards.
*/
void
(*dpms)(xf86OutputPtr output,
int mode);
/**
* Saves the output's state for restoration on VT switch.
*/
void
(*save)(xf86OutputPtr output);
/**
* Restore's the output's state at VT switch.
*/
void
(*restore)(xf86OutputPtr output);
/**
* Callback for testing a video mode for a given output.
*
* This function should only check for cases where a mode can't be supported
* on the pipe specifically, and not represent generic CRTC limitations.
*
* \return MODE_OK if the mode is valid, or another MODE_* otherwise.
*/
int
(*mode_valid)(xf86OutputPtr output,
DisplayModePtr pMode);
/**
* Callback for setting up a video mode before any crtc/dpll changes.
*
* \param pMode the mode that will be set, or NULL if the mode to be set is
* unknown (such as the restore path of VT switching).
*/
void
(*pre_set_mode)(xf86OutputPtr output,
DisplayModePtr pMode);
/**
* Callback for setting up a video mode after the DPLL update but before
* the plane is enabled.
*/
void
(*post_set_mode)(xf86OutputPtr output,
DisplayModePtr pMode);
/**
* Probe for a connected output, and return detect_status.
*/
enum detect_status
(*detect)(xf86OutputPtr output);
/**
* Query the device for the modes it provides.
*
* This function may also update MonInfo, mm_width, and mm_height.
*
* \return singly-linked list of modes or NULL if no modes found.
*/
DisplayModePtr
(*get_modes)(xf86OutputPtr output);
/**
* Clean up driver-specific bits of the output
*/
void
(*destroy) (xf86OutputPtr output);
} xf86OutputFuncsRec, *xf86OutputFuncsPtr;
struct _xf86Output {
/**
* Associated ScrnInfo
*/
ScrnInfoPtr scrn;
/**
* Currently connected crtc (if any)
*
* If this output is not in use, this field will be NULL.
*/
xf86CrtcPtr crtc;
/**
* List of available modes on this output.
*
* This should be the list from get_modes(), plus perhaps additional
* compatible modes added later.
*/
DisplayModePtr probed_modes;
/** EDID monitor information */
xf86MonPtr MonInfo;
/** Physical size of the currently attached output device. */
int mm_width, mm_height;
/** Output name */
char *name;
/** output-specific functions */
const xf86OutputFuncsRec *funcs;
/** driver private information */
void *driver_private;
#ifdef RANDR_12_INTERFACE
/**
* RandR 1.2 output structure.
*
* When RandR 1.2 is available, this points at the associated
* RandR output structure and is created when this output is created
*/
RROutputPtr randr_output;
#else
void *randr_output;
#endif
};
#define XF86_MAX_CRTC 4
#define XF86_MAX_OUTPUT 16
typedef struct _xf86CrtcConfig {
int num_output;
xf86OutputPtr output[XF86_MAX_OUTPUT];
int num_crtc;
xf86CrtcPtr crtc[XF86_MAX_CRTC];
} xf86CrtcConfigRec, *xf86CrtcConfigPtr;
#define XF86_CRTC_CONFIG_PTR(p) ((xf86CrtcConfigPtr) ((p)->driverPrivate))
/*
* Crtc functions
*/
xf86CrtcPtr
xf86CrtcCreate (ScrnInfoPtr scrn,
const xf86CrtcFuncsRec *funcs);
void
xf86CrtcDestroy (xf86CrtcPtr crtc);
/**
* Allocate a crtc for the specified output
*
* Find a currently unused CRTC which is suitable for
* the specified output
*/
xf86CrtcPtr
xf86AllocCrtc (xf86OutputPtr output);
/**
* Free a crtc
*
* Mark the crtc as unused by any outputs
*/
void
xf86FreeCrtc (xf86CrtcPtr crtc);
/*
* Output functions
*/
xf86OutputPtr
xf86OutputCreate (ScrnInfoPtr scrn,
const xf86OutputFuncsRec *funcs,
const char *name);
void
xf86OutputDestroy (xf86OutputPtr output);
#endif /* _XF86CRTC_H_ */

View File

@ -526,3 +526,27 @@ i830xf86PruneInvalidModes(ScrnInfoPtr pScrn, DisplayModePtr *modeList,
mode = next;
}
}
/**
* Adds the new mode into the mode list, and returns the new list
*
* \param modes doubly-linked mode list.
*/
DisplayModePtr
xf86ModesAdd(DisplayModePtr modes, DisplayModePtr new)
{
if (modes == NULL)
return new;
if (new) {
DisplayModePtr mode = modes;
while (mode->next)
mode = mode->next;
mode->next = new;
new->prev = mode;
}
return modes;
}

View File

@ -25,6 +25,8 @@
*
*/
#ifndef _I830_XF86MODES_H_
#define _I830_XF86MODES_H_
#include "xorgVersion.h"
#if XORG_VERSION_CURRENT <= XORG_VERSION_NUMERIC(7,1,99,2,0)
@ -37,6 +39,8 @@ void i830_xf86SetModeDefaultName(DisplayModePtr mode);
void i830_xf86SetModeCrtc(DisplayModePtr p, int adjustFlags);
Bool i830_xf86ModesEqual(DisplayModePtr pMode1, DisplayModePtr pMode2);
void i830_xf86PrintModeline(int scrnIndex,DisplayModePtr mode);
DisplayModePtr i830_xf86ModesAdd(DisplayModePtr modes, DisplayModePtr new);
#define xf86ModeHSync i830_xf86ModeHSync
#define xf86ModeVRefresh i830_xf86ModeVRefresh
#define xf86DuplicateMode i830_xf86DuplicateMode
@ -45,6 +49,7 @@ void i830_xf86PrintModeline(int scrnIndex,DisplayModePtr mode);
#define xf86SetModeCrtc i830_xf86SetModeCrtc
#define xf86ModesEqual i830_xf86ModesEqual
#define xf86PrintModeline i830_xf86PrintModeline
#define xf86ModesAdd i830_xf86ModesAdd
#endif /* XORG_VERSION_CURRENT <= 7.1.99.2 */
void
@ -73,3 +78,5 @@ i830xf86ValidateModesFlags(ScrnInfoPtr pScrn, DisplayModePtr modeList,
void
i830xf86ValidateModesUserConfig(ScrnInfoPtr pScrn, DisplayModePtr modeList);
#endif /* _I830_XF86MODES_H_ */