| From ef60f6c04841f649ef0e7c6c5c43a439fa0fe380 Mon Sep 17 00:00:00 2001 |
| From: Daniel Vetter <daniel.vetter@ffwll.ch> |
| Date: Thu, 6 Jun 2013 14:55:52 +0200 |
| Subject: drm/i915: pipe config quirk infrastructure plus sdvo mode.flags fix |
| |
| For various reasons the hw state readout might not be able to |
| faithfully match the hw state: |
| - broken hw (like the case which motivated this patch here where the |
| sdvo encoder does not implemented mandatory functionality |
| correctly). |
| - platforms which are not supported fully with the pipe config |
| infrastructure |
| - if our code doesn't support a given hw configuration natively, e.g. |
| special restrictions on the per-pipe panel fitters when they're used |
| in high-quality scaling modes. |
| |
| In all these cases both fastboot and the hw state cross checker need |
| to be aware of these cases and act accordingly. To be able to do this |
| add a new quirk flag to the pipe config structure. |
| |
| The specific case at hand is an sdvo encoder which doesn't implement |
| the get_timings function, so adjusted_mode flags will be wrong. The |
| strange thing though is that the encoder _does_ work, even though it |
| doesn't implement any of the timings functions (so neither get nor |
| set, neither for input nor output timings). |
| |
| Not that non-compliant sdvo encoder are any surprise at all ... |
| |
| v2: |
| - Don't read random garbage from the dtd if the get_timings call |
| failed (suggested by Chris). |
| - Still check the interlaced flag, that's read out from someplace |
| else. We want maximal paranoia, after all. |
| |
| Reviewed-by: Chris Wilson <chris@chris-wilson.co.uk> |
| Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch> |
| (cherry picked from commit bb760063790fbbc3c956f23aff4dbdfdd3c03818) |
| Signed-off-by: Darren Hart <dvhart@linux.intel.com> |
| --- |
| drivers/gpu/drm/i915/intel_display.c | 22 ++++++++++++++-------- |
| drivers/gpu/drm/i915/intel_drv.h | 11 +++++++++++ |
| drivers/gpu/drm/i915/intel_sdvo.c | 24 +++++++++++++----------- |
| 3 files changed, 38 insertions(+), 19 deletions(-) |
| |
| diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c |
| index 69c70dd606e3..b8851f3f4911 100644 |
| --- a/drivers/gpu/drm/i915/intel_display.c |
| +++ b/drivers/gpu/drm/i915/intel_display.c |
| @@ -8095,6 +8095,9 @@ intel_pipe_config_compare(struct drm_device *dev, |
| return false; \ |
| } |
| |
| +#define PIPE_CONF_QUIRK(quirk) \ |
| + ((current_config->quirks | pipe_config->quirks) & (quirk)) |
| + |
| PIPE_CONF_CHECK_I(cpu_transcoder); |
| |
| PIPE_CONF_CHECK_I(has_pch_encoder); |
| @@ -8125,14 +8128,16 @@ intel_pipe_config_compare(struct drm_device *dev, |
| PIPE_CONF_CHECK_FLAGS(adjusted_mode.flags, |
| DRM_MODE_FLAG_INTERLACE); |
| |
| - PIPE_CONF_CHECK_FLAGS(adjusted_mode.flags, |
| - DRM_MODE_FLAG_PHSYNC); |
| - PIPE_CONF_CHECK_FLAGS(adjusted_mode.flags, |
| - DRM_MODE_FLAG_NHSYNC); |
| - PIPE_CONF_CHECK_FLAGS(adjusted_mode.flags, |
| - DRM_MODE_FLAG_PVSYNC); |
| - PIPE_CONF_CHECK_FLAGS(adjusted_mode.flags, |
| - DRM_MODE_FLAG_NVSYNC); |
| + if (!PIPE_CONF_QUIRK(PIPE_CONFIG_QUIRK_MODE_SYNC_FLAGS)) { |
| + PIPE_CONF_CHECK_FLAGS(adjusted_mode.flags, |
| + DRM_MODE_FLAG_PHSYNC); |
| + PIPE_CONF_CHECK_FLAGS(adjusted_mode.flags, |
| + DRM_MODE_FLAG_NHSYNC); |
| + PIPE_CONF_CHECK_FLAGS(adjusted_mode.flags, |
| + DRM_MODE_FLAG_PVSYNC); |
| + PIPE_CONF_CHECK_FLAGS(adjusted_mode.flags, |
| + DRM_MODE_FLAG_NVSYNC); |
| + } |
| |
| PIPE_CONF_CHECK_I(requested_mode.hdisplay); |
| PIPE_CONF_CHECK_I(requested_mode.vdisplay); |
| @@ -8149,6 +8154,7 @@ intel_pipe_config_compare(struct drm_device *dev, |
| |
| #undef PIPE_CONF_CHECK_I |
| #undef PIPE_CONF_CHECK_FLAGS |
| +#undef PIPE_CONF_QUIRK |
| |
| return true; |
| } |
| diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h |
| index 0e5897cb8d48..a060d82f175b 100644 |
| --- a/drivers/gpu/drm/i915/intel_drv.h |
| +++ b/drivers/gpu/drm/i915/intel_drv.h |
| @@ -193,6 +193,17 @@ typedef struct dpll { |
| } intel_clock_t; |
| |
| struct intel_crtc_config { |
| + /** |
| + * quirks - bitfield with hw state readout quirks |
| + * |
| + * For various reasons the hw state readout code might not be able to |
| + * completely faithfully read out the current state. These cases are |
| + * tracked with quirk flags so that fastboot and state checker can act |
| + * accordingly. |
| + */ |
| +#define PIPE_CONFIG_QUIRK_MODE_SYNC_FLAGS (1<<0) /* unreliable sync mode.flags */ |
| + unsigned long quirks; |
| + |
| struct drm_display_mode requested_mode; |
| struct drm_display_mode adjusted_mode; |
| /* This flag must be set by the encoder's compute_config callback if it |
| diff --git a/drivers/gpu/drm/i915/intel_sdvo.c b/drivers/gpu/drm/i915/intel_sdvo.c |
| index 785968c6916f..1262fc4a1b34 100644 |
| --- a/drivers/gpu/drm/i915/intel_sdvo.c |
| +++ b/drivers/gpu/drm/i915/intel_sdvo.c |
| @@ -1324,19 +1324,21 @@ static void intel_sdvo_get_config(struct intel_encoder *encoder, |
| |
| ret = intel_sdvo_get_input_timing(intel_sdvo, &dtd); |
| if (!ret) { |
| + /* Some sdvo encoders are not spec compliant and don't |
| + * implement the mandatory get_timings function. */ |
| DRM_DEBUG_DRIVER("failed to retrieve SDVO DTD\n"); |
| - return; |
| - } |
| - |
| - if (dtd.part2.dtd_flags & DTD_FLAG_HSYNC_POSITIVE) |
| - flags |= DRM_MODE_FLAG_PHSYNC; |
| - else |
| - flags |= DRM_MODE_FLAG_NHSYNC; |
| + pipe_config->quirks |= PIPE_CONFIG_QUIRK_MODE_SYNC_FLAGS; |
| + } else { |
| + if (dtd.part2.dtd_flags & DTD_FLAG_HSYNC_POSITIVE) |
| + flags |= DRM_MODE_FLAG_PHSYNC; |
| + else |
| + flags |= DRM_MODE_FLAG_NHSYNC; |
| |
| - if (dtd.part2.dtd_flags & DTD_FLAG_VSYNC_POSITIVE) |
| - flags |= DRM_MODE_FLAG_PVSYNC; |
| - else |
| - flags |= DRM_MODE_FLAG_NVSYNC; |
| + if (dtd.part2.dtd_flags & DTD_FLAG_VSYNC_POSITIVE) |
| + flags |= DRM_MODE_FLAG_PVSYNC; |
| + else |
| + flags |= DRM_MODE_FLAG_NVSYNC; |
| + } |
| |
| pipe_config->adjusted_mode.flags |= flags; |
| |
| -- |
| 1.8.5.rc3 |
| |