xf86-video-intel: 4 commits - src/i830_display.c src/i830.h src/i830_sdvo.c
Eric Anholt
anholt at kemper.freedesktop.org
Wed Apr 9 15:23:46 PDT 2008
src/i830.h | 1
src/i830_display.c | 9 +-
src/i830_sdvo.c | 226 ++++++++++++++++++++++++++++++++++++++---------------
3 files changed, 172 insertions(+), 64 deletions(-)
New commits:
commit 96ae9a9f0abc582e45ff4e17dd213c8739c24cb3
Author: Eric Anholt <eric at anholt.net>
Date: Wed Apr 9 14:17:29 2008 -0700
SDVO: Rename output_dtd variable to input_dtd, which is its new job.
diff --git a/src/i830_sdvo.c b/src/i830_sdvo.c
index 3141cc9..2379127 100644
--- a/src/i830_sdvo.c
+++ b/src/i830_sdvo.c
@@ -808,7 +808,7 @@ i830_sdvo_mode_set(xf86OutputPtr output, DisplayModePtr mode,
uint32_t sdvox;
int sdvo_pixel_multiply;
struct i830_sdvo_in_out_map in_out;
- struct i830_sdvo_dtd output_dtd;
+ struct i830_sdvo_dtd input_dtd;
uint8_t status;
if (!mode)
@@ -827,13 +827,15 @@ i830_sdvo_mode_set(xf86OutputPtr output, DisplayModePtr mode,
&in_out, sizeof(in_out));
status = i830_sdvo_read_response(output, NULL, 0);
- /* If it's a TV, we already set the output timing in mode_fixup. */
- if (!dev_priv->is_tv) {
- i830_sdvo_get_dtd_from_mode(&output_dtd, mode);
+ i830_sdvo_get_dtd_from_mode(&input_dtd, mode);
+ /* If it's a TV, we already set the output timing in mode_fixup.
+ * Otherwise, the output timing is equal to the input timing.
+ */
+ if (!dev_priv->is_tv) {
/* Set the output timing to the screen */
i830_sdvo_set_target_output(output, dev_priv->controlled_output);
- i830_sdvo_set_output_timing(output, &output_dtd);
+ i830_sdvo_set_output_timing(output, &input_dtd);
}
/* Set the input timing to the screen. Assume always input 0. */
@@ -854,7 +856,7 @@ i830_sdvo_mode_set(xf86OutputPtr output, DisplayModePtr mode,
i830_sdvo_set_input_timing(output, &input_dtd);
}
#else
- i830_sdvo_set_input_timing(output, &output_dtd);
+ i830_sdvo_set_input_timing(output, &input_dtd);
#endif
switch (i830_sdvo_get_pixel_multiplier(mode)) {
commit 72c3995d5158286d20e97296f4552697f32f935f
Author: Eric Anholt <eric at anholt.net>
Date: Tue Apr 8 15:00:18 2008 -0700
SDVO: Set adjusted_mode in mode_fixup from the preferred input timings for TV.
diff --git a/src/i830_sdvo.c b/src/i830_sdvo.c
index ecddbaf..3141cc9 100644
--- a/src/i830_sdvo.c
+++ b/src/i830_sdvo.c
@@ -557,13 +557,12 @@ 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(xf86OutputPtr output, uint16_t clock,
uint16_t width, uint16_t height)
{
- struct i830_sdvo_priv *dev_priv = output->dev_priv;
struct i830_sdvo_preferred_input_timing_args args;
+ uint8_t status;
args.clock = clock;
args.width = width;
@@ -578,10 +577,10 @@ i830_sdvo_create_preferred_input_timing(xf86OutputPtr output, uint16_t clock,
}
static Bool
-i830_sdvo_get_preferred_input_timing(I830OutputPtr output,
+i830_sdvo_get_preferred_input_timing(xf86OutputPtr output,
struct i830_sdvo_dtd *dtd)
{
- struct i830_sdvo_priv *dev_priv = output->dev_priv;
+ Bool status;
i830_sdvo_write_cmd(output, SDVO_CMD_GET_PREFERRED_INPUT_TIMING_PART1,
NULL, 0);
@@ -599,7 +598,6 @@ i830_sdvo_get_preferred_input_timing(I830OutputPtr output,
return TRUE;
}
-#endif
/** Returns the SDVO_CLOCK_RATE_MULT_* for the current clock multiplier */
static int
@@ -644,14 +642,155 @@ i830_sdvo_set_clock_rate_mult(xf86OutputPtr output, uint8_t val)
return TRUE;
}
+static void
+i830_sdvo_get_dtd_from_mode(struct i830_sdvo_dtd *dtd, DisplayModePtr mode)
+{
+ uint16_t width, height;
+ uint16_t h_blank_len, h_sync_len, v_blank_len, v_sync_len;
+ uint16_t h_sync_offset, v_sync_offset;
+
+ width = mode->CrtcHDisplay;
+ height = mode->CrtcVDisplay;
+
+ /* 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;
+
+ dtd->part1.clock = mode->Clock / 10;
+ dtd->part1.h_active = width & 0xff;
+ dtd->part1.h_blank = h_blank_len & 0xff;
+ dtd->part1.h_high = (((width >> 8) & 0xf) << 4) |
+ ((h_blank_len >> 8) & 0xf);
+ dtd->part1.v_active = height & 0xff;
+ dtd->part1.v_blank = v_blank_len & 0xff;
+ dtd->part1.v_high = (((height >> 8) & 0xf) << 4) |
+ ((v_blank_len >> 8) & 0xf);
+
+ dtd->part2.h_sync_off = h_sync_offset;
+ dtd->part2.h_sync_width = h_sync_len & 0xff;
+ dtd->part2.v_sync_off_width = (v_sync_offset & 0xf) << 4 |
+ (v_sync_len & 0xf);
+ dtd->part2.sync_off_width_high = ((h_sync_offset & 0x300) >> 2) |
+ ((h_sync_len & 0x300) >> 4) | ((v_sync_offset & 0x30) >> 2) |
+ ((v_sync_len & 0x30) >> 4);
+
+ dtd->part2.dtd_flags = 0x18;
+ if (mode->Flags & V_PHSYNC)
+ dtd->part2.dtd_flags |= 0x2;
+ if (mode->Flags & V_PVSYNC)
+ dtd->part2.dtd_flags |= 0x4;
+
+ dtd->part2.sdvo_flags = 0;
+ dtd->part2.v_sync_off_high = v_sync_offset & 0xc0;
+ dtd->part2.reserved = 0;
+}
+
+static void
+i830_sdvo_get_mode_from_dtd(DisplayModePtr mode, struct i830_sdvo_dtd *dtd)
+{
+ uint16_t width, height;
+ uint16_t h_blank_len, h_sync_len, v_blank_len, v_sync_len;
+ uint16_t h_sync_offset, v_sync_offset;
+
+ width = mode->CrtcHDisplay;
+ height = mode->CrtcVDisplay;
+
+ /* 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;
+
+ mode->HDisplay = dtd->part1.h_active;
+ mode->HDisplay += ((dtd->part1.h_high >> 4) & 0x0f) << 8;
+ mode->HSyncStart = mode->HDisplay + dtd->part2.h_sync_off;
+ mode->HSyncStart += (dtd->part2.sync_off_width_high & 0xa0) << 2;
+ mode->HSyncEnd = mode->HSyncStart + dtd->part2.h_sync_width;
+ mode->HSyncEnd += (dtd->part2.sync_off_width_high & 0x30) << 4;
+ mode->HTotal = mode->HDisplay + dtd->part1.h_blank;
+ mode->HTotal += (dtd->part1.h_high & 0xf) << 8;
+
+ mode->VDisplay = dtd->part1.v_active;
+ mode->VDisplay += ((dtd->part1.v_high >> 4) & 0x0f) << 8;
+ mode->VSyncStart = mode->VDisplay;
+ mode->VSyncStart += (dtd->part2.v_sync_off_width >> 4) & 0xf;
+ mode->VSyncStart += (dtd->part2.sync_off_width_high & 0x0a) << 2;
+ mode->VSyncStart += dtd->part2.v_sync_off_high & 0xc0;
+ mode->VSyncEnd = mode->VSyncStart + (dtd->part2.v_sync_off_width & 0xf);
+ mode->VSyncEnd += (dtd->part2.sync_off_width_high & 0x3) << 4;
+ mode->VTotal = mode->VDisplay + dtd->part1.v_blank;
+ mode->VTotal += (dtd->part1.v_high & 0xf) << 8;
+
+ mode->Clock = dtd->part1.clock * 10;
+
+ mode->Flags &= (V_PHSYNC | V_PVSYNC);
+ if (dtd->part2.dtd_flags & 0x2)
+ mode->Flags |= V_PHSYNC;
+ if (dtd->part2.dtd_flags & 0x4)
+ mode->Flags |= V_PVSYNC;
+}
+
static Bool
i830_sdvo_mode_fixup(xf86OutputPtr output, DisplayModePtr mode,
DisplayModePtr adjusted_mode)
{
- /* Make the CRTC code factor in the SDVO pixel multiplier. The SDVO
- * device will be told of the multiplier during mode_set.
- */
- adjusted_mode->Clock *= i830_sdvo_get_pixel_multiplier(mode);
+ I830OutputPrivatePtr intel_output = output->driver_private;
+ struct i830_sdvo_priv *dev_priv = intel_output->dev_priv;
+
+ if (!dev_priv->is_tv) {
+ /* Make the CRTC code factor in the SDVO pixel multiplier. The SDVO
+ * device will be told of the multiplier during mode_set.
+ */
+ adjusted_mode->Clock *= i830_sdvo_get_pixel_multiplier(mode);
+ } else {
+ struct i830_sdvo_dtd output_dtd;
+ Bool success;
+
+ /* We need to construct preferred input timings based on our output
+ * timings. To do that, we have to set the output timings, even
+ * though this isn't really the right place in the sequence to do it.
+ * Oh well.
+ */
+
+ ErrorF("output modeline:\n");
+ xf86PrintModeline(0, mode);
+
+ /* Set output timings */
+ i830_sdvo_get_dtd_from_mode(&output_dtd, mode);
+ i830_sdvo_set_target_output(output, dev_priv->controlled_output);
+ i830_sdvo_set_output_timing(output, &output_dtd);
+
+ /* Set the input timing to the screen. Assume always input 0. */
+ i830_sdvo_set_target_input(output, TRUE, FALSE);
+
+
+ success = i830_sdvo_create_preferred_input_timing(output,
+ mode->Clock / 10,
+ mode->HDisplay,
+ mode->VDisplay);
+ if (success) {
+ struct i830_sdvo_dtd input_dtd;
+
+ i830_sdvo_get_preferred_input_timing(output, &input_dtd);
+
+ i830_sdvo_get_mode_from_dtd(adjusted_mode, &input_dtd);
+
+ ErrorF("input modeline:\n");
+ xf86PrintModeline(0, adjusted_mode);
+ } else {
+ return FALSE;
+ }
+ }
return TRUE;
}
@@ -668,9 +807,6 @@ i830_sdvo_mode_set(xf86OutputPtr output, DisplayModePtr mode,
I830CrtcPrivatePtr intel_crtc = crtc->driver_private;
uint32_t sdvox;
int sdvo_pixel_multiply;
- uint16_t width, height;
- uint16_t h_blank_len, h_sync_len, v_blank_len, v_sync_len;
- uint16_t h_sync_offset, v_sync_offset;
struct i830_sdvo_in_out_map in_out;
struct i830_sdvo_dtd output_dtd;
uint8_t status;
@@ -691,50 +827,14 @@ i830_sdvo_mode_set(xf86OutputPtr output, DisplayModePtr mode,
&in_out, sizeof(in_out));
status = i830_sdvo_read_response(output, NULL, 0);
- width = mode->CrtcHDisplay;
- height = mode->CrtcVDisplay;
-
- /* 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;
+ /* If it's a TV, we already set the output timing in mode_fixup. */
+ if (!dev_priv->is_tv) {
+ i830_sdvo_get_dtd_from_mode(&output_dtd, mode);
- output_dtd.part1.clock = mode->Clock / 10;
- output_dtd.part1.h_active = width & 0xff;
- output_dtd.part1.h_blank = h_blank_len & 0xff;
- output_dtd.part1.h_high = (((width >> 8) & 0xf) << 4) |
- ((h_blank_len >> 8) & 0xf);
- output_dtd.part1.v_active = height & 0xff;
- output_dtd.part1.v_blank = v_blank_len & 0xff;
- output_dtd.part1.v_high = (((height >> 8) & 0xf) << 4) |
- ((v_blank_len >> 8) & 0xf);
-
- output_dtd.part2.h_sync_off = h_sync_offset;
- output_dtd.part2.h_sync_width = h_sync_len & 0xff;
- output_dtd.part2.v_sync_off_width = (v_sync_offset & 0xf) << 4 |
- (v_sync_len & 0xf);
- output_dtd.part2.sync_off_width_high = ((h_sync_offset & 0x300) >> 2) |
- ((h_sync_len & 0x300) >> 4) | ((v_sync_offset & 0x30) >> 2) |
- ((v_sync_len & 0x30) >> 4);
-
- output_dtd.part2.dtd_flags = 0x18;
- if (mode->Flags & V_PHSYNC)
- output_dtd.part2.dtd_flags |= 0x2;
- if (mode->Flags & V_PVSYNC)
- output_dtd.part2.dtd_flags |= 0x4;
-
- output_dtd.part2.sdvo_flags = 0;
- output_dtd.part2.v_sync_off_high = v_sync_offset & 0xc0;
- output_dtd.part2.reserved = 0;
-
- /* Set the output timing to the screen */
- i830_sdvo_set_target_output(output, dev_priv->controlled_output);
- i830_sdvo_set_output_timing(output, &output_dtd);
+ /* Set the output timing to the screen */
+ i830_sdvo_set_target_output(output, dev_priv->controlled_output);
+ i830_sdvo_set_output_timing(output, &output_dtd);
+ }
/* Set the input timing to the screen. Assume always input 0. */
i830_sdvo_set_target_input(output, TRUE, FALSE);
commit b61178524bece756dc0fd4f798c6c7743b5725db
Author: Eric Anholt <eric at anholt.net>
Date: Tue Apr 8 14:11:42 2008 -0700
SDVO: Fix lols TV mode list handling.
diff --git a/src/i830_sdvo.c b/src/i830_sdvo.c
index e25de3a..ecddbaf 100644
--- a/src/i830_sdvo.c
+++ b/src/i830_sdvo.c
@@ -1208,12 +1208,11 @@ i830_sdvo_get_tv_mode(DisplayModePtr *head, int width, int height,
mode->next = NULL;
mode->prev = NULL;
- mode->next = NULL;
- mode->prev = *head;
+ mode->next = *head;
+ mode->prev = NULL;
if (*head != NULL)
- (*head)->next = mode;
- else
- *head = mode;
+ (*head)->prev = mode;
+ *head = mode;
}
/**
commit 5db73f18d2badec37523850024b9aa824e4e6bd8
Author: Eric Anholt <eric at anholt.net>
Date: Tue Apr 8 13:53:51 2008 -0700
SDVO: Use the TV reference clock for SDVO TV outputs.
Based on a patch by Will Wiseman.
diff --git a/src/i830.h b/src/i830.h
index 834e4dc..318b188 100644
--- a/src/i830.h
+++ b/src/i830.h
@@ -288,6 +288,7 @@ typedef struct _I830OutputPrivateRec {
I2CBusPtr pDDCBus;
struct _I830DVODriver *i2c_drv;
Bool load_detect_temp;
+ Bool needs_tv_clock;
uint32_t lvds_bits;
int pipe_mask;
int clone_mask;
diff --git a/src/i830_display.c b/src/i830_display.c
index 4091e79..ca5e5dc 100644
--- a/src/i830_display.c
+++ b/src/i830_display.c
@@ -1100,6 +1100,8 @@ i830_crtc_mode_set(xf86CrtcPtr crtc, DisplayModePtr mode,
break;
case I830_OUTPUT_SDVO:
is_sdvo = TRUE;
+ if (intel_output->needs_tv_clock)
+ is_tv = TRUE;
break;
case I830_OUTPUT_DVO_TMDS:
case I830_OUTPUT_DVO_LVDS:
@@ -1144,7 +1146,8 @@ i830_crtc_mode_set(xf86CrtcPtr crtc, DisplayModePtr mode,
if (is_sdvo)
{
dpll |= DPLL_DVO_HIGH_SPEED;
- if (IS_I945G(pI830) || IS_I945GM(pI830) || IS_G33CLASS(pI830))
+ if ((IS_I945G(pI830) || IS_I945GM(pI830) || IS_G33CLASS(pI830)) &&
+ !is_tv)
{
int sdvo_pixel_multiply = adjusted_mode->Clock / mode->Clock;
dpll |= (sdvo_pixel_multiply - 1) << SDVO_MULTIPLIER_SHIFT_HIRES;
@@ -1182,7 +1185,9 @@ i830_crtc_mode_set(xf86CrtcPtr crtc, DisplayModePtr mode,
}
}
- if (is_tv)
+ if (is_sdvo && is_tv)
+ dpll |= PLL_REF_INPUT_TVCLKINBC;
+ else if (is_tv)
{
/* XXX: just matching BIOS for now */
/* dpll |= PLL_REF_INPUT_TVCLKINBC; */
diff --git a/src/i830_sdvo.c b/src/i830_sdvo.c
index 642ba88..e25de3a 100644
--- a/src/i830_sdvo.c
+++ b/src/i830_sdvo.c
@@ -1535,6 +1535,7 @@ i830_sdvo_init(ScrnInfoPtr pScrn, int output_device)
output->subpixel_order = SubPixelHorizontalRGB; /* XXX */
name_prefix="TV";
dev_priv->is_tv = TRUE;
+ intel_output->needs_tv_clock = TRUE;
}
else if (dev_priv->caps.output_flags & SDVO_OUTPUT_RGB0)
{
More information about the xorg-commit
mailing list