[patch 2/2] intel: enable SDVO-HDMI output
Hong Liu
hong.liu at intel.com
Tue Jun 3 00:45:57 PDT 2008
This patch enables the SDVO-HDMI output on my ASUS P5E-VM
motherboard(G35 platform). I can have display on our SONY TV
with 1920x1080 resolution.
You may need patch 1 (DSPARB fix 2nd) to get correct display.
VT switch is not working on HDMI output currently.
Thanks,
Hong
diff --git a/src/i830_sdvo.c b/src/i830_sdvo.c
index 2379127..3360af5 100644
--- a/src/i830_sdvo.c
+++ b/src/i830_sdvo.c
@@ -92,6 +92,9 @@ struct i830_sdvo_priv {
*/
struct i830_sdvo_tv_format tv_format;
+ /** supported encoding mode, used to determine whether HDMI is supported */
+ struct i830_sdvo_encode encode;
+
/** DDC bus used by this SDVO output */
uint8_t ddc_bus;
@@ -225,10 +228,23 @@ const static struct _sdvo_cmd_name {
SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_SUPPORTED_POWER_STATES),
SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_ENCODER_POWER_STATE),
SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_ENCODER_POWER_STATE),
- SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_TV_RESOLUTION_SUPPORT),
+ //SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_TV_RESOLUTION_SUPPORT),
SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_CONTROL_BUS_SWITCH),
SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_SDTV_RESOLUTION_SUPPORT),
SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_SUPPORTED_ENHANCEMENTS),
+ /* HDMI op code */
+ SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_SUPP_ENCODE),
+ SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_ENCODE),
+ SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_PIXEL_REPLI),
+ SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_COLORIMETRY_CAP),
+ SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_COLORIMETRY),
+ SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_AUDIO_ENCRYPT_PREFER),
+ SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_AUDIO_STAT),
+ SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_HBUF_INDEX),
+ SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_HBUF_INDEX),
+ SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_HBUF_INFO),
+ SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_HBUF_AV_SPLIT),
+ SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_HBUF_TXRATE),
};
static I2CSlaveAddr slaveAddr;
@@ -741,6 +757,190 @@ i830_sdvo_get_mode_from_dtd(DisplayModePtr mode, struct i830_sdvo_dtd *dtd)
}
static Bool
+i830_sdvo_get_supp_encode(xf86OutputPtr output, struct i830_sdvo_encode *encode)
+{
+ uint8_t status;
+
+ i830_sdvo_write_cmd(output, SDVO_CMD_GET_SUPP_ENCODE, NULL, 0);
+ status = i830_sdvo_read_response(output, encode, sizeof(*encode));
+ if (status != SDVO_CMD_STATUS_SUCCESS) {
+ memset(encode, 0, sizeof(*encode));
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+static Bool
+i830_sdvo_set_encode(xf86OutputPtr output, uint8_t mode)
+{
+ uint8_t status;
+
+ i830_sdvo_write_cmd(output, SDVO_CMD_SET_ENCODE, &mode, 1);
+ status = i830_sdvo_read_response(output, NULL, 0);
+
+ return (status == SDVO_CMD_STATUS_SUCCESS);
+}
+
+static Bool
+i830_sdvo_set_colorimetry(xf86OutputPtr output, uint8_t mode)
+{
+ uint8_t status;
+
+ i830_sdvo_write_cmd(output, SDVO_CMD_SET_COLORIMETRY, &mode, 1);
+ status = i830_sdvo_read_response(output, NULL, 0);
+
+ return (status == SDVO_CMD_STATUS_SUCCESS);
+}
+
+static Bool
+i830_sdvo_set_pixel_repli(xf86OutputPtr output, uint8_t repli)
+{
+ uint8_t status;
+
+ i830_sdvo_write_cmd(output, SDVO_CMD_SET_PIXEL_REPLI, &repli, 1);
+ status = i830_sdvo_read_response(output, NULL, 0);
+
+ return (status == SDVO_CMD_STATUS_SUCCESS);
+}
+
+static void i830_sdvo_dump_hdmi_buf(xf86OutputPtr output)
+{
+ int i, j;
+ uint8_t set_buf_index[2];
+ uint8_t av_split;
+ uint8_t buf_size;
+ uint8_t buf[48];
+ uint8_t *pos;
+
+
+ i830_sdvo_write_cmd(output, SDVO_CMD_GET_HBUF_AV_SPLIT, NULL, 0);
+ i830_sdvo_read_response(output, &av_split, 1);
+
+ for (i = 0; i <= av_split; i++) {
+ set_buf_index[0] = i; set_buf_index[1] = 0;
+ i830_sdvo_write_cmd(output, SDVO_CMD_SET_HBUF_INDEX,
+ set_buf_index, 2);
+ i830_sdvo_write_cmd(output, SDVO_CMD_GET_HBUF_INFO, NULL, 0);
+ i830_sdvo_read_response(output, &buf_size, 1);
+
+ pos = buf;
+ for (j = 0; j <= buf_size; j += 8) {
+ i830_sdvo_write_cmd(output, SDVO_CMD_GET_HBUF_DATA, NULL, 0);
+ i830_sdvo_read_response(output, pos, 8);
+ pos += 8;
+ }
+ }
+}
+
+static void i830_sdvo_set_hdmi_buf(xf86OutputPtr output, int index,
+ uint8_t *data, int8_t size, uint8_t tx_rate)
+{
+ uint8_t set_buf_index[2];
+
+ set_buf_index[0] = index;
+ set_buf_index[1] = 0;
+
+ i830_sdvo_write_cmd(output, SDVO_CMD_SET_HBUF_INDEX, set_buf_index, 2);
+
+ for (; size > 0; size -= 8) {
+ i830_sdvo_write_cmd(output, SDVO_CMD_SET_HBUF_DATA, data, 8);
+ data += 8;
+ }
+
+ i830_sdvo_write_cmd(output, SDVO_CMD_SET_HBUF_TXRATE, &tx_rate, 1);
+}
+
+static uint8_t i830_sdvo_calc_hbuf_csum(uint8_t *data, uint8_t size)
+{
+ uint8_t csum = 0;
+ int i;
+
+ for (i = 0; i < size; i++)
+ csum += data[i];
+
+ return 0x100 - csum;
+}
+
+#define DIP_TYPE_AVI 0x82
+#define DIP_VERSION_AVI 0x2
+#define DIP_LEN_AVI 13
+
+struct dip_infoframe {
+ uint8_t type;
+ uint8_t version;
+ uint8_t len;
+ uint8_t checksum;
+ union {
+ struct {
+ /* Packet Byte #1 */
+ uint8_t S:2;
+ uint8_t B:2;
+ uint8_t A:1;
+ uint8_t Y:2;
+ uint8_t rsvd1:1;
+ /* Packet Byte #2 */
+ uint8_t R:4;
+ uint8_t M:2;
+ uint8_t C:2;
+ /* Packet Byte #3 */
+ uint8_t SC:2;
+ uint8_t Q:2;
+ uint8_t EC:3;
+ uint8_t ITC:1;
+ /* Packet Byte #4 */
+ uint8_t VIC:7;
+ uint8_t rsvd2:1;
+ /* Packet Byte #5 */
+ uint8_t PR:4;
+ uint8_t rsvd3:4;
+ /* Packet Byte #6~13 */
+ uint16_t top_bar_end;
+ uint16_t bottom_bar_start;
+ uint16_t left_bar_end;
+ uint16_t right_bar_start;
+ } avi;
+ struct {
+ /* Packet Byte #1 */
+ uint8_t CC:3;
+ uint8_t rsvd1:1;
+ uint8_t CT:4;
+ /* Packet Byte #2 */
+ uint8_t SS:2;
+ uint8_t SF:3;
+ uint8_t rsvd2:3;
+ /* Packet Byte #3 */
+ uint8_t CXT:5;
+ uint8_t rsvd3:3;
+ /* Packet Byte #4 */
+ uint8_t CA;
+ /* Packet Byte #5 */
+ uint8_t rsvd4:3;
+ uint8_t LSV:4;
+ uint8_t DM_INH:1;
+ } audio;
+ uint8_t payload[28];
+ } __attribute__ ((packed)) u;
+} __attribute__((packed));
+
+static void i830_sdvo_set_avi_infoframe(xf86OutputPtr output,
+ DisplayModePtr mode)
+{
+ I830OutputPrivatePtr intel_output = output->driver_private;
+ struct dip_infoframe avi_if = {
+ .type = DIP_TYPE_AVI,
+ .version = DIP_VERSION_AVI,
+ .len = DIP_LEN_AVI,
+ };
+
+ avi_if.u.avi.PR = i830_sdvo_get_pixel_multiplier(mode) - 1;
+ avi_if.checksum = i830_sdvo_calc_hbuf_csum((uint8_t *)&avi_if,
+ 4 + avi_if.len);
+ i830_sdvo_set_hdmi_buf(output, 1, (uint8_t *)&avi_if, 4 + avi_if.len,
+ SDVO_HBUF_TX_VSYNC);
+}
+
+static Bool
i830_sdvo_mode_fixup(xf86OutputPtr output, DisplayModePtr mode,
DisplayModePtr adjusted_mode)
{
@@ -827,6 +1027,9 @@ i830_sdvo_mode_set(xf86OutputPtr output, DisplayModePtr mode,
&in_out, sizeof(in_out));
status = i830_sdvo_read_response(output, NULL, 0);
+ if (dev_priv->encode.hdmi_rev)
+ i830_sdvo_set_avi_infoframe(output, mode);
+
i830_sdvo_get_dtd_from_mode(&input_dtd, mode);
/* If it's a TV, we already set the output timing in mode_fixup.
@@ -1201,6 +1404,15 @@ i830_sdvo_dump_device(xf86OutputPtr output)
i830_sdvo_dump_cmd(output, SDVO_CMD_GET_TV_FORMAT);
i830_sdvo_dump_cmd(output, SDVO_CMD_GET_SDTV_RESOLUTION_SUPPORT);
i830_sdvo_dump_cmd(output, SDVO_CMD_GET_SUPPORTED_ENHANCEMENTS);
+
+ i830_sdvo_dump_cmd(output, SDVO_CMD_GET_SUPP_ENCODE);
+ i830_sdvo_dump_cmd(output, SDVO_CMD_GET_ENCODE);
+ i830_sdvo_dump_cmd(output, SDVO_CMD_GET_PIXEL_REPLI);
+ i830_sdvo_dump_cmd(output, SDVO_CMD_GET_COLORIMETRY_CAP);
+ i830_sdvo_dump_cmd(output, SDVO_CMD_GET_COLORIMETRY);
+ i830_sdvo_dump_cmd(output, SDVO_CMD_GET_AUDIO_ENCRYPT_PREFER);
+ i830_sdvo_dump_cmd(output, SDVO_CMD_GET_AUDIO_STAT);
+ i830_sdvo_dump_hdmi_buf(output);
}
void
@@ -1618,17 +1830,22 @@ i830_sdvo_init(ScrnInfoPtr pScrn, int output_device)
i830_sdvo_get_capabilities(output, &dev_priv->caps);
- if (dev_priv->caps.output_flags & SDVO_OUTPUT_TMDS0)
- {
- dev_priv->controlled_output = SDVO_OUTPUT_TMDS0;
- output->subpixel_order = SubPixelHorizontalRGB;
- name_prefix="TMDS";
- }
- else if (dev_priv->caps.output_flags & SDVO_OUTPUT_TMDS1)
+ if (dev_priv->caps.output_flags & (SDVO_OUTPUT_TMDS0 | SDVO_OUTPUT_TMDS1))
{
- dev_priv->controlled_output = SDVO_OUTPUT_TMDS1;
+ 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";
+
+ i830_sdvo_get_supp_encode(output, &dev_priv->encode);
+ if (dev_priv->encode.hdmi_rev != 0) {
+ /* 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)
{
diff --git a/src/i830_sdvo_regs.h b/src/i830_sdvo_regs.h
index dc2522a..cdf3e27 100644
--- a/src/i830_sdvo_regs.h
+++ b/src/i830_sdvo_regs.h
@@ -503,7 +503,7 @@ struct i830_sdvo_enhancements_arg {
# define SDVO_DITHER_ON (1 << 0)
# define SDVO_DITHER_DEFAULT_ON (1 << 1)
-#define SDVO_CMD_SET_TV_RESOLUTION_SUPPORT 0x93
+//#define SDVO_CMD_SET_TV_RESOLUTION_SUPPORT 0x93
#define SDVO_CMD_SET_CONTROL_BUS_SWITCH 0x7a
# define SDVO_CONTROL_BUS_PROM (1 << 0)
@@ -511,3 +511,39 @@ struct i830_sdvo_enhancements_arg {
# define SDVO_CONTROL_BUS_DDC2 (1 << 2)
# define SDVO_CONTROL_BUS_DDC3 (1 << 3)
+/* HDMI op codes */
+#define SDVO_CMD_GET_SUPP_ENCODE 0x9d
+#define SDVO_CMD_GET_ENCODE 0x9e
+#define SDVO_CMD_SET_ENCODE 0x9f
+ #define SDVO_ENCODE_DVI 0x0
+ #define SDVO_ENCODE_HDMI 0x1
+#define SDVO_CMD_SET_PIXEL_REPLI 0x8b
+#define SDVO_CMD_GET_PIXEL_REPLI 0x8c
+#define SDVO_CMD_GET_COLORIMETRY_CAP 0x8d
+#define SDVO_CMD_SET_COLORIMETRY 0x8e
+ #define SDVO_COLORIMETRY_RGB256 0x0
+ #define SDVO_COLORIMETRY_RGB220 0x1
+ #define SDVO_COLORIMETRY_YCrCb422 0x3
+ #define SDVO_COLORIMETRY_YCrCb444 0x4
+#define SDVO_CMD_GET_COLORIMETRY 0x8f
+#define SDVO_CMD_GET_AUDIO_ENCRYPT_PREFER 0x90
+#define SDVO_CMD_SET_AUDIO_STAT 0x91
+#define SDVO_CMD_GET_AUDIO_STAT 0x92
+#define SDVO_CMD_SET_HBUF_INDEX 0x93
+#define SDVO_CMD_GET_HBUF_INDEX 0x94
+#define SDVO_CMD_GET_HBUF_INFO 0x95
+#define SDVO_CMD_SET_HBUF_AV_SPLIT 0x96
+#define SDVO_CMD_GET_HBUF_AV_SPLIT 0x97
+#define SDVO_CMD_SET_HBUF_DATA 0x98
+#define SDVO_CMD_GET_HBUF_DATA 0x99
+#define SDVO_CMD_SET_HBUF_TXRATE 0x9a
+#define SDVO_CMD_GET_HBUF_TXRATE 0x9b
+ #define SDVO_HBUF_TX_DISABLED (0 << 6)
+ #define SDVO_HBUF_TX_ONCE (2 << 6)
+ #define SDVO_HBUF_TX_VSYNC (3 << 6)
+#define SDVO_CMD_GET_AUDIO_TX_INFO 0x9c
+
+struct i830_sdvo_encode{
+ uint8_t dvi_rev;
+ uint8_t hdmi_rev;
+} __attribute__ ((packed));
More information about the xorg
mailing list