> Also fix an embarassing bug in standard timing subblock parsing that > would result in an infinite loop.
Thanks, all applied to drm-core-next. Dave. > > Signed-off-by: Adam Jackson <a...@redhat.com> > --- > drivers/gpu/drm/drm_edid.c | 163 ++++++++++++++++--------------------------- > 1 files changed, 61 insertions(+), 102 deletions(-) > > diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c > index bdea313..999571a 100644 > --- a/drivers/gpu/drm/drm_edid.c > +++ b/drivers/gpu/drm/drm_edid.c > @@ -838,8 +838,57 @@ static int add_standard_modes(struct drm_connector > *connector, struct edid *edid > 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); > + struct drm_display_mode *newmode; > + struct drm_device *dev = connector->dev; > + > + if (timing->pixel_clock) { > + newmode = drm_mode_detailed(dev, edid, timing, quirks); > + if (!newmode) > + return 0; > + > + if (preferred) > + newmode->type |= DRM_MODE_TYPE_PREFERRED; > + > + drm_mode_probed_add(connector, newmode); > + return 1; > + } > + > + /* other timing types */ > + switch (data->type) { > + case EDID_DETAIL_MONITOR_RANGE: > + /* Get monitor range data */ > + break; > + case EDID_DETAIL_STD_MODES: > + /* Six modes per detailed section */ > + for (i = 0; i < 6; i++) { > + struct std_timing *std; > + struct drm_display_mode *newmode; > + > + std = &data->data.timings[i]; > + newmode = drm_mode_std(dev, std, edid->revision, > + timing_level); > + if (newmode) { > + drm_mode_probed_add(connector, newmode); > + modes++; > + } > + } > + break; > + default: > + break; > + } > + > + return modes; > +} > + > /** > - * add_detailed_modes - get detailed mode info from EDID data > + * add_detailed_info - get detailed mode info from EDID data > * @connector: attached connector > * @edid: EDID block to scan > * @quirks: quirks to apply > @@ -850,67 +899,24 @@ static int add_standard_modes(struct drm_connector > *connector, struct edid *edid > static int add_detailed_info(struct drm_connector *connector, > struct edid *edid, u32 quirks) > { > - struct drm_device *dev = connector->dev; > - int i, j, modes = 0; > - int timing_level; > - > - timing_level = standard_timing_level(edid); > + int i, modes = 0; > > for (i = 0; i < EDID_DETAILED_TIMINGS; i++) { > struct detailed_timing *timing = &edid->detailed_timings[i]; > - struct detailed_non_pixel *data = &timing->data.other_data; > - struct drm_display_mode *newmode; > - > - /* X server check is version 1.1 or higher */ > - if (edid->version == 1 && edid->revision >= 1 && > - !timing->pixel_clock) { > - /* Other timing or info */ > - switch (data->type) { > - case EDID_DETAIL_MONITOR_SERIAL: > - break; > - case EDID_DETAIL_MONITOR_STRING: > - break; > - case EDID_DETAIL_MONITOR_RANGE: > - /* Get monitor range data */ > - break; > - case EDID_DETAIL_MONITOR_NAME: > - break; > - case EDID_DETAIL_MONITOR_CPDATA: > - break; > - case EDID_DETAIL_STD_MODES: > - for (j = 0; j < 6; i++) { > - struct std_timing *std; > - struct drm_display_mode *newmode; > - > - std = &data->data.timings[j]; > - newmode = drm_mode_std(dev, std, > - edid->revision, > - timing_level); > - if (newmode) { > - drm_mode_probed_add(connector, > newmode); > - modes++; > - } > - } > - break; > - default: > - break; > - } > - } else { > - newmode = drm_mode_detailed(dev, edid, timing, quirks); > - if (!newmode) > - continue; > + int preferred = (i == 0) && (edid->features & > DRM_EDID_FEATURE_PREFERRED_TIMING); > > - /* First detailed mode is preferred */ > - if (i == 0 && (edid->features & > DRM_EDID_FEATURE_PREFERRED_TIMING)) > - newmode->type |= DRM_MODE_TYPE_PREFERRED; > - drm_mode_probed_add(connector, newmode); > + /* In 1.0, only timings are allowed */ > + if (!timing->pixel_clock && edid->version == 1 && > + edid->revision == 0) > + continue; > > - modes++; > - } > + modes += add_detailed_modes(connector, timing, edid, quirks, > + preferred); > } > > return modes; > } > + > /** > * add_detailed_mode_eedid - get detailed mode info from addtional timing > * EDID block > @@ -924,12 +930,9 @@ static int add_detailed_info(struct drm_connector > *connector, > static int add_detailed_info_eedid(struct drm_connector *connector, > struct edid *edid, u32 quirks) > { > - struct drm_device *dev = connector->dev; > - int i, j, modes = 0; > + int i, modes = 0; > char *edid_ext = NULL; > struct detailed_timing *timing; > - struct detailed_non_pixel *data; > - struct drm_display_mode *newmode; > int edid_ext_num; > int start_offset, end_offset; > int timing_level; > @@ -980,51 +983,7 @@ static int add_detailed_info_eedid(struct drm_connector > *connector, > for (i = start_offset; i < end_offset; > i += sizeof(struct detailed_timing)) { > timing = (struct detailed_timing *)(edid_ext + i); > - data = &timing->data.other_data; > - /* Detailed mode timing */ > - if (timing->pixel_clock) { > - newmode = drm_mode_detailed(dev, edid, timing, quirks); > - if (!newmode) > - continue; > - > - drm_mode_probed_add(connector, newmode); > - > - modes++; > - continue; > - } > - > - /* Other timing or info */ > - switch (data->type) { > - case EDID_DETAIL_MONITOR_SERIAL: > - break; > - case EDID_DETAIL_MONITOR_STRING: > - break; > - case EDID_DETAIL_MONITOR_RANGE: > - /* Get monitor range data */ > - break; > - case EDID_DETAIL_MONITOR_NAME: > - break; > - case EDID_DETAIL_MONITOR_CPDATA: > - break; > - case EDID_DETAIL_STD_MODES: > - /* Five modes per detailed section */ > - for (j = 0; j < 5; i++) { > - struct std_timing *std; > - struct drm_display_mode *newmode; > - > - std = &data->data.timings[j]; > - newmode = drm_mode_std(dev, std, > - edid->revision, > - timing_level); > - if (newmode) { > - drm_mode_probed_add(connector, newmode); > - modes++; > - } > - } > - break; > - default: > - break; > - } > + modes += add_detailed_modes(connector, timing, edid, quirks, 0); > } > > return modes; > ------------------------------------------------------------------------------ Join us December 9, 2009 for the Red Hat Virtual Experience, a free event focused on virtualization and cloud computing. Attend in-depth sessions from your desk. Your couch. Anywhere. http://p.sf.net/sfu/redhat-sfdev2dev -- _______________________________________________ Dri-devel mailing list Dri-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/dri-devel