From patchwork Wed Jul 22 08:56:45 2009 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Zhao, Yakui" X-Patchwork-Id: 36729 Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) by demeter.kernel.org (8.14.2/8.14.2) with ESMTP id n6M8tc6o012179 for ; Wed, 22 Jul 2009 08:55:38 GMT Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 1116C9F380; Wed, 22 Jul 2009 01:55:38 -0700 (PDT) X-Original-To: intel-gfx@lists.freedesktop.org Delivered-To: intel-gfx@lists.freedesktop.org Received: from mga01.intel.com (mga01.intel.com [192.55.52.88]) by gabe.freedesktop.org (Postfix) with ESMTP id E907B9F377 for ; Wed, 22 Jul 2009 01:55:35 -0700 (PDT) Received: from fmsmga002.fm.intel.com ([10.253.24.26]) by fmsmga101.fm.intel.com with ESMTP; 22 Jul 2009 01:54:47 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="4.43,245,1246863600"; d="scan'208";a="476975585" Received: from yakui_zhao.sh.intel.com (HELO localhost.localdomain) ([10.239.13.79]) by fmsmga002.fm.intel.com with ESMTP; 22 Jul 2009 01:48:48 -0700 From: yakui.zhao@intel.com To: airlied@redhat.com Date: Wed, 22 Jul 2009 16:56:45 +0800 Message-Id: <1248253005-10337-3-git-send-email-yakui.zhao@intel.com> X-Mailer: git-send-email 1.5.4.5 In-Reply-To: <1248253005-10337-2-git-send-email-yakui.zhao@intel.com> References: <1248253005-10337-1-git-send-email-yakui.zhao@intel.com> <1248253005-10337-2-git-send-email-yakui.zhao@intel.com> Cc: intel-gfx@lists.freedesktop.org, dri-devel@sourceforege.net Subject: [Intel-gfx] [PATCH 3/3] DRM: Get the modeline for standard timing in EDID by using CVT/GTF X-BeenThere: intel-gfx@lists.freedesktop.org X-Mailman-Version: 2.1.9 Precedence: list List-Id: Intel graphics driver community testing & development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: intel-gfx-bounces@lists.freedesktop.org Errors-To: intel-gfx-bounces@lists.freedesktop.org From: Zhao Yakui Create the standard timing modeline by using CVT/GFT algorithm while interpreting the EDID. In course of interpreting the EDID, the timing level will be obtained, which is used to determine whether the CVT/GTF algorithm is selected to generate the modeline for the given hdisplay/vdisplay/vfresh_rate. In the UMS mode firstly it will check whether it can be found in the DMT table. If it can be found, then the modeline is returned. Then the timing_level is used to choose CVT/GTF. As there is no DMT table, no modeline is returned when timing level is DMT. For the other two timing levels, the CVT/GTF will be called to generate the required standard timing modeline. Signed-off-by: Zhao Yakui --- drivers/gpu/drm/drm_edid.c | 71 ++++++++++++++++++++++++++++++++++++++----- 1 files changed, 62 insertions(+), 9 deletions(-) diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c index 80cc6d0..917ed65 100644 --- a/drivers/gpu/drm/drm_edid.c +++ b/drivers/gpu/drm/drm_edid.c @@ -61,6 +61,10 @@ /* use +hsync +vsync for detailed mode */ #define EDID_QUIRK_DETAILED_SYNC_PP (1 << 6) +#define LEVEL_DMT 0 +#define LEVEL_GTF 1 +#define LEVEL_CVT 2 + static struct edid_quirk { char *vendor; int product_id; @@ -240,24 +244,29 @@ static void edid_fixup_preferred(struct drm_connector *connector, /** * drm_mode_std - convert standard mode info (width, height, refresh) into mode * @t: standard timing params + * @timing_level: standard timing level(CVT/GTF/DMT) * * Take the standard timing params (in this case width, aspect, and refresh) - * and convert them into a real mode using CVT. + * and convert them into a real mode using CVT/GTF/DMT. * * Punts for now, but should eventually use the FB layer's CVT based mode * generation code. */ struct drm_display_mode *drm_mode_std(struct drm_device *dev, - struct std_timing *t) + struct std_timing *t, + int timing_level) { struct drm_display_mode *mode; - int hsize = t->hsize * 8 + 248, vsize; + int hsize, vsize; + int vfresh_rate; unsigned aspect_ratio = (t->vfreq_aspect & EDID_TIMING_ASPECT_MASK) >> EDID_TIMING_ASPECT_SHIFT; - mode = drm_mode_create(dev); - if (!mode) - return NULL; + /* According to the EDID spec, the hdisplay = hsize * 8 + 248 */ + hsize = t->hsize * 8 + 248; + /* vfresh_rate = t->vfreq_aspect + 60 */ + vfresh_rate = t->vfreq_aspect & EDID_TIMING_VFREQ_MASK; + vfresh_rate += 60; if (aspect_ratio == 0) vsize = (hsize * 10) / 16; @@ -268,7 +277,29 @@ struct drm_display_mode *drm_mode_std(struct drm_device *dev, else vsize = (hsize * 9) / 16; - drm_mode_set_name(mode); + /* Any of hsize/vsize/vfresh_rate is zero, return NULL */ + if (!hsize || !vsize || !vfresh_rate) + return NULL; + /* + * Should we check whether the given mode can be found in + * the default standard mode. If so, please add the default + * standard mode table and return the required modelines + */ + mode = NULL; + switch (timing_level) { + case LEVEL_DMT: + /* When the timing level is DMT, return NULL */ + /* If it is incorrect, please fix me */ + break; + case LEVEL_GTF: + mode = drm_gtf_mode(dev, hsize, vsize, vfresh_rate, + 0, 0); + break; + case LEVEL_CVT: + mode = drm_cvt_mode(dev, hsize, vsize, vfresh_rate, + 0, 0); + break; + } return mode; } @@ -453,6 +484,21 @@ static int add_established_modes(struct drm_connector *connector, struct edid *e } /** + * stanard_timing_level - get std. timing level(CVT/GTF/DMT) + * @edid: EDID block to scan + */ +static int standard_timing_level(struct edid *edid) +{ + if (edid->revision >= 2) { + if (edid->revision >= 4 && + (edid->features & DRM_EDID_FEATURE_DEFAULT_GTF)) + return LEVEL_CVT; + return LEVEL_GTF; + } + return LEVEL_DMT; +} + +/** * add_standard_modes - get std. modes from EDID and add them * @edid: EDID block to scan * @@ -463,6 +509,9 @@ static int add_standard_modes(struct drm_connector *connector, struct edid *edid { struct drm_device *dev = connector->dev; int i, modes = 0; + int timing_level; + + timing_level = standard_timing_level(edid); for (i = 0; i < EDID_STD_TIMINGS; i++) { struct std_timing *t = &edid->standard_timings[i]; @@ -472,7 +521,8 @@ static int add_standard_modes(struct drm_connector *connector, struct edid *edid if (t->hsize == 1 && t->vfreq_aspect == 1) continue; - newmode = drm_mode_std(dev, &edid->standard_timings[i]); + newmode = drm_mode_std(dev, &edid->standard_timings[i], + timing_level); if (newmode) { drm_mode_probed_add(connector, newmode); modes++; @@ -496,6 +546,9 @@ static int add_detailed_info(struct drm_connector *connector, { struct drm_device *dev = connector->dev; int i, j, modes = 0; + int timing_level; + + timing_level = standard_timing_level(edid); for (i = 0; i < EDID_DETAILED_TIMINGS; i++) { struct detailed_timing *timing = &edid->detailed_timings[i]; @@ -541,7 +594,7 @@ static int add_detailed_info(struct drm_connector *connector, struct drm_display_mode *newmode; std = &data->data.timings[j]; - newmode = drm_mode_std(dev, std); + newmode = drm_mode_std(dev, std, timing_level); if (newmode) { drm_mode_probed_add(connector, newmode); modes++;