Skip to content

Commit

Permalink
drm/edid: Add DMT modes to the pool if the monitor is GTF-capable
Browse files Browse the repository at this point in the history
See also: http://bugzilla.redhat.com/539785

Signed-off-by: Adam Jackson <ajax@redhat.com>
Signed-off-by: Dave Airlie <airlied@redhat.com>
  • Loading branch information
Adam Jackson authored and Dave Airlie committed Dec 3, 2009
1 parent 7ac96a9 commit 07a5e63
Showing 1 changed file with 65 additions and 4 deletions.
69 changes: 65 additions & 4 deletions drivers/gpu/drm/drm_edid.c
Original file line number Diff line number Diff line change
Expand Up @@ -491,16 +491,17 @@ static struct drm_display_mode drm_dmt_modes[] = {
3048, 3536, 0, 1600, 1603, 1609, 1682, 0,
DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) },
};
static const int drm_num_dmt_modes =
sizeof(drm_dmt_modes) / sizeof(struct drm_display_mode);

static struct drm_display_mode *drm_find_dmt(struct drm_device *dev,
int hsize, int vsize, int fresh)
{
int i, count;
int i;
struct drm_display_mode *ptr, *mode;

count = sizeof(drm_dmt_modes) / sizeof(struct drm_display_mode);
mode = NULL;
for (i = 0; i < count; i++) {
for (i = 0; i < drm_num_dmt_modes; i++) {
ptr = &drm_dmt_modes[i];
if (hsize == ptr->hdisplay &&
vsize == ptr->vdisplay &&
Expand Down Expand Up @@ -838,13 +839,72 @@ static int add_standard_modes(struct drm_connector *connector, struct edid *edid
return modes;
}

/*
* XXX fix this for:
* - GTF secondary curve formula
* - EDID 1.4 range offsets
* - CVT extended bits
*/
static bool
mode_in_range(struct drm_display_mode *mode, struct detailed_timing *timing)
{
struct detailed_data_monitor_range *range;
int hsync, vrefresh;

range = &timing->data.other_data.data.range;

hsync = drm_mode_hsync(mode);
vrefresh = drm_mode_vrefresh(mode);

if (hsync < range->min_hfreq_khz || hsync > range->max_hfreq_khz)
return false;

if (vrefresh < range->min_vfreq || vrefresh > range->max_vfreq)
return false;

if (range->pixel_clock_mhz && range->pixel_clock_mhz != 0xff) {
/* be forgiving since it's in units of 10MHz */
int max_clock = range->pixel_clock_mhz * 10 + 9;
max_clock *= 1000;
if (mode->clock > max_clock)
return false;
}

return true;
}

/*
* XXX If drm_dmt_modes ever regrows the CVT-R modes (and it will) this will
* need to account for them.
*/
static int drm_gtf_modes_for_range(struct drm_connector *connector,
struct detailed_timing *timing)
{
int i, modes = 0;
struct drm_display_mode *newmode;
struct drm_device *dev = connector->dev;

for (i = 0; i < drm_num_dmt_modes; i++) {
if (mode_in_range(drm_dmt_modes + i, timing)) {
newmode = drm_mode_duplicate(dev, &drm_dmt_modes[i]);
if (newmode) {
drm_mode_probed_add(connector, newmode);
modes++;
}
}
}

return modes;
}

static int add_detailed_modes(struct drm_connector *connector,
struct detailed_timing *timing,
struct edid *edid, u32 quirks, int preferred)
{
int i, modes = 0;
struct detailed_non_pixel *data = &timing->data.other_data;
int timing_level = standard_timing_level(edid);
int gtf = (edid->features & DRM_EDID_FEATURE_DEFAULT_GTF);
struct drm_display_mode *newmode;
struct drm_device *dev = connector->dev;

Expand All @@ -863,7 +923,8 @@ static int add_detailed_modes(struct drm_connector *connector,
/* other timing types */
switch (data->type) {
case EDID_DETAIL_MONITOR_RANGE:
/* Get monitor range data */
if (gtf)
modes += drm_gtf_modes_for_range(connector, timing);
break;
case EDID_DETAIL_STD_MODES:
/* Six modes per detailed section */
Expand Down

0 comments on commit 07a5e63

Please sign in to comment.