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:
Eric Anholt
2006-04-19 14:23:45 -07:00
parent d8f7dfac76
commit 88bb4b5788
5 changed files with 667 additions and 6 deletions

View File

@@ -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.

View File

@@ -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 *

View File

@@ -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);

View File

@@ -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
View 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