diff options
Diffstat (limited to 'linux-core')
| -rw-r--r-- | linux-core/radeon_ms_fb.c | 70 | 
1 files changed, 60 insertions, 10 deletions
diff --git a/linux-core/radeon_ms_fb.c b/linux-core/radeon_ms_fb.c index ef7c5cf1..b629b9eb 100644 --- a/linux-core/radeon_ms_fb.c +++ b/linux-core/radeon_ms_fb.c @@ -42,8 +42,9 @@  #include "radeon_ms.h"  struct radeonfb_par { -	struct drm_device	*dev; -	struct drm_crtc		*crtc; +	struct drm_device       *dev; +	struct drm_crtc         *crtc; +	struct drm_display_mode *fb_mode;  };  static int radeonfb_setcolreg(unsigned regno, unsigned red, @@ -127,13 +128,38 @@ static int radeonfb_check_var(struct fb_var_screeninfo *var,  	return 0;  } +static bool radeonfb_mode_equal(struct drm_display_mode *mode1, +			        struct drm_display_mode *mode2) +{ +	if (mode1->hdisplay == mode2->hdisplay && +	    mode1->hsync_start == mode2->hsync_start && +	    mode1->hsync_end == mode2->hsync_end && +	    mode1->htotal == mode2->htotal && +	    mode1->hskew == mode2->hskew && +	    mode1->vdisplay == mode2->vdisplay && +	    mode1->vsync_start == mode2->vsync_start && +	    mode1->vsync_end == mode2->vsync_end && +	    mode1->vtotal == mode2->vtotal && +	    mode1->vscan == mode2->vscan && +	    mode1->flags == mode2->flags) { +	    	/* FIXME: what about adding a margin for clock ? */ +		if (mode1->clock == mode2->clock) +			return true; +		return false; +	} +	 +	return false; +} +  static int radeonfb_set_par(struct fb_info *info)  {  	struct radeonfb_par *par = info->par;  	struct drm_framebuffer *fb = par->crtc->fb;  	struct drm_device *dev = par->dev; -        struct drm_display_mode *drm_mode; +        struct drm_display_mode *drm_mode, *search_mode; +        struct drm_output *output;          struct fb_var_screeninfo *var = &info->var; +	int found = 0;          switch (var->bits_per_pixel) {          case 16: @@ -171,15 +197,39 @@ static int radeonfb_set_par(struct fb_info *info)  	drm_mode_set_name(drm_mode);  	drm_mode_set_crtcinfo(drm_mode, CRTC_INTERLACE_HALVE_V); -	drm_mode_debug_printmodeline(dev, drm_mode); +        list_for_each_entry(output, &dev->mode_config.output_list, head) { +                if (output->crtc == par->crtc) +                        break; +        } -	if (!drm_crtc_set_mode(par->crtc, drm_mode, 0, 0)) -		return -EINVAL; +	drm_mode_debug_printmodeline(dev, drm_mode);     +        list_for_each_entry(search_mode, &output->modes, head) { +		drm_mode_debug_printmodeline(dev, search_mode); +		if (radeonfb_mode_equal(drm_mode, search_mode)) { +			drm_mode_destroy(dev, drm_mode); +			drm_mode = search_mode; +			found = 1; +			break; +		} +	} -        /* Have to destroy our created mode if we're not searching the mode -         * list for it. -         */ -	drm_mode_destroy(dev, drm_mode); +	if (!found) { +		if (par->fb_mode) { +			drm_mode_detachmode_crtc(dev, par->fb_mode); +		} +		par->fb_mode = drm_mode; +		drm_mode_debug_printmodeline(dev, drm_mode); +		/* attach mode */ +		drm_mode_attachmode_crtc(dev, par->crtc, par->fb_mode); +	} + +	if (par->crtc->enabled) { +		if (!drm_mode_equal(&par->crtc->mode, drm_mode)) { +			if (!drm_crtc_set_mode(par->crtc, drm_mode, 0, 0)) { +				return -EINVAL; +			} +		} +	}  	return 0;  }  | 
