diff options
Diffstat (limited to 'drivers/gpu/drm/drm_modes.c')
| -rw-r--r-- | drivers/gpu/drm/drm_modes.c | 43 | 
1 files changed, 35 insertions, 8 deletions
diff --git a/drivers/gpu/drm/drm_modes.c b/drivers/gpu/drm/drm_modes.c index fc2adb62b757..85071a1c4547 100644 --- a/drivers/gpu/drm/drm_modes.c +++ b/drivers/gpu/drm/drm_modes.c @@ -707,18 +707,25 @@ EXPORT_SYMBOL(drm_mode_vrefresh);  /**   * drm_mode_set_crtcinfo - set CRTC modesetting parameters   * @p: mode - * @adjust_flags: unused? (FIXME) + * @adjust_flags: a combination of adjustment flags   *   * LOCKING:   * None.   *   * Setup the CRTC modesetting parameters for @p, adjusting if necessary. + * + * - The CRTC_INTERLACE_HALVE_V flag can be used to halve vertical timings of + *   interlaced modes. + * - The CRTC_STEREO_DOUBLE flag can be used to compute the timings for + *   buffers containing two eyes (only adjust the timings when needed, eg. for + *   "frame packing" or "side by side full").   */  void drm_mode_set_crtcinfo(struct drm_display_mode *p, int adjust_flags)  {  	if ((p == NULL) || ((p->type & DRM_MODE_TYPE_CRTC_C) == DRM_MODE_TYPE_BUILTIN))  		return; +	p->crtc_clock = p->clock;  	p->crtc_hdisplay = p->hdisplay;  	p->crtc_hsync_start = p->hsync_start;  	p->crtc_hsync_end = p->hsync_end; @@ -752,6 +759,20 @@ void drm_mode_set_crtcinfo(struct drm_display_mode *p, int adjust_flags)  		p->crtc_vtotal *= p->vscan;  	} +	if (adjust_flags & CRTC_STEREO_DOUBLE) { +		unsigned int layout = p->flags & DRM_MODE_FLAG_3D_MASK; + +		switch (layout) { +		case DRM_MODE_FLAG_3D_FRAME_PACKING: +			p->crtc_clock *= 2; +			p->crtc_vdisplay += p->crtc_vtotal; +			p->crtc_vsync_start += p->crtc_vtotal; +			p->crtc_vsync_end += p->crtc_vtotal; +			p->crtc_vtotal += p->crtc_vtotal; +			break; +		} +	} +  	p->crtc_vblank_start = min(p->crtc_vsync_start, p->crtc_vdisplay);  	p->crtc_vblank_end = max(p->crtc_vsync_end, p->crtc_vtotal);  	p->crtc_hblank_start = min(p->crtc_hsync_start, p->crtc_hdisplay); @@ -830,12 +851,16 @@ bool drm_mode_equal(const struct drm_display_mode *mode1, const struct drm_displ  	} else if (mode1->clock != mode2->clock)  		return false; -	return drm_mode_equal_no_clocks(mode1, mode2); +	if ((mode1->flags & DRM_MODE_FLAG_3D_MASK) != +	    (mode2->flags & DRM_MODE_FLAG_3D_MASK)) +		return false; + +	return drm_mode_equal_no_clocks_no_stereo(mode1, mode2);  }  EXPORT_SYMBOL(drm_mode_equal);  /** - * drm_mode_equal_no_clocks - test modes for equality + * drm_mode_equal_no_clocks_no_stereo - test modes for equality   * @mode1: first mode   * @mode2: second mode   * @@ -843,12 +868,13 @@ EXPORT_SYMBOL(drm_mode_equal);   * None.   *   * Check to see if @mode1 and @mode2 are equivalent, but - * don't check the pixel clocks. + * don't check the pixel clocks nor the stereo layout.   *   * RETURNS:   * True if the modes are equal, false otherwise.   */ -bool drm_mode_equal_no_clocks(const struct drm_display_mode *mode1, const struct drm_display_mode *mode2) +bool drm_mode_equal_no_clocks_no_stereo(const struct drm_display_mode *mode1, +					const struct drm_display_mode *mode2)  {  	if (mode1->hdisplay == mode2->hdisplay &&  	    mode1->hsync_start == mode2->hsync_start && @@ -860,12 +886,13 @@ bool drm_mode_equal_no_clocks(const struct drm_display_mode *mode1, const struct  	    mode1->vsync_end == mode2->vsync_end &&  	    mode1->vtotal == mode2->vtotal &&  	    mode1->vscan == mode2->vscan && -	    mode1->flags == mode2->flags) +	    (mode1->flags & ~DRM_MODE_FLAG_3D_MASK) == +	     (mode2->flags & ~DRM_MODE_FLAG_3D_MASK))  		return true;  	return false;  } -EXPORT_SYMBOL(drm_mode_equal_no_clocks); +EXPORT_SYMBOL(drm_mode_equal_no_clocks_no_stereo);  /**   * drm_mode_validate_size - make sure modes adhere to size constraints @@ -1014,7 +1041,7 @@ void drm_mode_connector_list_update(struct drm_connector *connector)  				/* if equal delete the probed mode */  				mode->status = pmode->status;  				/* Merge type bits together */ -				mode->type |= pmode->type; +				mode->type = pmode->type;  				list_del(&pmode->head);  				drm_mode_destroy(connector->dev, pmode);  				break;  | 
