[Intel-gfx] [PATCH] LVDS: Fix output mode list construction.
Dave Airlie
airlied at gmail.com
Tue Oct 13 22:36:24 CEST 2009
On Wed, Oct 14, 2009 at 5:18 AM, Adam Jackson <ajax at redhat.com> wrote:
> Construct a list of modes smaller than the LVDS panel size if either:
>
> - the panel does not have EDID or DisplayID
> - it has EDID/dID but does not claim to be continuous-frequency (in
> which case the server would have done it for us already)
>
> The old method would attempt to do this by mangling the EDID block and
> parsed ranges, which was unreasonably fragile, and would fail to do so
> when EDID existed but claimed only a single mode.
This really should be done in the kernel from what I can see, so all KMS users
get a consistent list of modes for the LVDS device.
Dave.
>
> 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 472bc74..d045903 100644
> --- a/src/drmmode_display.c
> +++ b/src/drmmode_display.c
> @@ -681,107 +681,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
> @@ -853,8 +792,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;
> }
>
> --
> 1.6.4.4
>
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx at lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/intel-gfx
>
More information about the Intel-gfx
mailing list