[Intel-gfx] [PATCH] kms: Fix LVDS mode list construction.

ykzhao yakui.zhao at intel.com
Mon Feb 8 03:24:50 CET 2010


On Thu, 2009-12-03 at 01:05 +0800, Adam Jackson wrote:

Hi, Carl
	Will you please look at this patch and apply it? Without this patch we
will get very few display mode for LVDS that has no DS_RANGE block in
EDID. 
        It will be better that the patch can also be applied on the
2.9.xx release.

Thanks.
    Yakui.

> Rather than mangle the EDID block and hope the server does the right
> thing, just build a sensible mode list up front.  Do this for LVDS where
> there is no EDID or where it does not claim to be continuous-frequency
> (since in the latter case, the server will add reasonable modes for us).
> 
> Signed-off-by: Adam Jackson <ajax at redhat.com>
> ---
>  src/drmmode_display.c |  140 ++++++++++++++----------------------------------
>  1 files changed, 41 insertions(+), 99 deletions(-)
> 
> diff --git a/src/drmmode_display.c b/src/drmmode_display.c
> index a469f6c..d5e3c7e 100644
> --- a/src/drmmode_display.c
> +++ b/src/drmmode_display.c
> @@ -682,107 +682,46 @@ 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)
>  {
> -	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;
> -	}
> -	/*
> -	 * 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
> -	 */
> -	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;
> -	}
> -	/* 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
> -	 */
> -	j = 0;
> -	for (i = 0; i < koutput->count_modes; i++) {
> -		mode_ptr = &koutput->modes[i];
> -		if ((mode_ptr->hdisplay == p_lvds->hdisplay) &&
> -			(mode_ptr->vdisplay == p_lvds->vdisplay)) {
> -			/* find the fixed panel mode */
> -			j = i;
> -			break;
> -		}
> +    xf86MonPtr mon = output->MonInfo;
> +
> +    if (!mon || !GTF_SUPPORTED(mon->features.msc)) {
> +	DisplayModePtr i, m, p = NULL;
> +	int max_x = 0, max_y = 0;
> +	float max_vrefresh = 0.0;
> +
> +	for (m = modes; m; m = m->next) {
> +	    if (m->type & M_T_PREFERRED)
> +		p = m;
> +	    max_x = max(max_x, m->HDisplay);
> +	    max_y = max(max_y, m->VDisplay);
> +	    max_vrefresh = max(max_vrefresh, xf86ModeVRefresh(m));
>  	}
> -	pmode = xnfalloc(sizeof(DisplayModeRec));
> -	drmmode_ConvertFromKMode(output->scrn, &koutput->modes[j], pmode);
> -	/*support DPM, instead of DPMS*/
> -	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
> -		 */
> -		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;
> +
> +	max_vrefresh = max(max_vrefresh, 60.0);
> +	max_vrefresh *= (1 + SYNC_TOLERANCE);
> +
> +	m = xf86GetDefaultModes();
> +
> +	xf86ValidateModesSize(output->scrn, m, max_x, max_y, 0);
> +
> +	for (i = m; i; i = i->next) {
> +	    if (xf86ModeVRefresh(i) > max_vrefresh)
> +		i->status = MODE_VSYNC;
> +	    if (p && i->HDisplay >= p->HDisplay &&
> +		i->VDisplay >= p->VDisplay &&
> +		xf86ModeVRefresh(i) >= xf86ModeVRefresh(p))
> +		i->status = MODE_VSYNC;
>  	}
> -	/* 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;
> +
> +	xf86PruneInvalidModes(output->scrn, &m, FALSE);
> +
> +	modes = xf86ModesAdd(modes, m);
> +    }
> +
> +    return modes;
>  }
>  
>  static DisplayModePtr
> @@ -854,8 +793,11 @@ 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);
>  	}
> +
> +	if (koutput->connector_type ==  DRM_MODE_CONNECTOR_LVDS)
> +		Modes = drmmode_output_lvds_edid(output, Modes);
> +
>  	return Modes;
>  }
>  




More information about the Intel-gfx mailing list