Merge remote-tracking branch 'dlespiau/20131216-4k'
This commit is contained in:
		
						commit
						409e8e29fb
					
				| 
						 | 
					@ -332,6 +332,97 @@ xf86ForEachVideoBlock(xf86MonPtr mon, handle_video_fn fn, void *data)
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static Bool
 | 
				
			||||||
 | 
					cea_db_offsets(Uchar *cea, int *start, int *end)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    /* Data block offset in CEA extension block */
 | 
				
			||||||
 | 
					    *start = CEA_EXT_MIN_DATA_OFFSET;
 | 
				
			||||||
 | 
					    *end = cea[2];
 | 
				
			||||||
 | 
					    if (*end == 0)
 | 
				
			||||||
 | 
					        *end = CEA_EXT_MAX_DATA_OFFSET;
 | 
				
			||||||
 | 
					    if (*end < CEA_EXT_MIN_DATA_OFFSET || *end > CEA_EXT_MAX_DATA_OFFSET)
 | 
				
			||||||
 | 
					        return FALSE;
 | 
				
			||||||
 | 
					    return TRUE;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int
 | 
				
			||||||
 | 
					cea_db_len(Uchar *db)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    return db[0] & 0x1f;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int
 | 
				
			||||||
 | 
					cea_db_tag(Uchar *db)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    return db[0] >> 5;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					typedef void (*handle_cea_db_fn) (Uchar *, void *);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void
 | 
				
			||||||
 | 
					cea_for_each_db(xf86MonPtr mon, handle_cea_db_fn fn, void *data)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    int i;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (!mon)
 | 
				
			||||||
 | 
					        return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (!(mon->flags & EDID_COMPLETE_RAWDATA))
 | 
				
			||||||
 | 
					        return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (!mon->no_sections)
 | 
				
			||||||
 | 
					        return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (!mon->rawData)
 | 
				
			||||||
 | 
					        return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    for (i = 0; i < mon->no_sections; i++) {
 | 
				
			||||||
 | 
					        int start, end, offset;
 | 
				
			||||||
 | 
					        Uchar *ext;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        ext = mon->rawData + EDID1_LEN * (i + 1);
 | 
				
			||||||
 | 
					        if (ext[EXT_TAG] != CEA_EXT)
 | 
				
			||||||
 | 
					            continue;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (!cea_db_offsets(ext, &start, &end))
 | 
				
			||||||
 | 
					            continue;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        for (offset = start;
 | 
				
			||||||
 | 
					             offset < end && offset + cea_db_len(&ext[offset]) < end;
 | 
				
			||||||
 | 
					             offset += cea_db_len(&ext[offset]) + 1)
 | 
				
			||||||
 | 
					                fn(&ext[offset], data);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct find_hdmi_block_data {
 | 
				
			||||||
 | 
					    struct cea_data_block *hdmi;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void find_hdmi_block(Uchar *db, void *data)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    struct find_hdmi_block_data *result = data;
 | 
				
			||||||
 | 
					    int oui;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (cea_db_tag(db) != CEA_VENDOR_BLK)
 | 
				
			||||||
 | 
					        return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (cea_db_len(db) < 5)
 | 
				
			||||||
 | 
					        return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    oui = (db[3] << 16) | (db[2] << 8) | db[1];
 | 
				
			||||||
 | 
					    if (oui == IEEE_ID_HDMI)
 | 
				
			||||||
 | 
					        result->hdmi = (struct cea_data_block *)db;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct cea_data_block *xf86MonitorFindHDMIBlock(xf86MonPtr mon)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    struct find_hdmi_block_data result = { NULL };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    cea_for_each_db(mon, find_hdmi_block, &result);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return result.hdmi;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
xf86MonPtr
 | 
					xf86MonPtr
 | 
				
			||||||
xf86InterpretEEDID(int scrnIndex, Uchar * block)
 | 
					xf86InterpretEEDID(int scrnIndex, Uchar * block)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
| 
						 | 
					@ -666,49 +757,5 @@ validate_version(int scrnIndex, struct edid_version *r)
 | 
				
			||||||
Bool
 | 
					Bool
 | 
				
			||||||
xf86MonitorIsHDMI(xf86MonPtr mon)
 | 
					xf86MonitorIsHDMI(xf86MonPtr mon)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    int i = 0, version, offset;
 | 
					    return xf86MonitorFindHDMIBlock(mon) != NULL;
 | 
				
			||||||
    char *edid = NULL;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    if (!mon)
 | 
					 | 
				
			||||||
        return FALSE;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    if (!(mon->flags & EDID_COMPLETE_RAWDATA))
 | 
					 | 
				
			||||||
        return FALSE;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    if (!mon->no_sections)
 | 
					 | 
				
			||||||
        return FALSE;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    edid = (char *) mon->rawData;
 | 
					 | 
				
			||||||
    if (!edid)
 | 
					 | 
				
			||||||
        return FALSE;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    /* find the CEA extension block */
 | 
					 | 
				
			||||||
    for (i = 1; i <= mon->no_sections; i++)
 | 
					 | 
				
			||||||
        if (edid[i * 128] == 0x02)
 | 
					 | 
				
			||||||
            break;
 | 
					 | 
				
			||||||
    if (i == mon->no_sections + 1)
 | 
					 | 
				
			||||||
        return FALSE;
 | 
					 | 
				
			||||||
    edid += (i * 128);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    version = edid[1];
 | 
					 | 
				
			||||||
    offset = edid[2];
 | 
					 | 
				
			||||||
    if (version < 3 || offset < 4)
 | 
					 | 
				
			||||||
        return FALSE;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    /* walk the cea data blocks */
 | 
					 | 
				
			||||||
    for (i = 4; i < offset; i += (edid[i] & 0x1f) + 1) {
 | 
					 | 
				
			||||||
        char *x = edid + i;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        /* find a vendor specific block */
 | 
					 | 
				
			||||||
        if ((x[0] & 0xe0) >> 5 == 0x03) {
 | 
					 | 
				
			||||||
            int oui = (x[3] << 16) + (x[2] << 8) + x[1];
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            /* find the HDMI vendor OUI */
 | 
					 | 
				
			||||||
            if (oui == 0x000c03)
 | 
					 | 
				
			||||||
                return TRUE;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    /* guess it's not HDMI after all */
 | 
					 | 
				
			||||||
    return FALSE;
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -98,4 +98,6 @@ typedef void (*handle_video_fn) (struct cea_video_block *, void *);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void xf86ForEachVideoBlock(xf86MonPtr, handle_video_fn, void *);
 | 
					void xf86ForEachVideoBlock(xf86MonPtr, handle_video_fn, void *);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct cea_data_block *xf86MonitorFindHDMIBlock(xf86MonPtr mon);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1673,6 +1673,7 @@ xf86ProbeOutputModes(ScrnInfoPtr scrn, int maxX, int maxY)
 | 
				
			||||||
        if (edid_monitor) {
 | 
					        if (edid_monitor) {
 | 
				
			||||||
            struct det_monrec_parameter p;
 | 
					            struct det_monrec_parameter p;
 | 
				
			||||||
            struct disp_features *features = &edid_monitor->features;
 | 
					            struct disp_features *features = &edid_monitor->features;
 | 
				
			||||||
 | 
					            struct cea_data_block *hdmi_db;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            /* if display is not continuous-frequency, don't add default modes */
 | 
					            /* if display is not continuous-frequency, don't add default modes */
 | 
				
			||||||
            if (!GTF_SUPPORTED(features->msc))
 | 
					            if (!GTF_SUPPORTED(features->msc))
 | 
				
			||||||
| 
						 | 
					@ -1685,6 +1686,16 @@ xf86ProbeOutputModes(ScrnInfoPtr scrn, int maxX, int maxY)
 | 
				
			||||||
            p.sync_source = &sync_source;
 | 
					            p.sync_source = &sync_source;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            xf86ForEachDetailedBlock(edid_monitor, handle_detailed_monrec, &p);
 | 
					            xf86ForEachDetailedBlock(edid_monitor, handle_detailed_monrec, &p);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            /* Look at the CEA HDMI vendor block for the max TMDS freq */
 | 
				
			||||||
 | 
					            hdmi_db = xf86MonitorFindHDMIBlock(edid_monitor);
 | 
				
			||||||
 | 
					            if (hdmi_db && hdmi_db->len >= 7) {
 | 
				
			||||||
 | 
					                int tmds_freq = hdmi_db->u.vendor.hdmi.max_tmds_clock * 5000;
 | 
				
			||||||
 | 
					                xf86DrvMsg(scrn->scrnIndex, X_PROBED,
 | 
				
			||||||
 | 
					                           "HDMI max TMDS frequency %dKHz\n", tmds_freq);
 | 
				
			||||||
 | 
					                if (tmds_freq > max_clock)
 | 
				
			||||||
 | 
					                    max_clock = tmds_freq;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (xf86GetOptValFreq(output->options, OPTION_MIN_CLOCK,
 | 
					        if (xf86GetOptValFreq(output->options, OPTION_MIN_CLOCK,
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue