[Intel-gfx] [PATCH 2/2] SDVO: handle multifunction encoder
Zhenyu Wang
zhenyu.z.wang at intel.com
Mon Jan 5 09:35:34 CET 2009
For SDVO encoder that advertise multiple functions,
we have to get current attached display to determine
output type.
---
src/i830_sdvo.c | 237 +++++++++++++++++++++++++++++++++++++-----------------
1 files changed, 162 insertions(+), 75 deletions(-)
diff --git a/src/i830_sdvo.c b/src/i830_sdvo.c
index 219eb6a..b96454f 100644
--- a/src/i830_sdvo.c
+++ b/src/i830_sdvo.c
@@ -66,6 +66,11 @@ struct i830_sdvo_priv {
*/
struct i830_sdvo_caps caps;
+ /**
+ * SDVO devices currently attached by i830_sdvo_get_attached_display()
+ */
+ uint16_t attached_output;
+
/** Pixel clock limitations reported by the SDVO device, in kHz */
int pixel_clock_min, pixel_clock_max;
@@ -113,6 +118,8 @@ struct i830_sdvo_priv {
/** @} */
};
+static Bool i830_sdvo_output_setup(xf86OutputPtr , uint16_t );
+
/**
* Writes the SDVOB or SDVOC with the given value, but always writes both
* SDVOB and SDVOC to work around apparent hardware issues (according to
@@ -1455,12 +1462,52 @@ i830_sdvo_digital_output(xf86OutputPtr output)
I830OutputPrivatePtr intel_output = output->driver_private;
struct i830_sdvo_priv *dev_priv = intel_output->dev_priv;
- if (dev_priv->caps.output_flags & (SDVO_OUTPUT_TMDS0 | SDVO_OUTPUT_TMDS1))
+ if (dev_priv->attached_output & (SDVO_OUTPUT_TMDS0 | SDVO_OUTPUT_TMDS1))
return TRUE;
else
return FALSE;
}
+static Bool
+i830_sdvo_get_attached_display (xf86OutputPtr output, uint16_t* response)
+{
+ uint8_t status;
+
+ i830_sdvo_write_cmd(output, SDVO_CMD_GET_ATTACHED_DISPLAYS, NULL, 0);
+
+ status = i830_sdvo_read_response(output, response, 2);
+ if (status != SDVO_CMD_STATUS_SUCCESS)
+ return FALSE;
+ else
+ return TRUE;
+}
+
+
+static Bool
+i830_sdvo_multifunc_encoder(xf86OutputPtr output)
+{
+ I830OutputPrivatePtr intel_output = output->driver_private;
+ struct i830_sdvo_priv *dev_priv = intel_output->dev_priv;
+ int count = 0;
+
+ if (dev_priv->caps.output_flags & (SDVO_OUTPUT_TMDS0 |
+ SDVO_OUTPUT_TMDS1))
+ count++;
+ if (dev_priv->caps.output_flags & (SDVO_OUTPUT_RGB0 |
+ SDVO_OUTPUT_RGB1))
+ count++;
+ if (dev_priv->caps.output_flags & (SDVO_OUTPUT_CVBS0 |
+ SDVO_OUTPUT_SVID0 | SDVO_OUTPUT_YPRPB0 |
+ SDVO_OUTPUT_SCART0 | SDVO_OUTPUT_CVBS1 |
+ SDVO_OUTPUT_SVID1 | SDVO_OUTPUT_YPRPB1 |
+ SDVO_OUTPUT_SCART1))
+ count++;
+ if (dev_priv->caps.output_flags & (SDVO_OUTPUT_LVDS0 |
+ SDVO_OUTPUT_LVDS1))
+ count++;
+ return (count > 1);
+}
+
/**
* Asks the SDVO device if any displays are currently connected.
*
@@ -1474,19 +1521,25 @@ static xf86OutputStatus
i830_sdvo_detect(xf86OutputPtr output)
{
I830OutputPrivatePtr intel_output = output->driver_private;
+ struct i830_sdvo_priv *dev_priv = intel_output->dev_priv;
xf86MonPtr edid_mon;
- uint8_t response[2];
- uint8_t status;
-
- i830_sdvo_write_cmd(output, SDVO_CMD_GET_ATTACHED_DISPLAYS, NULL, 0);
- status = i830_sdvo_read_response(output, &response, 2);
+ uint16_t response;
- if (status != SDVO_CMD_STATUS_SUCCESS)
+ if (i830_sdvo_get_attached_display(output, &response)
+ == FALSE)
return XF86OutputStatusUnknown;
- if (response[0] == 0 && response[1] == 0)
+ if (response == 0)
return XF86OutputStatusDisconnected;
+ if (dev_priv->attached_output != response) {
+ dev_priv->attached_output = response;
+ if (i830_sdvo_multifunc_encoder(output) &&
+ i830_sdvo_output_setup(output, dev_priv->attached_output)
+ == FALSE)
+ return XF86OutputStatusUnknown;
+ }
+
if (i830_sdvo_digital_output(output)) {
/* EDID is required and type should be digital, otherwise
we don't assume it's connected. */
@@ -1773,6 +1826,94 @@ i830_sdvo_get_digital_encoding_mode(xf86OutputPtr output)
return TRUE;
}
+static Bool
+i830_sdvo_output_setup(xf86OutputPtr output, uint16_t flag)
+{
+ I830OutputPrivatePtr intel_output = output->driver_private;
+ struct i830_sdvo_priv *dev_priv = intel_output->dev_priv;
+ char name[60];
+ char *name_prefix;
+ char *name_suffix;
+
+ if (dev_priv->output_device == SDVOB)
+ name_suffix="-1";
+ else
+ name_suffix="-2";
+
+ if (flag & (SDVO_OUTPUT_TMDS0 | SDVO_OUTPUT_TMDS1))
+ {
+ if (flag & SDVO_OUTPUT_TMDS0)
+ dev_priv->controlled_output = SDVO_OUTPUT_TMDS0;
+ else
+ dev_priv->controlled_output = SDVO_OUTPUT_TMDS1;
+ output->subpixel_order = SubPixelHorizontalRGB;
+ name_prefix="TMDS";
+
+ if (i830_sdvo_get_supp_encode(output, &dev_priv->encode) &&
+ i830_sdvo_get_digital_encoding_mode(output) &&
+ dev_priv->is_hdmi) {
+ /* enable hdmi encoding mode if supported */
+ i830_sdvo_set_encode(output, SDVO_ENCODE_HDMI);
+ i830_sdvo_set_colorimetry(output, SDVO_COLORIMETRY_RGB256);
+ name_prefix = "HDMI";
+ }
+ }
+ else if (flag & SDVO_OUTPUT_RGB0)
+ {
+ dev_priv->controlled_output = SDVO_OUTPUT_RGB0;
+ output->subpixel_order = SubPixelHorizontalRGB;
+ name_prefix="VGA";
+ }
+ else if (flag & SDVO_OUTPUT_RGB1)
+ {
+ dev_priv->controlled_output = SDVO_OUTPUT_RGB1;
+ output->subpixel_order = SubPixelHorizontalRGB;
+ name_prefix="VGA";
+ }
+ else if (dev_priv->caps.output_flags & SDVO_OUTPUT_LVDS0)
+ {
+ dev_priv->controlled_output = SDVO_OUTPUT_LVDS0;
+ output->subpixel_order = SubPixelHorizontalRGB;
+ name_prefix="LVDS";
+ }
+ else if (dev_priv->caps.output_flags & SDVO_OUTPUT_LVDS1)
+ {
+ dev_priv->controlled_output = SDVO_OUTPUT_LVDS1;
+ output->subpixel_order = SubPixelHorizontalRGB;
+ name_prefix="LVDS";
+ }
+ else if (flag & SDVO_OUTPUT_SVID0)
+ {
+ dev_priv->controlled_output = SDVO_OUTPUT_SVID0;
+ output->subpixel_order = SubPixelHorizontalRGB; /* XXX */
+ name_prefix="TV";
+ dev_priv->is_tv = TRUE;
+ intel_output->needs_tv_clock = TRUE;
+ }
+ else
+ {
+ unsigned char bytes[2];
+
+ dev_priv->controlled_output = 0;
+ memcpy (bytes, &flag, 2);
+ xf86DrvMsg(intel_output->pI2CBus->scrnIndex, X_WARNING,
+ "%s: Unknown SDVO output type (0x%02x%02x)\n",
+ SDVO_NAME(dev_priv),
+ bytes[0], bytes[1]);
+ name_prefix="Unknown";
+ }
+
+ strcpy (name, name_prefix);
+ strcat (name, name_suffix);
+ if (!xf86OutputRename (output, name)) {
+ return FALSE;
+ }
+
+ i830_sdvo_select_ddc_bus(dev_priv);
+
+ return TRUE;
+}
+
Bool
i830_sdvo_init(ScrnInfoPtr pScrn, int output_device)
{
@@ -1782,11 +1923,9 @@ i830_sdvo_init(ScrnInfoPtr pScrn, int output_device)
int i;
unsigned char ch[0x40];
I2CBusPtr i2cbus = NULL, ddcbus;
- char name[60];
- char *name_prefix;
- char *name_suffix;
- output = xf86OutputCreate (pScrn, &i830_sdvo_output_funcs,NULL);
+ output = xf86OutputCreate (pScrn, &i830_sdvo_output_funcs,
+ (output_device == SDVOB) ? "SDVOB" : "SDVOC");
if (!output)
return FALSE;
intel_output = xnfcalloc (sizeof (I830OutputPrivateRec) +
@@ -1824,11 +1963,9 @@ i830_sdvo_init(ScrnInfoPtr pScrn, int output_device)
if (output_device == SDVOB) {
dev_priv->d.DevName = "SDVO Controller B";
dev_priv->d.SlaveAddr = 0x70;
- name_suffix="-1";
} else {
dev_priv->d.DevName = "SDVO Controller C";
dev_priv->d.SlaveAddr = 0x72;
- name_suffix="-2";
}
dev_priv->d.pI2CBus = i2cbus;
dev_priv->d.DriverPrivate.ptr = output;
@@ -1889,76 +2026,26 @@ i830_sdvo_init(ScrnInfoPtr pScrn, int output_device)
intel_output->pDDCBus = ddcbus;
intel_output->dev_priv = dev_priv;
- i830_sdvo_get_capabilities(output, &dev_priv->caps);
-
- if (dev_priv->caps.output_flags & (SDVO_OUTPUT_TMDS0 | SDVO_OUTPUT_TMDS1))
+ if (i830_sdvo_get_capabilities(output, &dev_priv->caps) == FALSE ||
+ dev_priv->caps.output_flags == 0)
{
- if (dev_priv->caps.output_flags & SDVO_OUTPUT_TMDS0)
- dev_priv->controlled_output = SDVO_OUTPUT_TMDS0;
- else
- dev_priv->controlled_output = SDVO_OUTPUT_TMDS1;
- output->subpixel_order = SubPixelHorizontalRGB;
- name_prefix="TMDS";
-
- if (i830_sdvo_get_supp_encode(output, &dev_priv->encode) &&
- i830_sdvo_get_digital_encoding_mode(output) &&
- dev_priv->is_hdmi) {
- /* enable hdmi encoding mode if supported */
- i830_sdvo_set_encode(output, SDVO_ENCODE_HDMI);
- i830_sdvo_set_colorimetry(output, SDVO_COLORIMETRY_RGB256);
- name_prefix = "HDMI";
- }
- }
- else if (dev_priv->caps.output_flags & SDVO_OUTPUT_SVID0)
- {
- dev_priv->controlled_output = SDVO_OUTPUT_SVID0;
- 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)
- {
- dev_priv->controlled_output = SDVO_OUTPUT_RGB0;
- output->subpixel_order = SubPixelHorizontalRGB;
- name_prefix="VGA";
- }
- else if (dev_priv->caps.output_flags & SDVO_OUTPUT_RGB1)
- {
- dev_priv->controlled_output = SDVO_OUTPUT_RGB1;
- output->subpixel_order = SubPixelHorizontalRGB;
- name_prefix="VGA";
- } else if (dev_priv->caps.output_flags & SDVO_OUTPUT_LVDS0) {
- dev_priv->controlled_output = SDVO_OUTPUT_LVDS0;
- output->subpixel_order = SubPixelHorizontalRGB;
- name_prefix="LVDS";
- } else if (dev_priv->caps.output_flags & SDVO_OUTPUT_LVDS1) {
- dev_priv->controlled_output = SDVO_OUTPUT_LVDS1;
- output->subpixel_order = SubPixelHorizontalRGB;
- name_prefix="LVDS";
- }
- else
- {
- unsigned char bytes[2];
-
- dev_priv->controlled_output = 0;
- memcpy (bytes, &dev_priv->caps.output_flags, 2);
xf86DrvMsg(intel_output->pI2CBus->scrnIndex, X_WARNING,
- "%s: Unknown SDVO output type (0x%02x%02x)\n",
- SDVO_NAME(dev_priv),
- bytes[0], bytes[1]);
- name_prefix="Unknown";
+ "%s: can't get encoder capability\n",
+ SDVO_NAME(dev_priv));
+ xf86OutputDestroy (output);
+ return FALSE;
}
- strcpy (name, name_prefix);
- strcat (name, name_suffix);
- if (!xf86OutputRename (output, name))
+ /* if capability flags has no multiple function outputs,
+ setup output, else leave to ->detect time */
+ if (!i830_sdvo_multifunc_encoder(output) &&
+ i830_sdvo_output_setup(output, dev_priv->caps.output_flags)
+ == FALSE)
{
xf86OutputDestroy (output);
return FALSE;
}
- i830_sdvo_select_ddc_bus(dev_priv);
/* Set the input timing to the screen. Assume always input 0. */
i830_sdvo_set_target_input(output, TRUE, FALSE);
--
1.5.6.5
More information about the Intel-gfx
mailing list