mirror of
https://github.com/X11Libre/xf86-video-intel.git
synced 2026-03-24 01:24:12 +00:00
Add more SDVO code. It's taken from airlied's driver, but with magic numbers
replaced by symbolic names in many places. I tried to restrain myself from functional changes in airlied's code in this pass.
This commit is contained in:
@@ -580,10 +580,6 @@ extern Bool I830RandRInit(ScreenPtr pScreen, int rotation);
|
||||
extern Bool I830I2CInit(ScrnInfoPtr pScrn, I2CBusPtr *bus_ptr, int i2c_reg,
|
||||
char *name);
|
||||
|
||||
/* i830_sdvo.c */
|
||||
extern I830SDVOPtr I830SDVOInit(I2CBusPtr b);
|
||||
extern Bool I830I2CDetectSDVOController(ScrnInfoPtr pScrn, int output_index);
|
||||
|
||||
/*
|
||||
* 12288 is set as the maximum, chosen because it is enough for
|
||||
* 1920x1440@32bpp with a 2048 pixel line pitch with some to spare.
|
||||
|
||||
@@ -571,6 +571,7 @@ i830SetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode)
|
||||
#ifdef XF86DRI
|
||||
Bool didLock = FALSE;
|
||||
#endif
|
||||
int i;
|
||||
|
||||
DPRINTF(PFX, "i830SetMode\n");
|
||||
|
||||
@@ -590,6 +591,11 @@ i830SetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode)
|
||||
pI830->planeEnabled[1] = 0;
|
||||
}
|
||||
|
||||
for (i = 0; i < pI830->num_outputs; i++) {
|
||||
if (pI830->output[i].sdvo_drv && pI830->output[i].sdvo_drv->found)
|
||||
I830SDVOPreSetMode(pI830->output[i].sdvo_drv, pMode);
|
||||
}
|
||||
|
||||
if (pI830->planeEnabled[0]) {
|
||||
ok = i830PipeSetMode(pScrn, pMode, 0);
|
||||
if (!ok)
|
||||
@@ -600,6 +606,10 @@ i830SetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode)
|
||||
if (!ok)
|
||||
goto done;
|
||||
}
|
||||
for (i = 0; i < pI830->num_outputs; i++) {
|
||||
if (pI830->output[i].sdvo_drv && pI830->output[i].sdvo_drv->found)
|
||||
I830SDVOPostSetMode(pI830->output[i].sdvo_drv, pMode);
|
||||
}
|
||||
|
||||
xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Mode bandwidth is %d Mpixel/s\n",
|
||||
(int)(pMode->HDisplay * pMode->VDisplay *
|
||||
|
||||
@@ -25,7 +25,14 @@
|
||||
*
|
||||
*/
|
||||
|
||||
/* i830_display.c */
|
||||
Bool i830SetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode);
|
||||
Bool i830DetectCRT(ScrnInfoPtr pScrn);
|
||||
void i830SetLVDSPanelPower(ScrnInfoPtr pScrn, Bool on);
|
||||
void i830PipeSetBase(ScrnInfoPtr pScrn, int pipe, int x, int y);
|
||||
|
||||
/* i830_sdvo.c */
|
||||
I830SDVOPtr I830SDVOInit(I2CBusPtr b);
|
||||
Bool I830I2CDetectSDVOController(ScrnInfoPtr pScrn, int output_index);
|
||||
Bool I830SDVOPreSetMode(I830SDVOPtr s, DisplayModePtr mode);
|
||||
Bool I830SDVOPostSetMode(I830SDVOPtr s, DisplayModePtr mode);
|
||||
|
||||
479
src/i830_sdvo.c
479
src/i830_sdvo.c
@@ -28,6 +28,9 @@ USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
#include "xf86_OSproc.h"
|
||||
#include "compiler.h"
|
||||
#include "i830.h"
|
||||
#include "i830_sdvo_regs.h"
|
||||
|
||||
CARD16 curr_table[6];
|
||||
|
||||
/* SDVO support for i9xx chipsets */
|
||||
static Bool sReadByte(I830SDVOPtr s, int addr, unsigned char *ch)
|
||||
@@ -41,7 +44,6 @@ static Bool sReadByte(I830SDVOPtr s, int addr, unsigned char *ch)
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
#if 0
|
||||
static Bool sWriteByte(I830SDVOPtr s, int addr, unsigned char ch)
|
||||
{
|
||||
if (!xf86I2CWriteByte(&s->d, addr, ch)) {
|
||||
@@ -52,8 +54,481 @@ static Bool sWriteByte(I830SDVOPtr s, int addr, unsigned char ch)
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* following on from tracing the intel BIOS i2c routines */
|
||||
static void
|
||||
I830SDVOWriteOutputs(I830SDVOPtr s, int num_out)
|
||||
{
|
||||
int i;
|
||||
|
||||
ErrorF("SDVO: W: ");
|
||||
for (i = num_out; i <= SDVO_I2C_ARG_0; i++)
|
||||
ErrorF("%02X ", s->sdvo_regs[i]);
|
||||
ErrorF("\n");
|
||||
|
||||
/* blast the output regs */
|
||||
for (i = SDVO_I2C_ARG_0; i >= num_out; i--) {
|
||||
sWriteByte(s, i, s->sdvo_regs[i]);
|
||||
}
|
||||
/* blast the command reg */
|
||||
sWriteByte(s, SDVO_I2C_OPCODE, s->sdvo_regs[SDVO_I2C_OPCODE]);
|
||||
}
|
||||
|
||||
static void
|
||||
I830SDVOReadInputRegs(I830SDVOPtr s)
|
||||
{
|
||||
int i;
|
||||
|
||||
/* follow BIOS ordering */
|
||||
sReadByte(s, SDVO_I2C_CMD_STATUS, &s->sdvo_regs[SDVO_I2C_CMD_STATUS]);
|
||||
|
||||
sReadByte(s, SDVO_I2C_RETURN_3, &s->sdvo_regs[SDVO_I2C_RETURN_3]);
|
||||
sReadByte(s, SDVO_I2C_RETURN_2, &s->sdvo_regs[SDVO_I2C_RETURN_2]);
|
||||
sReadByte(s, SDVO_I2C_RETURN_1, &s->sdvo_regs[SDVO_I2C_RETURN_1]);
|
||||
sReadByte(s, SDVO_I2C_RETURN_0, &s->sdvo_regs[SDVO_I2C_RETURN_0]);
|
||||
sReadByte(s, SDVO_I2C_RETURN_7, &s->sdvo_regs[SDVO_I2C_RETURN_7]);
|
||||
sReadByte(s, SDVO_I2C_RETURN_6, &s->sdvo_regs[SDVO_I2C_RETURN_6]);
|
||||
sReadByte(s, SDVO_I2C_RETURN_5, &s->sdvo_regs[SDVO_I2C_RETURN_5]);
|
||||
sReadByte(s, SDVO_I2C_RETURN_4, &s->sdvo_regs[SDVO_I2C_RETURN_4]);
|
||||
|
||||
ErrorF("SDVO: R: ");
|
||||
for (i = SDVO_I2C_CMD_STATUS; i <= SDVO_I2C_RETURN_7; i++)
|
||||
ErrorF("%02X ", s->sdvo_regs[i]);
|
||||
ErrorF("\n");
|
||||
}
|
||||
|
||||
Bool
|
||||
I830SDVOSetupDDC(I830SDVOPtr s, int enable)
|
||||
{
|
||||
memset(s->sdvo_regs, 0, 9);
|
||||
|
||||
s->sdvo_regs[SDVO_I2C_OPCODE] = SDVO_CMD_SET_CONTROL_BUS_SWITCH;
|
||||
s->sdvo_regs[SDVO_I2C_ARG_0] = SDVO_CONTROL_BUS_DDC2;
|
||||
|
||||
I830SDVOWriteOutputs(s, 7);
|
||||
|
||||
sReadByte(s, SDVO_I2C_CMD_STATUS, &s->sdvo_regs[SDVO_I2C_CMD_STATUS]);
|
||||
|
||||
ErrorF("SDVO: R: ");
|
||||
ErrorF("%02X ", s->sdvo_regs[SDVO_I2C_CMD_STATUS]);
|
||||
ErrorF("\n");
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static Bool
|
||||
I830SDVOSetTargetInput(I830SDVOPtr s)
|
||||
{
|
||||
/* write out 0x10 */
|
||||
memset(s->sdvo_regs, 0, 9);
|
||||
|
||||
s->sdvo_regs[SDVO_I2C_OPCODE] = SDVO_CMD_SET_TARGET_INPUT;
|
||||
|
||||
I830SDVOWriteOutputs(s, 0);
|
||||
|
||||
I830SDVOReadInputRegs(s);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static Bool
|
||||
I830SDVOGetTrainedInputs(I830SDVOPtr s, int on)
|
||||
{
|
||||
memset(s->sdvo_regs, 0, 9);
|
||||
|
||||
s->sdvo_regs[SDVO_I2C_OPCODE] = SDVO_CMD_GET_TRAINED_INPUTS;
|
||||
|
||||
/* XXX: I don't believe we need to set anything here --anholt */
|
||||
s->sdvo_regs[0x07] = on ? 0x80 : 0x00;
|
||||
s->sdvo_regs[0x04] = on ? 0x80 : 0x00;
|
||||
|
||||
I830SDVOWriteOutputs(s, 0);
|
||||
I830SDVOReadInputRegs(s);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static Bool
|
||||
I830SDVOGetActiveOutputs(I830SDVOPtr s, int on)
|
||||
{
|
||||
memset(s->sdvo_regs, 0, 9);
|
||||
|
||||
s->sdvo_regs[SDVO_I2C_OPCODE] = SDVO_CMD_GET_ACTIVE_OUTPUTS;
|
||||
|
||||
s->sdvo_regs[0x07] = on ? 0x01 : 0x00;
|
||||
s->sdvo_regs[0x03] = 0x1;
|
||||
|
||||
I830SDVOWriteOutputs(s, 0);
|
||||
I830SDVOReadInputRegs(s);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static Bool
|
||||
I830SDVOSetActiveOutputs(I830SDVOPtr s, int on)
|
||||
{
|
||||
memset(s->sdvo_regs, 0, 9);
|
||||
|
||||
s->sdvo_regs[SDVO_I2C_OPCODE] = SDVO_CMD_SET_ACTIVE_OUTPUTS;
|
||||
|
||||
/* XXX: This should be touching args 0,1, I believe. --anholt */
|
||||
s->sdvo_regs[0x07] = on ? 0x01 : 0x00;
|
||||
s->sdvo_regs[0x03] = on ? 0x01 : 0x00;
|
||||
|
||||
I830SDVOWriteOutputs(s, 0);
|
||||
I830SDVOReadInputRegs(s);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static Bool
|
||||
I830SDVOGetInputPixelClockRange(I830SDVOPtr s, CARD16 clock, CARD16 height)
|
||||
{
|
||||
memset(s->sdvo_regs, 0, 9);
|
||||
|
||||
s->sdvo_regs[SDVO_I2C_OPCODE] = SDVO_CMD_GET_INPUT_PIXEL_CLOCK_RANGE;
|
||||
|
||||
/* XXX: SDVO_CMD_GET_INPUT_PIXEL_CLOCK_RANGE shouldn't be taking args. */
|
||||
|
||||
/* set clock regs */
|
||||
s->sdvo_regs[0x06] = (clock >> 8) & 0xff;
|
||||
s->sdvo_regs[0x07] = clock & 0xff;
|
||||
|
||||
/* set height regs */
|
||||
s->sdvo_regs[0x02] = (height >> 8) & 0xff;
|
||||
s->sdvo_regs[0x03] = height & 0xff;
|
||||
|
||||
I830SDVOWriteOutputs(s, 0);
|
||||
I830SDVOReadInputRegs(s);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static Bool
|
||||
I830SDVOSetTargetOutput(I830SDVOPtr s)
|
||||
{
|
||||
memset(s->sdvo_regs, 0, 9);
|
||||
|
||||
s->sdvo_regs[SDVO_I2C_OPCODE] = SDVO_CMD_SET_TARGET_OUTPUT;
|
||||
|
||||
s->sdvo_regs[SDVO_I2C_ARG_0] = 0x1; /* Enable */
|
||||
s->sdvo_regs[SDVO_I2C_ARG_1] = 0x0; /* Disable */
|
||||
|
||||
I830SDVOWriteOutputs(s, 0); /* XXX: Only write these two */
|
||||
I830SDVOReadInputRegs(s);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
#if 0
|
||||
static Bool
|
||||
I830SDVOGetOutputTimingsPart1(I830SDVOPtr s)
|
||||
{
|
||||
memset(s->sdvo_regs, 0, 9);
|
||||
|
||||
s->sdvo_regs[SDVO_I2C_OPCODE] = SDVO_CMD_GET_OUTPUT_TIMINGS_PART1;
|
||||
|
||||
/* XXX: No args */
|
||||
s->sdvo_regs[0x07] = 0x0;
|
||||
|
||||
I830SDVOWriteOutputs(s, 0);
|
||||
I830SDVOReadInputRegs(s);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static Bool
|
||||
I830SDVOGetOutputTimingsPart2(I830SDVOPtr s)
|
||||
{
|
||||
memset(s->sdvo_regs, 0, 9);
|
||||
|
||||
s->sdvo_regs[SDVO_I2C_OPCODE] = SDVO_CMD_GET_OUTPUT_TIMINGS_PART2;
|
||||
|
||||
/* XXX: No args */
|
||||
s->sdvo_regs[0x07] = 0x0;
|
||||
|
||||
I830SDVOWriteOutputs(s, 0);
|
||||
I830SDVOReadInputRegs(s);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
#endif
|
||||
|
||||
static Bool
|
||||
I830SDVOSetTimingsPart1(I830SDVOPtr s, char cmd, CARD16 clock, CARD16 magic1,
|
||||
CARD16 magic2, CARD16 magic3)
|
||||
{
|
||||
memset(s->sdvo_regs, 0, 9);
|
||||
|
||||
s->sdvo_regs[SDVO_I2C_OPCODE] = cmd;
|
||||
|
||||
/* set clock regs */
|
||||
s->sdvo_regs[SDVO_I2C_ARG_0] = clock & 0xff;
|
||||
s->sdvo_regs[SDVO_I2C_ARG_1] = (clock >> 8) & 0xff;
|
||||
s->sdvo_regs[SDVO_I2C_ARG_2] = magic3 & 0xff;
|
||||
s->sdvo_regs[SDVO_I2C_ARG_3] = (magic3 >> 8) & 0xff;
|
||||
s->sdvo_regs[SDVO_I2C_ARG_4] = magic2 & 0xff;
|
||||
s->sdvo_regs[SDVO_I2C_ARG_5] = (magic2 >> 8) & 0xff;
|
||||
s->sdvo_regs[SDVO_I2C_ARG_6] = magic1 & 0xff;
|
||||
s->sdvo_regs[SDVO_I2C_ARG_7] = (magic1 >> 8) & 0xff;
|
||||
|
||||
I830SDVOWriteOutputs(s, 0);
|
||||
I830SDVOReadInputRegs(s);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static Bool
|
||||
I830SDVOSetInputTimingsPart1(I830SDVOPtr s, CARD16 clock,
|
||||
CARD16 magic1, CARD16 magic2, CARD16 magic3)
|
||||
{
|
||||
return I830SDVOSetTimingsPart1(s, SDVO_CMD_SET_INPUT_TIMINGS_PART1,
|
||||
clock, magic1, magic2, magic3);
|
||||
}
|
||||
|
||||
static Bool
|
||||
I830SDVOSetOutputTimingsPart1(I830SDVOPtr s, CARD16 clock, CARD16 magic1,
|
||||
CARD16 magic2, CARD16 magic3)
|
||||
{
|
||||
return I830SDVOSetTimingsPart1(s, SDVO_CMD_SET_OUTPUT_TIMINGS_PART1,
|
||||
clock, magic1, magic2, magic3);
|
||||
}
|
||||
|
||||
static Bool
|
||||
I830SDVOGetPreferredInputTimingPart2(I830SDVOPtr s, CARD16 clock,
|
||||
CARD16 magic1, CARD16 magic2,
|
||||
CARD16 magic3)
|
||||
{
|
||||
Bool ok;
|
||||
|
||||
/* XXX: This is a rather different command */
|
||||
ok = I830SDVOSetTimingsPart1(s, SDVO_CMD_GET_PREFERRED_INPUT_TIMING_PART2,
|
||||
clock, magic1, magic2, magic3);
|
||||
|
||||
curr_table[3] = s->sdvo_regs[SDVO_I2C_RETURN_0] |
|
||||
(s->sdvo_regs[SDVO_I2C_RETURN_1] << 8);
|
||||
curr_table[4] = s->sdvo_regs[SDVO_I2C_RETURN_2] |
|
||||
(s->sdvo_regs[SDVO_I2C_RETURN_3] << 8);
|
||||
curr_table[5] = 0x1e;
|
||||
|
||||
return ok;
|
||||
}
|
||||
|
||||
static Bool
|
||||
I830SDVOSetTimingsPart2(I830SDVOPtr s, CARD8 cmd, CARD16 magic4, CARD16 magic5,
|
||||
CARD16 magic6)
|
||||
{
|
||||
memset(s->sdvo_regs, 0, 9);
|
||||
|
||||
s->sdvo_regs[SDVO_I2C_OPCODE] = cmd;
|
||||
|
||||
/* set clock regs */
|
||||
s->sdvo_regs[SDVO_I2C_ARG_0] = magic4 & 0xff;
|
||||
s->sdvo_regs[SDVO_I2C_ARG_1] = (magic4 >> 8) & 0xff;
|
||||
s->sdvo_regs[SDVO_I2C_ARG_2] = magic5 & 0xff;
|
||||
s->sdvo_regs[SDVO_I2C_ARG_3] = (magic5 >> 8) & 0xff;
|
||||
s->sdvo_regs[SDVO_I2C_ARG_4] = magic6 & 0xff;
|
||||
s->sdvo_regs[SDVO_I2C_ARG_5] = (magic6 >> 8) & 0xff;
|
||||
|
||||
I830SDVOWriteOutputs(s, 0);
|
||||
I830SDVOReadInputRegs(s);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static Bool
|
||||
I830SDVOSetInputTimingsPart2(I830SDVOPtr s, CARD16 magic4, CARD16 magic5,
|
||||
CARD16 magic6)
|
||||
{
|
||||
return I830SDVOSetTimingsPart2(s, SDVO_CMD_SET_INPUT_TIMINGS_PART2, magic4,
|
||||
magic5, magic6);
|
||||
}
|
||||
|
||||
static Bool
|
||||
I830SDVOSetOutputTimingsPart2(I830SDVOPtr s, CARD16 magic4, CARD16 magic5,
|
||||
CARD16 magic6)
|
||||
{
|
||||
return I830SDVOSetTimingsPart2(s, SDVO_CMD_SET_OUTPUT_TIMINGS_PART2, magic4,
|
||||
magic5, magic6);
|
||||
}
|
||||
|
||||
static Bool
|
||||
I830SDVOCreatePreferredInputTiming(I830SDVOPtr s, CARD16 clock, CARD16 width,
|
||||
CARD16 height)
|
||||
{
|
||||
memset(s->sdvo_regs, 0, 9);
|
||||
|
||||
s->sdvo_regs[SDVO_I2C_OPCODE] = SDVO_CMD_CREATE_PREFERRED_INPUT_TIMING;
|
||||
|
||||
s->sdvo_regs[SDVO_I2C_ARG_0] = clock & 0xff;
|
||||
s->sdvo_regs[SDVO_I2C_ARG_1] = (clock >> 8) & 0xff;
|
||||
s->sdvo_regs[SDVO_I2C_ARG_2] = width & 0xff;
|
||||
s->sdvo_regs[SDVO_I2C_ARG_3] = (width >> 8) & 0xff;
|
||||
s->sdvo_regs[SDVO_I2C_ARG_4] = (height >> 8) & 0xff;
|
||||
s->sdvo_regs[SDVO_I2C_ARG_5] = height & 0xff;
|
||||
|
||||
I830SDVOWriteOutputs(s, 0);
|
||||
I830SDVOReadInputRegs(s);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static Bool
|
||||
I830SDVOGetPreferredInputTimingPart1(I830SDVOPtr s)
|
||||
{
|
||||
memset(s->sdvo_regs, 0, 9);
|
||||
|
||||
s->sdvo_regs[SDVO_I2C_OPCODE] = SDVO_CMD_GET_PREFERRED_INPUT_TIMING_PART1;
|
||||
|
||||
I830SDVOWriteOutputs(s, 0);
|
||||
I830SDVOReadInputRegs(s);
|
||||
|
||||
curr_table[0] = s->sdvo_regs[SDVO_I2C_RETURN_6] |
|
||||
(s->sdvo_regs[SDVO_I2C_RETURN_7] << 8);
|
||||
curr_table[1] = s->sdvo_regs[SDVO_I2C_RETURN_4] |
|
||||
(s->sdvo_regs[SDVO_I2C_RETURN_5] << 8);
|
||||
curr_table[2] = s->sdvo_regs[SDVO_I2C_RETURN_2] |
|
||||
(s->sdvo_regs[SDVO_I2C_RETURN_3] << 8);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static Bool
|
||||
I830SDVOSetClockRateMult(I830SDVOPtr s, CARD8 val)
|
||||
{
|
||||
memset(s->sdvo_regs, 0, 9);
|
||||
|
||||
s->sdvo_regs[SDVO_I2C_OPCODE] = SDVO_CMD_SET_CLOCK_RATE_MULT;
|
||||
|
||||
s->sdvo_regs[SDVO_I2C_ARG_0] = val;
|
||||
I830SDVOWriteOutputs(s, 0);
|
||||
I830SDVOReadInputRegs(s);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
Bool
|
||||
I830SDVOPreSetMode(I830SDVOPtr s, DisplayModePtr mode)
|
||||
{
|
||||
CARD16 clock = mode->Clock/10, width = mode->CrtcHDisplay;
|
||||
CARD16 height = mode->CrtcVDisplay;
|
||||
CARD16 h_blank_len, h_sync_len, v_blank_len, v_sync_len;
|
||||
CARD16 h_sync_offset, v_sync_offset;
|
||||
CARD16 sync_flags;
|
||||
CARD8 c16a[8];
|
||||
CARD8 c17a[8];
|
||||
CARD16 out_timings[6];
|
||||
|
||||
/* do some mode translations */
|
||||
h_blank_len = mode->CrtcHBlankEnd - mode->CrtcHBlankStart;
|
||||
h_sync_len = mode->CrtcHSyncEnd - mode->CrtcHSyncStart;
|
||||
|
||||
v_blank_len = mode->CrtcVBlankEnd - mode->CrtcVBlankStart;
|
||||
v_sync_len = mode->CrtcVSyncEnd - mode->CrtcVSyncStart;
|
||||
|
||||
h_sync_offset = mode->CrtcHSyncStart - mode->CrtcHBlankStart;
|
||||
v_sync_offset = mode->CrtcVSyncStart - mode->CrtcVBlankStart;
|
||||
|
||||
sync_flags = 0x18;
|
||||
if (mode->Flags & V_PHSYNC)
|
||||
sync_flags |= 0x2;
|
||||
if (mode->Flags & V_PVSYNC)
|
||||
sync_flags |= 0x4;
|
||||
/* high bits of 0 */
|
||||
c16a[7] = clock & 0xff;
|
||||
c16a[6] = (clock >> 8) & 0xff;
|
||||
c16a[5] = (width & 0xff);
|
||||
c16a[4] = (h_blank_len & 0xff);
|
||||
c16a[3] = (((width >> 8) & 0xf) << 4) | ((h_blank_len >> 8) & 0xf);
|
||||
c16a[2] = (height & 0xff);
|
||||
c16a[1] = (v_blank_len & 0xff);
|
||||
c16a[0] = (((height >> 8) & 0xf) << 4) | ((v_blank_len >> 8) & 0xf);
|
||||
|
||||
c17a[7] = h_sync_offset;
|
||||
c17a[6] = h_sync_len & 0xff;
|
||||
c17a[5] = (v_sync_offset & 0xf) << 4 | (v_sync_len & 0xf);
|
||||
c17a[4] = 0;
|
||||
c17a[3] = sync_flags;
|
||||
c17a[2] = 0;
|
||||
out_timings[0] = c16a[1] | ((short)c16a[0] << 8);
|
||||
out_timings[1] = c16a[3] | ((short)c16a[2] << 8);
|
||||
out_timings[2] = c16a[5] | ((short)c16a[4] << 8);
|
||||
out_timings[3] = c17a[7] | ((short)c17a[6] << 8);
|
||||
out_timings[4] = c17a[5] | ((short)c17a[4] << 8);
|
||||
out_timings[5] = c17a[3] | ((short)c17a[2] << 8);
|
||||
|
||||
I830SDVOSetTargetInput(s);
|
||||
I830SDVOGetInputPixelClockRange(s, clock, height);
|
||||
|
||||
I830SDVOGetActiveOutputs(s, 0);
|
||||
I830SDVOSetActiveOutputs(s, 0);
|
||||
|
||||
I830SDVOSetTargetOutput(s);
|
||||
I830SDVOSetOutputTimingsPart1(s, clock, out_timings[0], out_timings[1],
|
||||
out_timings[2]);
|
||||
|
||||
I830SDVOSetTargetOutput(s);
|
||||
I830SDVOSetOutputTimingsPart2(s, out_timings[3], out_timings[4],
|
||||
out_timings[5]);
|
||||
|
||||
I830SDVOSetTargetInput(s);
|
||||
|
||||
I830SDVOCreatePreferredInputTiming(s, clock, width, height);
|
||||
I830SDVOSetTargetInput(s);
|
||||
|
||||
I830SDVOGetPreferredInputTimingPart1(s);
|
||||
I830SDVOSetTargetInput(s);
|
||||
|
||||
I830SDVOGetPreferredInputTimingPart2(s, clock, out_timings[0], out_timings[1],
|
||||
out_timings[2]);
|
||||
I830SDVOSetTargetInput(s);
|
||||
|
||||
I830SDVOSetInputTimingsPart1(s, clock, curr_table[0], curr_table[1],
|
||||
curr_table[2]);
|
||||
|
||||
I830SDVOSetTargetInput(s);
|
||||
I830SDVOSetInputTimingsPart2(s, curr_table[3], curr_table[4],
|
||||
out_timings[5]);
|
||||
|
||||
I830SDVOSetTargetInput(s);
|
||||
/*if (mode->PrivFlags & I830_MFLAG_DOUBLE)
|
||||
I830SDVOSetClockRateMult(s, 0x02);
|
||||
else */
|
||||
I830SDVOSetClockRateMult(s, 0x01);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
Bool
|
||||
I830SDVOPostSetMode(I830SDVOPtr s, DisplayModePtr mode)
|
||||
{
|
||||
int clock = mode->Clock/10, height=mode->CrtcVDisplay;
|
||||
Bool ret = TRUE;
|
||||
|
||||
/* the BIOS writes out 6 commands post mode set */
|
||||
/* two 03s, 04 05, 10, 1d */
|
||||
/* these contain the height and mode clock / 10 by the looks of it */
|
||||
|
||||
I830SDVOGetTrainedInputs(s, 1);
|
||||
I830SDVOGetTrainedInputs(s, 0);
|
||||
|
||||
/* THIS IS A DIRTY HACK - sometimes for some reason on startup
|
||||
* the BIOS doesn't find my DVI monitor -
|
||||
* without this hack the driver doesn't work.. this causes the modesetting
|
||||
* to be re-run
|
||||
*/
|
||||
if (s->sdvo_regs[SDVO_I2C_RETURN_0] != 0x1) {
|
||||
ret = FALSE;
|
||||
}
|
||||
|
||||
I830SDVOGetActiveOutputs(s, 1);
|
||||
I830SDVOSetActiveOutputs(s, 1);
|
||||
|
||||
I830SDVOSetTargetInput(s);
|
||||
I830SDVOGetInputPixelClockRange(s, clock, height);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
I830SDVOPtr
|
||||
I830SDVOInit(I2CBusPtr b)
|
||||
{
|
||||
@@ -92,7 +567,7 @@ I830I2CDetectSDVOController(ScrnInfoPtr pScrn, int output_index)
|
||||
if (sdvo == NULL)
|
||||
return FALSE;
|
||||
|
||||
for (i=0; i<0x40; i++) {
|
||||
for (i = 0; i < 0x40; i++) {
|
||||
if (!sReadByte(sdvo, i, &ch[i]))
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
173
src/i830_sdvo_regs.h
Normal file
173
src/i830_sdvo_regs.h
Normal file
@@ -0,0 +1,173 @@
|
||||
/*
|
||||
* Copyright © 2006 Intel Corporation
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the next
|
||||
* paragraph) shall be included in all copies or substantial portions of the
|
||||
* Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*
|
||||
* Authors:
|
||||
* Eric Anholt <eric@anholt.net>
|
||||
*
|
||||
*/
|
||||
|
||||
/* I2C registers for SDVO */
|
||||
#define SDVO_I2C_ARG_0 0x07
|
||||
#define SDVO_I2C_ARG_1 0x06
|
||||
#define SDVO_I2C_ARG_2 0x05
|
||||
#define SDVO_I2C_ARG_3 0x04
|
||||
#define SDVO_I2C_ARG_4 0x03
|
||||
#define SDVO_I2C_ARG_5 0x02
|
||||
#define SDVO_I2C_ARG_6 0x01
|
||||
#define SDVO_I2C_ARG_7 0x00
|
||||
#define SDVO_I2C_OPCODE 0x08
|
||||
#define SDVO_I2C_CMD_STATUS 0x09
|
||||
#define SDVO_I2C_RETURN_0 0x0a
|
||||
#define SDVO_I2C_RETURN_1 0x0b
|
||||
#define SDVO_I2C_RETURN_2 0x0c
|
||||
#define SDVO_I2C_RETURN_3 0x0d
|
||||
#define SDVO_I2C_RETURN_4 0x0e
|
||||
#define SDVO_I2C_RETURN_5 0x0f
|
||||
#define SDVO_I2C_RETURN_6 0x10
|
||||
#define SDVO_I2C_RETURN_7 0x11
|
||||
#define SDVO_I2C_VENDOR_BEGIN 0x20
|
||||
|
||||
/* Status results */
|
||||
#define SDVO_CMD_STATUS_POWER_ON 0x0
|
||||
#define SDVO_CMD_STATUS_SUCCESS 0x1
|
||||
#define SDVO_CMD_STATUS_NOTSUPP 0x2
|
||||
#define SDVO_CMD_STATUS_INVALID_ARG 0x3
|
||||
#define SDVO_CMD_STATUS_PENDING 0x4
|
||||
#define SDVO_CMD_STATUS_TARGET_NOT_SUPP 0x5
|
||||
#define SDVO_CMD_STATUS_SCALING_NOT_SUPP 0x6
|
||||
|
||||
/* SDVO commands, argument/result registers */
|
||||
#define SDVO_CMD_RESET 0x01
|
||||
#define SDVO_CMD_GET_DEVICE_CAPS 0x02
|
||||
# define SDVO_DEVICE_CAPS_VENDOR_ID SDVO_I2C_RETURN_0
|
||||
# define SDVO_DEVICE_CAPS_DEVICE_ID SDVO_I2C_RETURN_1
|
||||
# define SDVO_DEVICE_CAPS_DEVICE_REV_ID SDVO_I2C_RETURN_2
|
||||
# define SDVO_DEVICE_CAPS_SDVOVERSION_MINOR SDVO_I2C_RETURN_3
|
||||
# define SDVO_DEVICE_CAPS_SDVOVERSION_MAJOR SDVO_I2C_RETURN_4
|
||||
# define SDVO_DEVICE_CAPS_CAPS SDVO_I2C_RETURN_5
|
||||
# define SDVO_DEVICE_CAPS_INPUTS_MASK (3 << 0)
|
||||
# define SDVO_DEVICE_CAPS_SMOOTH_SCALING (1 << 2)
|
||||
# define SDVO_DEVICE_CAPS_SHARP_SCALING (1 << 3)
|
||||
# define SDVO_DEVICE_CAPS_UP_SCALING (1 << 4)
|
||||
# define SDVO_DEVICE_CAPS_DOWN_SCALING (1 << 5)
|
||||
# define SDVO_DEVICE_CAPS_STALL_SUPPORT (1 << 6)
|
||||
# define SDVO_DEVICE_CAPS_OUTPUT_0_SUPPORTED SDVO_I2C_RETURN_6
|
||||
# define SDVO_DEVICE_CAPS_OUTPUT_1_SUPPORTED SDVO_I2C_RETURN_7
|
||||
|
||||
#define SDVO_CMD_GET_FIRMWARE_REV 0x86
|
||||
# define SDVO_DEVICE_FIRMWARE_MINOR SDVO_I2C_RETURN_0
|
||||
# define SDVO_DEVICE_FIRMWARE_MAJOR SDVO_I2C_RETURN_1
|
||||
|
||||
#define SDVO_CMD_GET_TRAINED_INPUTS 0x03
|
||||
|
||||
#define SDVO_CMD_GET_ACTIVE_OUTPUTS 0x04
|
||||
|
||||
#define SDVO_CMD_SET_ACTIVE_OUTPUTS 0x05
|
||||
|
||||
#define SDVO_CMD_GET_IN_OUT_MAP 0x06
|
||||
|
||||
#define SDVO_CMD_SET_IN_OUT_MAP 0x07
|
||||
|
||||
#define SDVO_CMD_GET_ATTACHED_DISPLAYS 0x0b
|
||||
|
||||
#define SDVO_CMD_GET_HOT_PLUG_SUPPORT 0x0c
|
||||
|
||||
#define SDVO_CMD_SET_ACTIVE_HOT_PLUG 0x0d
|
||||
|
||||
#define SDVO_CMD_GET_ACTIVE_HOT_PLUG 0x0e
|
||||
|
||||
#define SDVO_CMD_GET_INTR_EVENT_SOURCE 0x0f
|
||||
|
||||
#define SDVO_CMD_SET_TARGET_INPUT 0x10
|
||||
|
||||
#define SDVO_CMD_SET_TARGET_OUTPUT 0x11
|
||||
|
||||
#define SDVO_CMD_GET_INPUT_TIMINGS_PART1 0x12
|
||||
#define SDVO_CMD_GET_INPUT_TIMINGS_PART2 0x13
|
||||
#define SDVO_CMD_SET_INPUT_TIMINGS_PART1 0x14
|
||||
#define SDVO_CMD_SET_INPUT_TIMINGS_PART2 0x15
|
||||
#define SDVO_CMD_SET_OUTPUT_TIMINGS_PART1 0x16
|
||||
#define SDVO_CMD_SET_OUTPUT_TIMINGS_PART2 0x17
|
||||
#define SDVO_CMD_GET_OUTPUT_TIMINGS_PART1 0x18
|
||||
#define SDVO_CMD_GET_OUTPUT_TIMINGS_PART2 0x19
|
||||
/* Part 1 */
|
||||
# define SDVO_DTD_CLOCK_LOW SDVO_I2C_ARG_0
|
||||
# define SDVO_DTD_CLOCK_HIGH SDVO_I2C_ARG_1
|
||||
# define SDVO_DTD_H_ACTIVE SDVO_I2C_ARG_2
|
||||
# define SDVO_DTD_H_BLANK SDVO_I2C_ARG_3
|
||||
# define SDVO_DTD_H_HIGH SDVO_I2C_ARG_4
|
||||
# define SDVO_DTD_V_ACTIVE SDVO_I2C_ARG_5
|
||||
# define SDVO_DTD_V_BLANK SDVO_I2C_ARG_6
|
||||
# define SDVO_DTD_V_HIGH SDVO_I2C_ARG_7
|
||||
/* Part 2 */
|
||||
# define SDVO_DTD_HSYNC_OFF SDVO_I2C_ARG_0
|
||||
# define SDVO_DTD_HSYNC_WIDTH SDVO_I2C_ARG_1
|
||||
# define SDVO_DTD_VSYNC_OFF_WIDTH SDVO_I2C_ARG_2
|
||||
# define SDVO_DTD_SYSNC_OFF_WIDTH_HIGH SDVO_I2C_ARG_3
|
||||
# define SDVO_DTD_DTD_FLAGS SDVO_I2C_ARG_4
|
||||
# define SDVO_DTD_DTD_FLAG_INTERLACED (1 << 7)
|
||||
# define SDVO_DTD_DTD_FLAG_STEREO_MASK (3 << 5)
|
||||
# define SDVO_DTD_DTD_FLAG_INPUT_MASK (3 << 3)
|
||||
# define SDVO_DTD_DTD_FLAG_SYNC_MASK (3 << 1)
|
||||
# define SDVO_DTD_SDVO_FLAS SDVO_I2C_ARG_5
|
||||
# define SDVO_DTD_SDVO_FLAG_STALL (1 << 7)
|
||||
# define SDVO_DTD_SDVO_FLAG_NOT_CENTERED (1 << 6)
|
||||
# define SDVO_DTD_SDVO_FLAG_SCALING_MASK (3 << 4)
|
||||
# define SDVO_DTD_VSYNC_OFF_HIGH SDVO_I2C_ARG_6
|
||||
|
||||
#define SDVO_CMD_CREATE_PREFERRED_INPUT_TIMING 0x1a
|
||||
# define SDVO_PREFERRED_INPUT_TIMING_CLOCK_LOW SDVO_I2C_ARG_0
|
||||
# define SDVO_PREFERRED_INPUT_TIMING_CLOCK_HIGH SDVO_I2C_ARG_1
|
||||
# define SDVO_PREFERRED_INPUT_TIMING_WIDTH_LOW SDVO_I2C_ARG_2
|
||||
# define SDVO_PREFERRED_INPUT_TIMING_WIDTH_HIGH SDVO_I2C_ARG_3
|
||||
# define SDVO_PREFERRED_INPUT_TIMING_HEIGHT_LOW SDVO_I2C_ARG_4
|
||||
# define SDVO_PREFERRED_INPUT_TIMING_HEIGHT_HIGH SDVO_I2C_ARG_5
|
||||
# define SDVO_PREFERRED_INPUT_TIMING_FLAGS SDVO_I2C_ARG_6
|
||||
# define SDVO_PREFERRED_INPUT_TIMING_FLAGS_INTERLACED (1 << 0)
|
||||
# define SDVO_PREFERRED_INPUT_TIMING_FLAGS_SCALED (1 << 1)
|
||||
|
||||
#define SDVO_CMD_GET_PREFERRED_INPUT_TIMING_PART1 0x1b
|
||||
#define SDVO_CMD_GET_PREFERRED_INPUT_TIMING_PART2 0x1c
|
||||
|
||||
#define SDVO_CMD_GET_INPUT_PIXEL_CLOCK_RANGE 0x1d
|
||||
#define SDVO_CMD_GET_OUTPUT_PIXEL_CLOCK_RANGE 0x1e
|
||||
|
||||
#define SDVO_CMD_GET_SUPPORTED_CLOCK_RATE_MULTS 0x1f
|
||||
|
||||
#define SDVO_CMD_GET_CLOCK_RATE_MULT 0x20
|
||||
|
||||
#define SDVO_CMD_SET_CLOCK_RATE_MULT 0x21
|
||||
|
||||
#define SDVO_CMD_GET_SUPPORTED_TV_FORMATS 0x27
|
||||
|
||||
#define SDVO_CMD_GET_TV_FORMAT 0x28
|
||||
|
||||
#define SDVO_CMD_SET_TV_FORMAT 0x29
|
||||
|
||||
#define SDVO_CMD_SET_TV_RESOLUTION_SUPPORT 0x93
|
||||
|
||||
#define SDVO_CMD_SET_CONTROL_BUS_SWITCH 0x7a
|
||||
# define SDVO_CONTROL_BUS_PROM 0x0
|
||||
# define SDVO_CONTROL_BUS_DDC1 0x1
|
||||
# define SDVO_CONTROL_BUS_DDC2 0x2
|
||||
# define SDVO_CONTROL_BUS_DDC3 0x3
|
||||
|
||||
Reference in New Issue
Block a user