This cherry-picked upstream patch removes an infinite
Surbhi Palande
surbhi.palande at canonical.com
Fri Feb 12 10:34:33 UTC 2010
Hi,
Apologies for sending this patch 3 times. There was some problem with
my smtp settings :( Sorry !
Warm Regards,
Surbhi.
Surbhi Palande wrote:
> From 2f8055156e9160f3d83e56122c90c3ece2e09819 Mon Sep 17 00:00:00 2001
> From: Adam Jackson <ajax at redhat.com>
> Date: Thu, 3 Dec 2009 17:44:36 -0500
> Subject: [PATCH] [PATCH] UBUNTU [Lucid]: [Upstream] drm/edid: Unify detailed block parsing between base and extension blocks
>
> BugLink: http://bugs.launchpad.net/bugs/500999
>
> Also fix an embarassing bug in standard timing subblock parsing that
> would result in an infinite loop.
>
> Signed-off-by: Adam Jackson <ajax at redhat.com>
> Signed-off-by: Dave Airlie <airlied at redhat.com>
> (cherry picked from commit 9cf00977da092096c7a983276dad8b3002d23a99)
>
> Signed-off-by: Surbhi Palande <Surbhi.Palande at canonical.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 b54ba63..d5671c3 100644
> --- a/drivers/gpu/drm/drm_edid.c
> +++ b/drivers/gpu/drm/drm_edid.c
> @@ -834,8 +834,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
> @@ -846,67 +895,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
> @@ -920,12 +926,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;
> @@ -976,51 +979,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;
More information about the kernel-team
mailing list