> 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

Reply via email to