From patchwork Wed Dec 9 13:51:42 2009 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Zhao, Yakui" X-Patchwork-Id: 65993 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 nB9DrhLi029712 for ; Wed, 9 Dec 2009 13:53:43 GMT Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 8021D9E8A5; Wed, 9 Dec 2009 05:53:42 -0800 (PST) X-Original-To: intel-gfx@lists.freedesktop.org Delivered-To: intel-gfx@lists.freedesktop.org Received: from mga09.intel.com (mga09.intel.com [134.134.136.24]) by gabe.freedesktop.org (Postfix) with ESMTP id 6FF8A9E7F7 for ; Wed, 9 Dec 2009 05:53:40 -0800 (PST) Received: from orsmga001.jf.intel.com ([10.7.209.18]) by orsmga102.jf.intel.com with ESMTP; 09 Dec 2009 05:52:54 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="4.47,368,1257148800"; d="scan'208";a="577082677" Received: from yakui_zhao.sh.intel.com (HELO localhost.localdomain) ([10.239.13.200]) by orsmga001.jf.intel.com with ESMTP; 09 Dec 2009 05:53:22 -0800 From: yakui.zhao@intel.com To: cworth@cworth.org, eric@anholt.net, ajax@redhat.com Date: Wed, 9 Dec 2009 21:51:42 +0800 Message-Id: <1260366702-13201-1-git-send-email-yakui.zhao@intel.com> X-Mailer: git-send-email 1.5.4.5 Cc: intel-gfx@lists.freedesktop.org Subject: [Intel-gfx] [PATCH] kms: fix the LVDS mode list construction 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 diff --git a/src/drmmode_display.c b/src/drmmode_display.c index a469f6c..7b4ce2f 100644 --- a/src/drmmode_display.c +++ b/src/drmmode_display.c @@ -682,65 +682,48 @@ static void fill_detailed_lvds_block(struct detailed_monitor_section *det_mon, timing->misc |= 0x01; } -static int drmmode_output_lvds_edid(xf86OutputPtr output, - struct fixed_panel_lvds *p_lvds) +static DisplayModePtr +drmmode_output_lvds_edid(xf86OutputPtr output, + DisplayModePtr modes, struct fixed_panel_lvds *p_lvds) { - drmmode_output_private_ptr drmmode_output = output->driver_private; - drmModeConnectorPtr koutput = drmmode_output->mode_output; - int i, j; - DisplayModePtr pmode; - xf86MonPtr edid_mon; - drmModeModeInfo *mode_ptr; - struct detailed_monitor_section *det_mon; - - if (output->MonInfo) { - /* - * If there exists the EDID, we will either find a DS_RANGES - * or replace a DS_VENDOR block, smashing it into a DS_RANGES - * block with opern refresh to match all the default modes. - */ - int edid_det_block_num; - edid_mon = output->MonInfo; - edid_mon->features.msc |= 0x01; - j = -1; - edid_det_block_num = sizeof(edid_mon->det_mon) / - sizeof(edid_mon->det_mon[0]); - for (i = 0; i < edid_det_block_num; i++) { - if (edid_mon->det_mon[i].type >= DS_VENDOR && j == -1) - j = i; - if (edid_mon->det_mon[i].type == DS_RANGES) { - j = i; - break; - } - } - if (j != -1) { - struct monitor_ranges *ranges = - &edid_mon->det_mon[j].section.ranges; - edid_mon->det_mon[j].type = DS_RANGES; - ranges->min_v = 0; - ranges->max_v = 200; - ranges->min_h = 0; - ranges->max_h = 200; - } - return 0; - } + drmmode_output_private_ptr drmmode_output = output->driver_private; + drmModeConnectorPtr koutput = drmmode_output->mode_output; + + xf86MonPtr edid_mon = output->MonInfo; + int i, j, flags; + DisplayModePtr pmode, m; + drmModeModeInfo *mode_ptr; + struct detailed_monitor_section *det_mon; + + pmode = xnfalloc(sizeof(DisplayModeRec)); + drmmode_ConvertFromKMode(output->scrn, &koutput->modes[j], pmode); + + if (edid_mon) { /* - * If there is no EDID, we will construct a bogus EDID for LVDS output - * device. This is similar to what we have done in i830_lvds.c + * when there exists the EDID, we will clear the GTF flag to avoid + * that the xf86GetDefaultModes will be called again in xserver + */ + edid_mon->features.msc &= ~(0x01); + } else { + /* + * When there is no EDID, we will construct the bogus EDID and not + * set the GTF flag. This is also to avoid that the xf86GetDefaultModes + * will be called again in xserver */ edid_mon = NULL; edid_mon = xcalloc(1, sizeof(xf86Monitor)); if (!edid_mon) { xf86DrvMsg(output->scrn->scrnIndex, X_ERROR, "Can't allocate memory for edid_mon.\n"); - return 0; + return modes; } - /* Find the fixed panel mode. + /* + * Find the fixed panel mode. * In theory when there is no EDID, KMS kernel will return only one * mode. And this can be regarded as fixed lvds panel mode. * But it will be better to traverse the mode list to get the fixed * lvds panel mode again as we don't know whether some new modes - * are added for the LVDS output device + * are added for the LVDS output device. */ j = 0; for (i = 0; i < koutput->count_modes; i++) { @@ -758,31 +741,38 @@ static int drmmode_output_lvds_edid(xf86OutputPtr output, edid_mon->features.dpms |= 0x1; /*defaultly support RGB color display*/ edid_mon->features.display_type |= 0x1; - /*defaultly display support continuous-freqencey*/ - edid_mon->features.msc |= 0x1; /*defaultly the EDID version is 1.4 */ edid_mon->ver.version = 1; edid_mon->ver.revision = 4; det_mon = edid_mon->det_mon; if (pmode) { - /* now we construct new EDID monitor, - * so filled one detailed timing block - */ + /* construct bogus EDID and filled one detailed timing block */ fill_detailed_lvds_block(det_mon, pmode); /* the filed timing block should be set preferred*/ edid_mon->features.msc |= 0x2; - det_mon = det_mon + 1; } - /* Set wide sync ranges so we get all modes - * handed to valid_mode for checking - */ - det_mon->type = DS_RANGES; - det_mon->section.ranges.min_v = 0; - det_mon->section.ranges.max_v = 200; - det_mon->section.ranges.min_h = 0; - det_mon->section.ranges.max_h = 200; output->MonInfo = edid_mon; - return 0; + if (pmode) + xfree(pmode); + } + /* + * Always add the default mode for LVDS and invalidate the mode which is + * beyond the range of hdisplay/vdisplay + */ + m = xf86GetDefaultModes(); + /* validate the default mode list by checking panel size */ + xf86ValidateModesSize(output->scrn, m, p_lvds->hdisplay, + p_lvds->vdisplay, 0); + + /* mark the invalid mode by checking flag(Interface/doublescan) */ + flags = (output->interlaceAllowed ? V_INTERLACE : 0) | + (output->doubleScanAllowed ? V_DBLSCAN : 0); + xf86ValidateModesFlags(output->scrn, m, flags); + /* remove the invalid mode */ + xf86PruneInvalidModes(output->scrn, &m, 1); + modes = xf86ModesAdd(modes, m); + + return modes; } static DisplayModePtr @@ -854,8 +844,9 @@ drmmode_output_get_modes(xf86OutputPtr output) if (!p_lvds->hdisplay || !p_lvds->vdisplay) xf86DrvMsg(output->scrn->scrnIndex, X_ERROR, "Incorrect KMS mode.\n"); - drmmode_output_lvds_edid(output, p_lvds); + Modes = drmmode_output_lvds_edid(output, Modes, p_lvds); } + return Modes; }