@@ -1608,6 +1608,12 @@ typedef struct drm_i915_private {
struct drm_property *broadcast_rgb_property;
struct drm_property *force_audio_property;
+ /*
+ * Property to dynamically vary the size of the
+ * PIPESRC or Panel fitter input size
+ */
+ struct drm_property *input_size_property;
+
uint32_t hw_context_size;
struct list_head context_list;
@@ -10434,8 +10434,38 @@ out_config:
static int intel_crtc_set_property(struct drm_crtc *crtc,
struct drm_property *property, uint64_t val)
{
+ struct drm_device *dev = crtc->dev;
+ struct drm_i915_private *dev_priv = dev->dev_private;
+ struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
int ret = -ENOENT;
+ if (property == dev_priv->input_size_property) {
+ int new_width = (int)((val >> 16) & 0xffff);
+ int new_height = (int)(val & 0xffff);
+
+ if ((new_width == intel_crtc->config.pipe_src_w) &&
+ (new_height == intel_crtc->config.pipe_src_h))
+ return 0;
+
+ intel_crtc->config.pipe_src_w = new_width;
+ intel_crtc->config.pipe_src_h = new_height;
+
+ intel_crtc->config.requested_mode.hdisplay = new_width;
+ intel_crtc->config.requested_mode.vdisplay = new_height;
+
+ crtc->mode.hdisplay = new_width;
+ crtc->mode.vdisplay = new_height;
+
+ /* pipesrc controls the size that is scaled from, which should
+ * always be the user's requested size.
+ */
+ I915_WRITE(PIPESRC(intel_crtc->pipe),
+ ((intel_crtc->config.pipe_src_w - 1) << 16) |
+ (intel_crtc->config.pipe_src_h - 1));
+
+ return 0;
+ }
+
return ret;
}
@@ -10586,6 +10616,15 @@ static void intel_crtc_init(struct drm_device *dev, int pipe)
dev_priv->pipe_to_crtc_mapping[intel_crtc->pipe] = &intel_crtc->base;
drm_crtc_helper_add(&intel_crtc->base, &intel_helper_funcs);
+
+ if (!dev_priv->input_size_property)
+ dev_priv->input_size_property =
+ drm_property_create_range(dev, 0, "input size", 0, 0xFFFFFFFF);
+
+ if (dev_priv->input_size_property)
+ drm_object_attach_property(&intel_crtc->base.base,
+ dev_priv->input_size_property,
+ 0);
}
enum pipe intel_get_pipe_from_connector(struct intel_connector *connector)