On Wed, Nov 19, 2008 at 04:08:00PM +0800, Wu Fengguang wrote:
> On Tue, Nov 18, 2008 at 11:55:45PM -0800, Shane W wrote:
> > On Wed, Nov 19, 2008 at 03:17:57PM +0800, Wu Fengguang wrote:
> > > On Tue, Nov 18, 2008 at 11:11:35PM -0800, Shane W wrote:
> > > > On Thu, Nov 13, 2008 at 10:21:53AM +0800, Wu Fengguang wrote:
> > > > > Create hda_eld.c for ELD routines and proc interface.
> > >
> > > > Just testing this and your multichannel HDMI code over here
> > > > but it doesn't seem to get ELD data for my setup. Intel
> > > > g45-id board with an Yamaha RX-v1800 receiver which is HDMI
> > > > 1.3 capable.
> > >
> > > Do you run the latest xorg intel driver? Also dmesg should tell us
> > > something if anything goes wrong with ELD retrieving/parsing.
> >
> > Yes though Xorg wasn't running when I was doing the audio
> > tests. Pure console at that point but I fired up Xorg
> > which is latest git as of today but still no ELD
>
> Yeah sorry I missed one note. The xorg git tree only contains the
> audio output enabling patches, but not yet ELD transferring patches.
> (the ELD data flow is monitor => video driver => audio driver)
> I called for the Xorg ELD enabling patches from Ma Ling just after
> replying to your email. He should send the patches soon.
Hi Shane,
I managed to update the last working Xorg ELD patches to the latest
git tree, and they compile flawlessly. The attached 2 patches are for
xf86-video-intel/ and xserver/ respectively.
Thanks,
Fengguang
---
src/i810_reg.h | 13 ++-
src/i830.h | 3
src/i830_hdmi.c | 64 +++++++++++++++
src/i830_modes.c | 189 +++++++++++++++++++++++++++++++++++++++++++++
src/i830_sdvo.c | 49 ++++++++++-
src/i830_sdvo.h | 2
6 files changed, 313 insertions(+), 7 deletions(-)
--- xf86-video-intel.orig/src/i810_reg.h
+++ xf86-video-intel/src/i810_reg.h
@@ -1240,6 +1240,7 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN
# define HDMID_HOTPLUG_INT_EN (1 << 27)
# define SDVOB_HOTPLUG_INT_EN (1 << 26)
# define SDVOC_HOTPLUG_INT_EN (1 << 25)
+# define AUDIO_HOTPLUG_INT_EN (1 << 24)
# define TV_HOTPLUG_INT_EN (1 << 18)
# define CRT_HOTPLUG_INT_EN (1 << 9)
# define CRT_HOTPLUG_ACTIVATION_PERIOD_32 (0 << 8)
@@ -1271,7 +1272,17 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN
# define CRT_HOTPLUG_MONITOR_NONE (0 << 8)
# define SDVOC_HOTPLUG_INT_STATUS (1 << 7)
# define SDVOB_HOTPLUG_INT_STATUS (1 << 6)
-
+#define AUDIO_VENDOR_DEVICE_ID 0x62020
+#define INTEL_AUDIO_DEVCL 0x808629FB
+#define INTEL_AUDIO_DEVBLC 0x80862801
+#define INTEL_AUDIO_DEVCTG 0x80862802
+
+#define AUDIO_CNTL_STATUS 0x620B4
+#define AUDIO_ELD_VALID_DEVCL_DEVBLC (1 << 13)
+#define AUDIO_ELD_VALID_DEVCTG (1 << 14)
+#define AUDIO_ELD_ADDR (0xf << 5)
+#define AUDIO_ELD_ACK (1 << 4)
+#define AUDIO_HDMIW_HDMIEDID 0x6210C
#define SDVOB 0x61140
#define SDVOC 0x61160
#define SDVO_ENABLE (1 << 31)
--- xf86-video-intel.orig/src/i830.h
+++ xf86-video-intel/src/i830.h
@@ -887,7 +887,8 @@ Bool I830UnbindAGPMemory(ScrnInfoPtr pSc
/* i830_modes.c */
DisplayModePtr i830_ddc_get_modes(xf86OutputPtr output);
-
+int i830_handle_cea_like_data(xf86OutputPtr output,Uchar **buf);
+unsigned long i830_extract_max_tmds_clock(xf86OutputPtr output);
/* i830_tv.c */
void i830_tv_init(ScrnInfoPtr pScrn);
--- xf86-video-intel.orig/src/i830_hdmi.c
+++ xf86-video-intel/src/i830_hdmi.c
@@ -45,12 +45,17 @@ struct i830_hdmi_priv {
static int
i830_hdmi_mode_valid(xf86OutputPtr output, DisplayModePtr mode)
{
+ unsigned long tmds_max_clock = i830_extract_max_tmds_clock(output);
+
if (mode->Clock > 165000)
return MODE_CLOCK_HIGH;
if (mode->Clock < 20000)
return MODE_CLOCK_LOW;
+ if( 0 < tmds_max_clock && tmds_max_clock < mode->Clock)
+ return MODE_CLOCK_HIGH;
+
return MODE_OK;
}
@@ -64,6 +69,60 @@ i830_hdmi_mode_fixup(xf86OutputPtr outpu
return TRUE;
}
+static uint32_t i830_hdmi_get_eld_flag(I830Ptr pI830 )
+{
+ uint32_t ar ;
+
+ ar = INREG(AUDIO_VENDOR_DEVICE_ID);
+
+ if (INTEL_AUDIO_DEVBLC == ar || INTEL_AUDIO_DEVCL == ar) {
+ ar = AUDIO_ELD_VALID_DEVCL_DEVBLC;
+ } else {
+ ar = AUDIO_ELD_VALID_DEVCTG;
+ }
+
+ return ar;
+
+}
+
+static void i830_hdmi_set_edid_like_data(xf86OutputPtr output)
+{
+ I830Ptr pI830 = I830PTR(output->scrn);
+ uint32_t *eld;
+ int eld_len;
+ uint32_t ar;
+ uint32_t flag;
+ int i;
+
+
+ eld = NULL;
+ eld_len = i830_extract_cea_like_data(output, (Uchar **)&eld);
+ eld_len = eld_len / sizeof(uint32_t);
+
+ if (NULL == eld) {
+ xf86DrvMsg(output->scrn->scrnIndex, X_ERROR,
+ "HDMI failed to get ELD \n");
+ goto end;
+ }
+
+ flag = i830_hdmi_get_eld_flag(pI830);
+
+ ar = INREG(AUDIO_CNTL_STATUS);
+ ar &= ~(flag | AUDIO_ELD_ADDR);
+ OUTREG(AUDIO_CNTL_STATUS, ar);
+
+ for (i = 0; i < eld_len; i = i + 1)
+ OUTREG(AUDIO_HDMIW_HDMIEDID, eld[i]);
+
+ ar = INREG(AUDIO_CNTL_STATUS);
+ ar |= flag ;
+ OUTREG(AUDIO_CNTL_STATUS, ar);
+
+end:
+ if (NULL != eld )
+ xfree(eld);
+}
+
static void
i830_hdmi_mode_set(xf86OutputPtr output, DisplayModePtr mode,
DisplayModePtr adjusted_mode)
@@ -76,6 +135,8 @@ i830_hdmi_mode_set(xf86OutputPtr output,
I830CrtcPrivatePtr intel_crtc = crtc->driver_private;
uint32_t sdvox;
+ i830_hdmi_set_edid_like_data(output);
+
sdvox = SDVO_ENCODING_HDMI |
SDVO_BORDER_ENABLE |
SDVO_VSYNC_ACTIVE_HIGH |
@@ -165,7 +226,8 @@ i830_hdmi_detect(xf86OutputPtr output)
temp |
HDMIB_HOTPLUG_INT_EN |
HDMIC_HOTPLUG_INT_EN |
- HDMID_HOTPLUG_INT_EN);
+ HDMID_HOTPLUG_INT_EN |
+ AUDIO_HOTPLUG_INT_EN);
POSTING_READ(PORT_HOTPLUG_EN);
--- xf86-video-intel.orig/src/i830_modes.c
+++ xf86-video-intel/src/i830_modes.c
@@ -54,6 +54,195 @@
#include "xf86Modes.h"
#include <randrstr.h>
+#define CEA_LIKE_DATA_MAX_LEN 48
+struct eld_header{
+ Uchar rsv_0 :3;
+ Uchar ELD_ver :5;
+ Uchar rsv_1;
+ Uchar baseline_ELD_len;
+ Uchar rsv_3;
+}__attribute__ ((packed));
+
+struct eld_data_fixed_fields {
+ struct eld_header header;
+
+ /* byte 1 */
+ Uchar MNL :5;
+ Uchar CEA_EDID_ver :3;
+
+ /* byte 2 */
+ Uchar HDCP :1;
+ Uchar S_AI :1;
+ Uchar Conn_Type :2;
+ Uchar SAD_Count :4;
+
+ /* byte 3 */
+ Uchar Aud_Synch_Delay;
+
+ /* byte 4 */
+ Uchar FLR :1;
+ Uchar LFE :1;
+ Uchar FC :1;
+ Uchar RLR :1;
+ Uchar RC :1;
+ Uchar FLRC :1;
+ Uchar RLRC :1;
+ Uchar rsv_7 :1;
+
+ /* byte 5-12 */
+ Uchar Port_ID[8]; /* little endian */
+
+ /* byte 13-14 */
+ Uchar Manufacture_Name[2];
+ /* byte 15-16 */
+ Uchar Product_Code[2];
+
+ /* byte 17 len MNL */
+ char Monitor_Name[0];
+} __attribute__ ((packed));
+
+unsigned long i830_extract_max_tmds_clock(xf86OutputPtr output)
+{
+ struct cea_data_blk *blk ;
+ struct extension_type type;
+
+ unsigned long ret = 0;
+
+ if (0 == (EDID_CEA_EXTENSION_FLG & output->MonInfo->flags)) {
+ goto end;
+ }
+
+ type.body_type = CEA_EXT;
+ type.data_type = CEA_VENDOR_BLK;
+ blk = (struct cea_data_blk *)xf86DDCGetCEA( output->MonInfo,&type);
+
+ if (NULL != blk) {
+ if (VENDOR_OFFSET(struct cea_vendor_blk, hdmi.Max_TMDS_Clock) <=
+ blk->len) {
+ ret = blk->u.vendor.hdmi.Max_TMDS_Clock * HDMI_MAX_TMDS_UNIT;
+ }
+ }
+end:
+ return ret;
+}
+
+int i830_extract_cea_like_data(xf86OutputPtr output, Uchar **buf)
+{
+ struct eld_data_fixed_fields *eld;
+ struct cea_data_blk *blk ;
+ struct cea_audio_blk *audio;
+ struct extension_type type;
+ Uchar *name ;
+ int i;
+ int eld_len;
+ int SAD_Count;
+
+
+ if (0 == (EDID_CEA_EXTENSION_FLG & output->MonInfo->flags)) {
+ eld = NULL;
+ eld_len = 0;
+ goto end;
+ }
+
+ name = NULL;
+ audio = NULL;
+
+ eld_len = sizeof(struct eld_data_fixed_fields);
+
+ type.body_type = CEA_EXT;
+ type.data_type = CEA_AUDIO_BLK;
+ blk = (struct cea_data_blk *)xf86DDCGetCEA(output->MonInfo, &type);
+
+ SAD_Count = 0;
+ if (NULL != blk) {
+ audio = (struct cea_audio_blk *)&blk->u.audio;
+ eld_len = eld_len + blk->len;
+ SAD_Count = blk->len/3; // SAD_Count is multiple of 3 bytes
+ }
+
+ for (i=0; i<output->MonInfo->det_mon_num; i++) {
+ if (0xfc == output->MonInfo->det_mon[i].type){
+ eld_len = eld_len + EDID_DET_NAME_LEN ;
+ name = output->MonInfo->det_mon[i].section.name;
+ break;
+ }
+ }
+ /* The item need to be multiple of 8 because sdvo write 8 bytes one time */
+ eld_len = (eld_len + 7)/8;
+ eld_len = eld_len * 8;
+ eld = (struct eld_data_fixed_fields *)xcalloc(1, eld_len);
+
+ if (NULL == eld) {
+ eld_len = 0;
+ goto end;
+ }
+
+ memset((Uchar *)eld, 0, eld_len);
+ /* The item need to be multiple of 4 */
+ eld->header.baseline_ELD_len = (eld_len - sizeof(struct eld_header))/4;
+ eld->header.ELD_ver = CEA_EXT;
+ eld->HDCP = 0;
+ eld->CEA_EDID_ver = output->MonInfo->ver.version;
+ if (NULL != name) {
+ eld->MNL = EDID_DET_NAME_LEN;
+ }
+ eld->SAD_Count = SAD_Count;
+ type.body_type = CEA_EXT;
+ type.data_type = CEA_VENDOR_BLK;
+ blk = (struct cea_data_blk *)xf86DDCGetCEA( output->MonInfo,&type);
+
+ eld->Conn_Type = 0;
+ /* Currently do not consider about Interlaced mode.
+ * Because the member hdmi of vendor data block is extension part,
+ * it's length is flexible, we need to guarantee the boundary
+ * prior to fetching data.
+ */
+
+ if (NULL != blk) {
+ if (VENDOR_OFFSET(struct cea_vendor_blk, hdmi.Support_flags) <=
+ blk->len)
+ eld->S_AI = VENDOR_SUPPORT_AI(blk->u.vendor.hdmi.Support_flags);
+
+ if (VENDOR_OFFSET(struct cea_vendor_blk, hdmi.Audio_Latency) <=
+ blk->len) {
+ if (VENDOR_LATENCY_PRESENT(blk->u.vendor.hdmi.Latency_Present)) {
+ if(blk->u.vendor.hdmi.Audio_Latency)
+ eld->Aud_Synch_Delay = blk->u.vendor.hdmi.Audio_Latency - 1;
+ }
+ }
+ }
+
+ type.body_type = CEA_EXT;
+ type.data_type = CEA_SPEAKER_ALLOC_BLK;
+ blk = (struct cea_data_blk *)xf86DDCGetCEA(output->MonInfo,&type);
+ if (NULL != blk) {
+ eld->FLR = blk->u.speaker.FLR;
+ eld->LFE = blk->u.speaker.LFE;
+ eld->FC = blk->u.speaker.FC;
+ eld->RLR = blk->u.speaker.RLR;
+ eld->RC = blk->u.speaker.RC;
+ eld->FLRC = blk->u.speaker.FLRC;
+ eld->RLRC = blk->u.speaker.RLRC;
+ }
+
+ //eld->Port_ID /*TBD XXX*/
+ eld->Manufacture_Name[0] = output->MonInfo->vendor.name[0];
+ eld->Manufacture_Name[1] = output->MonInfo->vendor.name[1];
+ eld->Product_Code[0] = output->MonInfo->vendor.prod_id & 0xff;
+ eld->Product_Code[1] = output->MonInfo->vendor.prod_id >> 8;
+
+ if (NULL != name) {
+ memcpy(eld->Monitor_Name, name, EDID_DET_NAME_LEN);
+ }
+ if (NULL != audio) {
+ memcpy(eld->Monitor_Name + EDID_DET_NAME_LEN, audio,SAD_Count * 3);
+ }
+
+end:
+ *buf = eld;
+ return eld_len <= CEA_LIKE_DATA_MAX_LEN ? eld_len:CEA_LIKE_DATA_MAX_LEN ;
+}
+
DisplayModePtr
i830_ddc_get_modes (xf86OutputPtr output)
{
--- xf86-video-intel.orig/src/i830_sdvo.c
+++ xf86-video-intel/src/i830_sdvo.c
@@ -36,6 +36,7 @@ USE OR OTHER DEALINGS IN THE SOFTWARE.
* this code doesn't deal with either ganged mode or more than one SDVO output.
*/
+
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
@@ -889,10 +890,13 @@ struct dip_infoframe {
union {
struct {
/* Packet Byte #1 */
- uint8_t S:2;
- uint8_t B:2;
+ uint8_t S0: 1;
+ uint8_t S1:1;
+ uint8_t B0:1;
+ uint8_t B1:1;
uint8_t A:1;
- uint8_t Y:2;
+ uint8_t Y0:1;
+ uint8_t Y1:1;
uint8_t rsvd1:1;
/* Packet Byte #2 */
uint8_t R:4;
@@ -954,6 +958,36 @@ static void i830_sdvo_set_avi_infoframe(
SDVO_HBUF_TX_VSYNC);
}
+static void i830_sdvo_set_edid_like_data(xf86OutputPtr output)
+{
+ Uchar *eld;
+ int eld_len;
+ Uchar av_split;
+ Uchar eld_pre;
+
+ eld = NULL;
+ eld_len = i830_extract_cea_like_data(output, &eld);
+ if (NULL == eld)
+ goto end;
+
+ av_split = 7;
+
+ i830_sdvo_write_cmd(output, SDVO_CMD_SET_HBUF_AV_SPLIT,
+ &av_split, sizeof(Uchar));
+ av_split = 0;
+ i830_sdvo_set_hdmi_buf(output, av_split, eld, eld_len,
+ SDVO_HBUF_TX_DISABLED);
+
+ eld_pre = SDVO_ELD_PRESENT | SDVO_ELD_VALID;
+
+ i830_sdvo_write_cmd(output, SDVO_CMD_SET_AUDIO_STAT,
+ &eld_pre, sizeof(Uchar));
+end:
+ if (NULL != eld)
+ xfree(eld);
+
+}
+
static Bool
i830_sdvo_mode_fixup(xf86OutputPtr output, DisplayModePtr mode,
DisplayModePtr adjusted_mode)
@@ -1025,6 +1059,8 @@ i830_sdvo_mode_set(xf86OutputPtr output,
struct i830_sdvo_dtd input_dtd;
uint8_t status;
+ sdvox = 0;
+
if (!mode)
return;
@@ -1043,6 +1079,7 @@ i830_sdvo_mode_set(xf86OutputPtr output,
if (dev_priv->is_hdmi) {
i830_sdvo_set_avi_infoframe(output, mode);
+ i830_sdvo_set_edid_like_data(output);
sdvox |= SDVO_AUDIO_ENABLE;
}
@@ -1118,7 +1155,7 @@ i830_sdvo_mode_set(xf86OutputPtr output,
} else {
sdvox |= (sdvo_pixel_multiply - 1) << SDVO_PORT_MULTIPLY_SHIFT;
}
-
+ sdvox = sdvox ;
i830_sdvo_write_sdvox(output, sdvox);
}
@@ -1264,6 +1301,7 @@ i830_sdvo_mode_valid(xf86OutputPtr outpu
{
I830OutputPrivatePtr intel_output = output->driver_private;
struct i830_sdvo_priv *dev_priv = intel_output->dev_priv;
+ unsigned long tmds_max_clock = i830_extract_max_tmds_clock(output);
if (pMode->Flags & V_DBLSCAN)
return MODE_NO_DBLESCAN;
@@ -1274,6 +1312,9 @@ i830_sdvo_mode_valid(xf86OutputPtr outpu
if (dev_priv->pixel_clock_max < pMode->Clock)
return MODE_CLOCK_HIGH;
+ if(0 != dev_priv->is_hdmi && 0 < tmds_max_clock && tmds_max_clock < pMode->Clock)
+ return MODE_CLOCK_HIGH;
+
return MODE_OK;
}
--- xf86-video-intel.orig/src/i830_sdvo.h
+++ xf86-video-intel/src/i830_sdvo.h
@@ -24,6 +24,8 @@
* Eric Anholt <[EMAIL PROTECTED]>
*
*/
+#define SDVO_ELD_PRESENT (1 << 0)
+#define SDVO_ELD_VALID (1 << 1)
Bool
i830_sdvo_init(ScrnInfoPtr pScrn, int output_device);
---
hw/xfree86/ddc/edid.h | 101 ++++++++++++++++++++++++-
hw/xfree86/ddc/interpret_edid.c | 102 ++++++++++++++++++++++++-
hw/xfree86/ddc/print_edid.c | 9 +-
hw/xfree86/ddc/xf86DDC.c | 41 +++++++---
hw/xfree86/ddc/xf86DDC.h | 4 +
hw/xfree86/modes/xf86Crtc.c | 2
hw/xfree86/modes/xf86EdidModes.c | 114 +++++++++++++++++++++++++++--
7 files changed, 342 insertions(+), 31 deletions(-)
--- xserver.orig/hw/xfree86/ddc/edid.h
+++ xserver/hw/xfree86/ddc/edid.h
@@ -20,7 +20,7 @@
#define STD_TIMINGS 8
#define DET_TIMINGS 4
-
+#define EDID_DET_NAME_LEN 13
#ifdef _PARSE_EDID_
/* header: 0x00 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0x00 */
@@ -519,9 +519,9 @@ struct detailed_monitor_section {
int type;
union {
struct detailed_timings d_timings; /* 56 */
- Uchar serial[13];
- Uchar ascii_data[13];
- Uchar name[13];
+ Uchar serial[EDID_DET_NAME_LEN];
+ Uchar ascii_data[EDID_DET_NAME_LEN];
+ Uchar name[EDID_DET_NAME_LEN];
struct monitor_ranges ranges; /* 56 */
struct std_timings std_t[5]; /* 80 */
struct whitePoints wp[2]; /* 32 */
@@ -533,6 +533,96 @@ struct detailed_monitor_section {
/* flags */
#define EDID_COMPLETE_RAWDATA 0x1
+#define EDID_CEA_EXTENSION_FLG 0x2
+
+#define CEA_EXT 2
+#define CEA_EXT_MIN_DATA_OFFSET 4
+#define CEA_EXT_MAX_DATA_OFFSET 127
+
+#define IEEE_ID_HDMI 0x000C03
+#define CEA_AUDIO_BLK 1
+#define CEA_VIDEO_BLK 2
+#define CEA_VENDOR_BLK 3
+#define CEA_SPEAKER_ALLOC_BLK 4
+#define CEA_VESA_DTC_BLK 5
+
+#define VENDOR_OFFSET(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
+
+#define VENDOR_SUPPORT_AI(x) (x >> 7)
+#define VENDOR_SUPPORT_DC_48bit(x) ( ( x >> 6) & 0x01)
+#define VENDOR_SUPPORT_DC_36bit(x) ( ( x >> 5) & 0x01)
+#define VENDOR_SUPPORT_DC_30bit(x) ( ( x >> 4) & 0x01)
+#define VENDOR_SUPPORT_DC_Y444(x) ( ( x >> 3) & 0x01)
+#define VENDOR_LATENCY_PRESENT(x) ( ( x >> 7) )
+#define VENDOR_LATENCY_PRESENT_I(x) ( ( x >> 6) & 0x01)
+#define HDMI_MAX_TMDS_UNIT (5000)
+struct cea_video_blk {
+ Uchar video_code; /* point to raw EDID data block */
+}__attribute__ ((packed));
+
+
+struct cea_audio_blk {
+ Uchar descs[3];
+}__attribute__ ((packed));
+struct hdmi {
+ Uchar Support_flags;
+ Uchar Max_TMDS_Clock;
+ Uchar Latency_Present;
+ Uchar Video_Latency;
+ Uchar Audio_Latency;
+ Uchar Interlaced_Video_Latency;
+ Uchar Interlaced_Audio_Latency;
+
+}__attribute__ ((packed));
+struct cea_vendor_blk {
+ unsigned char ieee_id[3];
+ Uchar Port_Addr[2];
+ struct hdmi hdmi;
+}__attribute__ ((packed));
+
+struct cea_speaker_blk
+{
+ Uchar FLR:1;
+ Uchar LFE:1;
+ Uchar FC:1;
+ Uchar RLR:1;
+ Uchar RC:1;
+ Uchar FLRC:1;
+ Uchar RLRC:1;
+ Uchar FLRW:1;
+ Uchar FLRH:1;
+ Uchar TC:1;
+ Uchar FCH:1;
+ Uchar Resv:5;
+ Uchar Resv_Byte;
+}__attribute__ ((packed));
+
+struct cea_data_blk {
+ Uchar len:5;
+ Uchar tag:3;
+union{
+ struct cea_video_blk video;
+ struct cea_audio_blk audio;
+ struct cea_vendor_blk vendor;
+ struct cea_speaker_blk speaker;
+ }u;
+}__attribute__ ((packed));
+struct cea_ext {
+ Uchar tag;
+ Uchar rev;
+ Uchar dt_offset;
+ Uchar flags;
+ struct cea_data_blk data_collection;
+}__attribute__ ((packed));
+struct extension_block {
+ union{
+ struct cea_ext cea;
+ }u;
+}__attribute__ ((packed));
+struct extension_type {
+ int body_type;
+ int data_type;
+}__attribute__ ((packed));
typedef struct {
int scrnIndex;
@@ -541,7 +631,8 @@ typedef struct {
struct disp_features features;
struct established_timings timings1;
struct std_timings timings2[8];
- struct detailed_monitor_section det_mon[4];
+ struct detailed_monitor_section det_mon[10];
+ int det_mon_num;
unsigned long flags;
int no_sections;
Uchar *rawData;
--- xserver.orig/hw/xfree86/ddc/interpret_edid.c
+++ xserver/hw/xfree86/ddc/interpret_edid.c
@@ -42,7 +42,7 @@ static void get_established_timing_secti
static void get_std_timing_section(Uchar*, struct std_timings *,
struct edid_version *);
static void get_dt_md_section(Uchar *, struct edid_version *,
- struct detailed_monitor_section *det_mon);
+ struct detailed_monitor_section *det_mon,int det_mon_num);
static void copy_string(Uchar *, Uchar *);
static void get_dst_timing_section(Uchar *, struct std_timings *,
struct edid_version *);
@@ -64,10 +64,10 @@ handle_edid_quirks(xf86MonPtr m)
* similar. Strictly we should refuse to round up too far, but let's
* see how well this works.
*/
- for (i = 0; i < 4; i++) {
+ for (i = 0; i < m->det_mon_num; i++) {
if (m->det_mon[i].type == DS_RANGES) {
ranges = &m->det_mon[i].section.ranges;
- for (j = 0; j < 4; j++) {
+ for (j = 0; j < m->det_mon_num; j++) {
if (m->det_mon[j].type == DT) {
preferred_timing = &m->det_mon[j].section.d_timings;
if (!ranges->max_clock) continue; /* zero is legal */
@@ -99,7 +99,7 @@ handle_edid_quirks(xf86MonPtr m)
float target_aspect, timing_aspect;
target_aspect = (float)m->features.hsize / (float)m->features.vsize;
- for (i = 0; i < 4; i++) {
+ for (i = 0; i < m->det_mon_num; i++) {
if (m->det_mon[i].type == DT) {
struct detailed_timings *timing;
timing = &m->det_mon[i].section.d_timings;
@@ -132,6 +132,79 @@ handle_edid_quirks(xf86MonPtr m)
}
}
+Uchar * xf86DDCGetCEA(xf86MonPtr MonPtr, struct extension_type *type)
+{
+ struct extension_block *blk;
+ struct cea_ext *cea_blk;
+ struct cea_data_blk *data_collection;
+ Uchar *ret;
+ int data_len ;
+ int data_type;
+ int i;
+
+ ret = NULL;
+ blk = (struct extension_block *) (MonPtr->rawData + EDID1_LEN) ;
+
+ for (i = 0; i < MonPtr->no_sections; i++) {
+
+ if (CEA_EXT == blk ->u.cea.tag) {
+ ret = (Uchar *)&blk->u.cea;
+ if (CEA_EXT == type->body_type && 0 == type->data_type) {
+ goto end;
+ }
+ break;
+ }
+ blk =(struct extension_block *) ((Uchar * )blk + EDID1_LEN);
+ }
+
+ if (NULL == ret)
+ goto end;
+
+ cea_blk = (struct cea_ext *)ret;
+
+ ret = NULL;
+
+ if (CEA_EXT_MIN_DATA_OFFSET >= cea_blk->dt_offset)
+ goto end;
+
+ data_collection = &cea_blk->data_collection ;
+ data_len = 0;
+ while (data_len < cea_blk->dt_offset) {
+ if (type->data_type == data_collection->tag) {
+ ret = (unsigned char *)data_collection;
+ goto end;
+ }
+ data_len = data_len + data_collection->len + 1;
+ data_collection = (unsigned char *)data_collection + data_len ;
+ }
+
+
+end:
+ return ret;
+}
+
+static void get_cea_detail_timing(xf86MonPtr m, Uchar *blk )
+{
+ int dt_offset = ((struct cea_ext *)blk)->dt_offset;
+
+ if (CEA_EXT_MIN_DATA_OFFSET < dt_offset) {
+ goto end;
+ }
+
+ while (dt_offset < (CEA_EXT_MAX_DATA_OFFSET - DET_TIMING_INFO_LEN )) {
+
+ get_dt_md_section(blk + dt_offset, &m->ver,
+ m->det_mon + m->det_mon_num, 1);
+
+ m->det_mon_num = m->det_mon_num + 1 ;
+
+ _NEXT_DT_MD_SECTION(dt_offset);
+ }
+
+end:
+ return;
+}
+
xf86MonPtr
xf86InterpretEDID(int scrnIndex, Uchar *block)
{
@@ -151,9 +224,24 @@ xf86InterpretEDID(int scrnIndex, Uchar *
&m->timings1);
get_std_timing_section(SECTION(STD_TIMING_SECTION,block),m->timings2,
&m->ver);
- get_dt_md_section(SECTION(DET_TIMING_SECTION,block),&m->ver, m->det_mon);
+ get_dt_md_section(SECTION(DET_TIMING_SECTION,block),&m->ver, m->det_mon,4);
+ m->det_mon_num = 4;
m->no_sections = (int)*(char *)SECTION(NO_EDID,block);
+
+ if (0 != m->no_sections) {
+ unsigned char *blk;
+ struct extension_type type;
+
+ type.body_type = CEA_EXT;
+ type.data_type = 0;
+ blk = xf86DDCGetCEA(m, &type) ;
+ if (NULL != blk) {
+ get_cea_detail_timing(m, blk);
+ m->flags = EDID_CEA_EXTENSION_FLG;
+ }
+ }
+
handle_edid_quirks(m);
return (m);
@@ -286,11 +374,11 @@ get_std_timing_section(Uchar *c, struct
static void
get_dt_md_section(Uchar *c, struct edid_version *ver,
- struct detailed_monitor_section *det_mon)
+ struct detailed_monitor_section *det_mon,int det_mon_num)
{
int i;
- for (i=0;i<DET_TIMINGS;i++) {
+ for (i=0;i<det_mon_num;i++) {
if (ver->version == 1 && ver->revision >= 1 && IS_MONITOR_DESC) {
switch (MONITOR_DESC_TYPE) {
--- xserver.orig/hw/xfree86/ddc/print_edid.c
+++ xserver/hw/xfree86/ddc/print_edid.c
@@ -335,11 +335,12 @@ print_detailed_timings(int scrnIndex, st
static void
print_detailed_monitor_section(int scrnIndex,
- struct detailed_monitor_section *m)
+ struct detailed_monitor_section *m,
+ int det_mon_num)
{
int i,j;
- for (i=0;i<DET_TIMINGS;i++) {
+ for (i=0;i<det_mon_num;i++) {
switch (m[i].type) {
case DT:
print_detailed_timings(scrnIndex,&m[i].section.d_timings);
@@ -473,12 +474,12 @@ xf86PrintEDID(xf86MonPtr m)
print_display(m->scrnIndex, &m->features, &m->ver);
print_established_timings(m->scrnIndex, &m->timings1);
print_std_timings(m->scrnIndex, m->timings2);
- print_detailed_monitor_section(m->scrnIndex, m->det_mon);
+ print_detailed_monitor_section(m->scrnIndex, m->det_mon, m->det_mon_num);
print_number_sections(m->scrnIndex, m->no_sections);
/* extension block section stuff */
- xf86DrvMsg(m->scrnIndex, X_INFO, "EDID (in hex):\n");
+ xf86DrvMsg(m->scrnIndex, X_INFO, "EDID (in hex): flags is <%d>\n",m->no_sections);
n = 128;
if (m->flags & EDID_COMPLETE_RAWDATA)
--- xserver.orig/hw/xfree86/ddc/xf86DDC.c
+++ xserver/hw/xfree86/ddc/xf86DDC.c
@@ -213,6 +213,7 @@ xf86DoEEDID(int scrnIndex, I2CBusPtr pBu
unsigned char *EDID_block = NULL;
xf86MonPtr tmp = NULL;
I2CDevPtr dev = NULL;
+ int i,n;
/* Default DDC and DDC2 to enabled. */
Bool noddc = FALSE, noddc2 = FALSE;
OptionInfoPtr options;
@@ -237,21 +238,41 @@ xf86DoEEDID(int scrnIndex, I2CBusPtr pBu
if (!EDID_block)
return NULL;
- if (DDC2Read(dev, 0, EDID_block)) {
- int i, n = EDID_block[0x7e];
-
- if (complete && n) {
- EDID_block = xrealloc(EDID_block, EDID1_LEN * (1+n));
-
- for (i = 0; i < n; i++)
- DDC2Read(dev, i+1, EDID_block + (EDID1_LEN * (1+i)));
+ if(FALSE == DDC2Read(dev, 0, EDID_block)){
+ xfree(EDID_block);
+ return NULL;
+ }
+
+
+ n = EDID_block[0x7e];
+
+ if (complete && n) {
+ int ret;
+
+ EDID_block = xrealloc(EDID_block, EDID1_LEN * (1+n));
+
+ if (!EDID_block)
+ return NULL;
+
+ for (i = 0; i < n; i++){
+ ret = DDC2Read(dev, i+1, EDID_block + (EDID1_LEN * (1+i)));
+ if(FALSE == ret){
+ xfree(EDID_block);
+ return NULL;
+ }
}
tmp = xf86InterpretEEDID(scrnIndex, EDID_block);
- }
- if (tmp && complete)
+ if(NULL == tmp){
+ xfree(EDID_block);
+ return NULL;
+ }
+ }
+
+ if (tmp && complete){
tmp->flags |= EDID_COMPLETE_RAWDATA;
+ }
return tmp;
}
--- xserver.orig/hw/xfree86/ddc/xf86DDC.h
+++ xserver/hw/xfree86/ddc/xf86DDC.h
@@ -44,6 +44,10 @@ extern xf86MonPtr xf86PrintEDID(
extern xf86MonPtr xf86InterpretEDID(
int screenIndex, Uchar *block
);
+extern unsigned char * xf86DDCGetCEA(
+ xf86MonPtr MonPtr,
+ struct extension_type *type
+);
extern xf86MonPtr xf86InterpretEEDID(
int screenIndex, Uchar *block
--- xserver.orig/hw/xfree86/modes/xf86Crtc.c
+++ xserver/hw/xfree86/modes/xf86Crtc.c
@@ -2683,7 +2683,7 @@ xf86OutputSetEDID (xf86OutputPtr output,
if (edid_mon)
{
/* Pull out a phyiscal size from a detailed timing if available. */
- for (i = 0; i < 4; i++) {
+ for (i = 0; i < edid_mon->det_mon_num; i++) {
if (edid_mon->det_mon[i].type == DT &&
edid_mon->det_mon[i].section.d_timings.h_size != 0 &&
edid_mon->det_mon[i].section.d_timings.v_size != 0)
--- xserver.orig/hw/xfree86/modes/xf86EdidModes.c
+++ xserver/hw/xfree86/modes/xf86EdidModes.c
@@ -51,7 +51,7 @@ xf86MonitorSupportsReducedBlanking(xf86M
/* EDID 1.4 explicitly defines RB support */
if (DDC->ver.revision >= 4) {
int i;
- for (i = 0; i < DET_TIMINGS; i++) {
+ for (i = 0; i < DDC->det_mon_num; i++) {
struct detailed_monitor_section *det_mon = &DDC->det_mon[i];
if (det_mon->type == DS_RANGES)
if (det_mon->section.ranges.supported_blanking & CVT_REDUCED)
@@ -498,6 +498,107 @@ DDCModesFromStandardTiming(struct std_ti
return Modes;
}
+#define CEA_VIDEO_MODES_NUM 64
+static const DisplayModeRec CEAVideoModes[CEA_VIDEO_MODES_NUM] = {
+ { MODEPREFIX, 25175, 640, 656, 752, 800, 0, 480, 490, 492, 525, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* VIC 1:[EMAIL PROTECTED] */
+ { MODEPREFIX, 27000, 720, 736, 798, 858, 0, 480, 489, 495, 525, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* VIC 2:[EMAIL PROTECTED] */
+ { MODEPREFIX, 27000, 720, 736, 798, 858, 0, 480, 489, 495, 525, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* VIC 3:[EMAIL PROTECTED] */
+ { MODEPREFIX, 74250, 1280, 1390, 1430, 1650, 0, 720, 725, 730, 750, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* VIC 4: [EMAIL PROTECTED] */
+ { MODEPREFIX, 74250, 1920, 2008, 2052, 2200, 0, 1080, 1084, 1094, 1125, 0, V_PHSYNC | V_PVSYNC | V_INTERLACE, MODESUFFIX }, /* VIC 5:[EMAIL PROTECTED] */
+ { MODEPREFIX, 27000, 1440, 1478, 1602, 1716, 0, 480, 488, 494, 525, 0, V_NHSYNC | V_NVSYNC | V_INTERLACE, MODESUFFIX }, /* VIC 6:[EMAIL PROTECTED] */
+ { MODEPREFIX, 27000, 1440, 1478, 1602, 1716, 0, 480, 488, 494, 525, 0, V_NHSYNC | V_NVSYNC | V_INTERLACE, MODESUFFIX }, /* VIC 7:[EMAIL PROTECTED] */
+ { MODEPREFIX, 27000, 1440, 1478, 1602, 1716, 0, 240, 244, 247, 262, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* VIC 8:[EMAIL PROTECTED] */
+ { MODEPREFIX, 27000, 1440, 1478, 1602, 1716, 0, 240, 244, 247, 262, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* VIC 9:[EMAIL PROTECTED] */
+ { MODEPREFIX, 54000, 2880, 2956, 3204, 3432, 0, 480, 488, 494, 525, 0, V_NHSYNC | V_NVSYNC | V_INTERLACE, MODESUFFIX }, /* VIC 10:[EMAIL PROTECTED] */
+ { MODEPREFIX, 54000, 2880, 2956, 3204, 3432, 0, 480, 488, 494, 525, 0, V_NHSYNC | V_NVSYNC | V_INTERLACE, MODESUFFIX }, /* VIC 11:[EMAIL PROTECTED] */
+ { MODEPREFIX, 54000, 2880, 2956, 3204, 3432, 0, 240, 244, 247, 262, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* VIC 12:[EMAIL PROTECTED] */
+ { MODEPREFIX, 54000, 2880, 2956, 3204, 3432, 0, 240, 244, 247, 262, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* VIC 13:[EMAIL PROTECTED] */
+ { MODEPREFIX, 54000, 1440, 1472, 1596, 1716, 0, 480, 489, 495, 525, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* VIC 14:[EMAIL PROTECTED] */
+ { MODEPREFIX, 54000, 1440, 1472, 1596, 1716, 0, 480, 489, 495, 525, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* VIC 15:[EMAIL PROTECTED] */
+ { MODEPREFIX, 148500, 1920, 2008, 2052, 2200, 0, 1080, 1084, 1089, 1125, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* VIC 16:[EMAIL PROTECTED] */
+ { MODEPREFIX, 27000, 720, 732, 796, 864, 0, 576, 581, 586, 625, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* VIC 17:[EMAIL PROTECTED] */
+ { MODEPREFIX, 27000, 720, 732, 796, 864, 0, 576, 581, 586, 625, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* VIC 18:[EMAIL PROTECTED] */
+ { MODEPREFIX, 74250, 1280, 1720, 1760, 1980, 0, 720, 725, 730, 750, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* VIC 19: [EMAIL PROTECTED] */
+ { MODEPREFIX, 74250, 1920, 2448, 2492, 2640, 0, 1080, 1084, 1094, 1125, 0, V_PHSYNC | V_PVSYNC | V_INTERLACE, MODESUFFIX }, /* VIC 20:[EMAIL PROTECTED] */
+ { MODEPREFIX, 27000, 1440, 1464, 1590, 1728, 0, 576, 580, 586, 625, 0, V_NHSYNC | V_NVSYNC | V_INTERLACE, MODESUFFIX }, /* VIC 21:[EMAIL PROTECTED] */
+ { MODEPREFIX, 27000, 1440, 1464, 1590, 1728, 0, 576, 580, 586, 625, 0, V_NHSYNC | V_NVSYNC | V_INTERLACE, MODESUFFIX }, /* VIC 22:[EMAIL PROTECTED] */
+ { MODEPREFIX, 27000, 1440, 1464, 1590, 1728, 0, 288, 290, 293, 312, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* VIC 23:[EMAIL PROTECTED] */
+ { MODEPREFIX, 27000, 1440, 1464, 1590, 1728, 0, 288, 290, 293, 312, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* VIC 24:[EMAIL PROTECTED] */
+ { MODEPREFIX, 54000, 2880, 2928, 3180, 3456, 0, 576, 580, 586, 625, 0, V_NHSYNC | V_NVSYNC | V_INTERLACE, MODESUFFIX }, /* VIC 25:[EMAIL PROTECTED] */
+ { MODEPREFIX, 54000, 2880, 2928, 3180, 3456, 0, 576, 580, 586, 625, 0, V_NHSYNC | V_NVSYNC | V_INTERLACE, MODESUFFIX }, /* VIC 26:[EMAIL PROTECTED] */
+ { MODEPREFIX, 54000, 2880, 2928, 3180, 3456, 0, 288, 290, 293, 312, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* VIC 27:[EMAIL PROTECTED] */
+ { MODEPREFIX, 54000, 2880, 2928, 3180, 3456, 0, 288, 290, 293, 312, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* VIC 28:[EMAIL PROTECTED] */
+ { MODEPREFIX, 54000, 1440, 1464, 1592, 1728, 0, 576, 581, 586, 625, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* VIC 29:[EMAIL PROTECTED] */
+ { MODEPREFIX, 54000, 1440, 1464, 1592, 1728, 0, 576, 581, 586, 625, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* VIC 30:[EMAIL PROTECTED] */
+ { MODEPREFIX, 148500, 1920, 2448, 2492, 2640, 0, 1080, 1084, 1089, 1125, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* VIC 31:[EMAIL PROTECTED] */
+ { MODEPREFIX, 74250, 1920, 2558, 2602, 2750, 0, 1080, 1084, 1089, 1125, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* VIC 32:[EMAIL PROTECTED] */
+ { MODEPREFIX, 74250, 1920, 2448, 2492, 2640, 0, 1080, 1084, 1089, 1125, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* VIC 33:[EMAIL PROTECTED] */
+ { MODEPREFIX, 74250, 1920, 2008, 2052, 2200, 0, 1080, 1084, 1089, 1125, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* VIC 34:[EMAIL PROTECTED] */
+ { MODEPREFIX, 108000, 2880, 2944, 3192, 3432, 0, 480, 489, 495, 525, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* VIC 35:[EMAIL PROTECTED] */
+ { MODEPREFIX, 108000, 2880, 2944, 3192, 3432, 0, 480, 489, 495, 525, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* VIC 36:[EMAIL PROTECTED] */
+ { MODEPREFIX, 108000, 2880, 2928, 3184, 3456, 0, 576, 581, 586, 625, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* VIC 37:[EMAIL PROTECTED] */
+ { MODEPREFIX, 108000, 2880, 2928, 3184, 3456, 0, 576, 581, 586, 625, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* VIC 38:[EMAIL PROTECTED] */
+ { MODEPREFIX, 72000, 1920, 1952, 2120, 2304, 0, 1080, 1126, 1136, 1250, 0, V_PHSYNC | V_NVSYNC | V_INTERLACE, MODESUFFIX }, /* VIC 39:[EMAIL PROTECTED] */
+ { MODEPREFIX, 148500, 1920, 2448, 2492, 2640, 0, 1080, 1084, 1094, 1125, 0, V_PHSYNC | V_PVSYNC | V_INTERLACE, MODESUFFIX }, /* VIC 40:[EMAIL PROTECTED] */
+ { MODEPREFIX, 148500, 1280, 1720, 1760, 1980, 0, 720, 725, 730, 750, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* VIC 41:[EMAIL PROTECTED] */
+ { MODEPREFIX, 54000, 720, 732, 796, 864, 0, 576, 581, 586, 625, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* VIC 42:[EMAIL PROTECTED] */
+ { MODEPREFIX, 54000, 720, 732, 796, 864, 0, 576, 581, 586, 625, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* VIC 43:[EMAIL PROTECTED] */
+ { MODEPREFIX, 54000, 1440, 1464, 1590, 1728, 0, 576, 580, 586, 625, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* VIC 44:[EMAIL PROTECTED] */
+ { MODEPREFIX, 54000, 1440, 1464, 1590, 1728, 0, 576, 580, 586, 625, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* VIC 45:[EMAIL PROTECTED] */
+ { MODEPREFIX, 148500, 1920, 2008, 2052, 2200, 0, 1080, 1084, 1094, 1125, 0, V_PHSYNC | V_PVSYNC | V_INTERLACE, MODESUFFIX }, /* VIC 46:[EMAIL PROTECTED] */
+ { MODEPREFIX, 148500, 1280, 1390, 1430, 1650, 0, 720, 725, 730, 750, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* VIC 47:[EMAIL PROTECTED] */
+ { MODEPREFIX, 54000, 720, 736, 798, 858, 0, 480, 489, 495, 525, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* VIC 48:[EMAIL PROTECTED] */
+ { MODEPREFIX, 54000, 720, 736, 798, 858, 0, 480, 489, 495, 525, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* VIC 49:[EMAIL PROTECTED] */
+ { MODEPREFIX, 54000, 1440, 1478, 1602, 1716, 0, 480, 488, 494, 525, 0, V_NHSYNC | V_NVSYNC | V_INTERLACE, MODESUFFIX },/* VIC 50:[EMAIL PROTECTED] */
+ { MODEPREFIX, 54000, 1440, 1478, 1602, 1716, 0, 480, 488, 494, 525, 0, V_NHSYNC | V_NVSYNC | V_INTERLACE, MODESUFFIX },/* VIC 51:[EMAIL PROTECTED] */
+ { MODEPREFIX, 108000, 720, 732, 796, 864, 0, 576, 581, 586, 625, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* VIC 52:[EMAIL PROTECTED] */
+ { MODEPREFIX, 108000, 720, 732, 796, 864, 0, 576, 581, 586, 625, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* VIC 53:[EMAIL PROTECTED] */
+ { MODEPREFIX, 108000, 1440, 1464, 1590, 1728, 0, 576, 580, 586, 625, 0, V_NHSYNC | V_NVSYNC | V_INTERLACE, MODESUFFIX },/* VIC 54:[EMAIL PROTECTED] */
+ { MODEPREFIX, 108000, 1440, 1464, 1590, 1728, 0, 576, 580, 586, 625, 0, V_NHSYNC | V_NVSYNC | V_INTERLACE, MODESUFFIX },/* VIC 55:[EMAIL PROTECTED] */
+ { MODEPREFIX, 108000, 720, 736, 798, 858, 0, 480, 489, 495, 525, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* VIC 56:[EMAIL PROTECTED] */
+ { MODEPREFIX, 108000, 720, 736, 798, 858, 0, 480, 489, 495, 525, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* VIC 57:[EMAIL PROTECTED] */
+ { MODEPREFIX, 108000, 1440, 1478, 1602, 1716, 0, 480, 488, 494, 525, 0, V_NHSYNC | V_NVSYNC | V_INTERLACE, MODESUFFIX },/* VIC 58:[EMAIL PROTECTED] */
+ { MODEPREFIX, 108000, 1440, 1478, 1602, 1716, 0, 480, 488, 494, 525, 0, V_NHSYNC | V_NVSYNC | V_INTERLACE, MODESUFFIX },/* VIC 59:[EMAIL PROTECTED] */
+ { MODEPREFIX, 59400, 1280, 3040, 3080, 3300, 0, 720, 725, 730, 750, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* VIC 60: [EMAIL PROTECTED] */
+ { MODEPREFIX, 74250, 3700, 3740, 1430, 3960, 0, 720, 725, 730, 750, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* VIC 61: [EMAIL PROTECTED] */
+ { MODEPREFIX, 74250, 1280, 3040, 3080, 3300, 0, 720, 725, 730, 750, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* VIC 62: [EMAIL PROTECTED] */
+ { MODEPREFIX, 297000, 1920, 2008, 2052, 2200, 0, 1080, 1084, 1089, 1125, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* VIC 63: [EMAIL PROTECTED] */
+ { MODEPREFIX, 297000, 1920, 2448, 2492, 2640, 0, 1080, 1084, 1094, 1125, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* VIC 64:[EMAIL PROTECTED] */
+};
+
+static DisplayModePtr
+DDCModesFromCeaExtension(int idx, xf86MonPtr MonPtr)
+{
+ DisplayModePtr Modes = NULL, Mode = NULL;
+ struct extension_type type;
+ struct cea_data_blk *data_collection;
+ struct cea_video_blk *video;
+ int num ;
+ int vid;
+
+ type.body_type = CEA_EXT ;
+ type.data_type = CEA_VIDEO_BLK;
+
+ data_collection = (struct cea_data_blk *)xf86DDCGetCEA(MonPtr, &type);
+ if (NULL == data_collection)
+ goto end;
+
+ video = &data_collection->u.video;
+ num = 0;
+
+ while (num < (data_collection->len/sizeof(struct cea_video_blk))) {
+ vid = video[num].video_code & 0x7f;
+
+ if(vid < CEA_VIDEO_MODES_NUM){
+ Mode = xf86DuplicateMode(CEAVideoModes + vid );
+ Modes = xf86ModesAdd(Modes, Mode);
+ }
+ num = num + 1;
+ }
+
+end:
+ return Modes;
+}
/*
*
@@ -699,7 +800,7 @@ xf86DDCApplyQuirks(int scrnIndex, xf86Mo
ddc_quirk_t quirks = xf86DDCDetectQuirks (scrnIndex, DDC, FALSE);
int i;
- for (i = 0; i < DET_TIMINGS; i++) {
+ for (i = 0; i < DDC->det_mon_num; i++) {
struct detailed_monitor_section *det_mon = &DDC->det_mon[i];
if (det_mon->type != DT)
@@ -785,7 +886,7 @@ xf86DDCGetModes(int scrnIndex, xf86MonPt
timing_level = MonitorStandardTimingLevel(DDC);
- for (i = 0; i < DET_TIMINGS; i++) {
+ for (i = 0; i < DDC->det_mon_num; i++) {
struct detailed_monitor_section *det_mon = &DDC->det_mon[i];
switch (det_mon->type) {
@@ -821,6 +922,11 @@ xf86DDCGetModes(int scrnIndex, xf86MonPt
Mode = DDCModesFromStandardTiming(DDC->timings2, quirks, timing_level, rb);
Modes = xf86ModesAdd(Modes, Mode);
+ if(EDID_CEA_EXTENSION_FLG & DDC->flags){
+ Mode = DDCModesFromCeaExtension(scrnIndex,DDC);
+ Modes = xf86ModesAdd(Modes, Mode);
+ }
+
if (quirks & DDC_QUIRK_PREFER_LARGE_60)
xf86DDCSetPreferredRefresh(scrnIndex, Modes, 60);
@@ -863,7 +969,7 @@ xf86DDCMonitorSet(int scrnIndex, MonPtr
have_maxpixclock = (Monitor->maxPixClock != 0);
/* Go through the detailed monitor sections */
- for (i = 0; i < DET_TIMINGS; i++) {
+ for (i = 0; i < DDC->det_mon_num; i++) {
switch (DDC->det_mon[i].type) {
case DS_RANGES:
if (!have_hsync) {
_______________________________________________
xorg mailing list
[email protected]
http://lists.freedesktop.org/mailman/listinfo/xorg