@@ -1614,6 +1614,13 @@ typedef struct drm_i915_private {
*/
struct drm_property *input_size_property;
+ /*
+ * Property to dynamically vary the size of the
+ * borders. This will indirectly control the size
+ * of the display window i.e Panel fitter output
+ */
+ struct drm_property *output_border_property;
+
uint32_t hw_context_size;
struct list_head context_list;
@@ -10447,7 +10447,23 @@ static int intel_crtc_set_property(struct drm_crtc *crtc,
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->output_border_property) {
+ if ((val == (uint64_t)intel_crtc->border_size) &&
+ (((val >> 32) & 0x1) == intel_crtc->pfit_enabled))
+ return 0;
+
+ intel_crtc->border_size = (uint32_t)val;
+ intel_crtc->pfit_enabled = (val >> 32) & 0x1;
+ if ((intel_crtc->border_size != 0) &&
+ (!intel_crtc->pfit_enabled)) {
+ DRM_ERROR("Wrong setting, expect Pfit to be enabled when "
+ "applying borders\n");
+ return -EINVAL;
+ }
+
+ goto done;
+ }
if (property == dev_priv->input_size_property) {
int new_width = (int)((val >> 16) & 0xffff); @@ -10488,7 +10504,13 @@ static int intel_crtc_set_property(struct drm_crtc *crtc,
return 0;
}
- return ret;
+ return -EINVAL;
+
+done:
+ if (crtc)
+ intel_crtc_restore_mode(crtc);
+
+ return 0;
}
static const struct drm_crtc_funcs intel_crtc_funcs = { @@ -10641,12 +10663,23 @@ static void intel_crtc_init(struct drm_device *dev, int pipe)
if (!dev_priv->input_size_property)
dev_priv->input_size_property =
- drm_property_create_range(dev, 0, "input size", 0, 0xFFFFFFFF);
+ 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);
+
+ if (!dev_priv->output_border_property)
+ dev_priv->output_border_property =
+ drm_property_create_range(dev, 0, "border size",
+ 0, (uint64_t)0x1FFFFFFFF);
+
+ if (dev_priv->output_border_property)
+ drm_object_attach_property(&intel_crtc->base.base,
+ dev_priv->output_border_property,
+ 0);
}
enum pipe intel_get_pipe_from_connector(struct intel_connector *connector) diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
@@ -387,6 +387,11 @@ struct intel_crtc {
bool cpu_fifo_underrun_disabled;
bool pch_fifo_underrun_disabled;
+ /* for forceful enabling of panel fitter */
+ bool pfit_enabled;
+ /* border info for the output/display window */
+ uint32_t border_size;
+
/* per-pipe watermark state */
struct {
/* watermarks currently being used */ diff --git a/drivers/gpu/drm/i915/intel_panel.c b/drivers/gpu/drm/i915/intel_panel.c
@@ -29,10 +29,25 @@
*/
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+/* Max Downscale ratio of 1.125, expressed in 1.12 fixed point format
+*/ #define MAX_DOWNSCALE_RATIO (0x9 << 9)
#include <linux/moduleparam.h>
#include "intel_drv.h"
+static inline u32 panel_fitter_scaling(u32 source, u32 target) {
+ /*
+ * Floating point operation is not supported. So the FACTOR
+ * is defined, which can avoid the floating point computation
+ * when calculating the panel ratio.
+ */
+#define ACCURACY 12
+#define FACTOR (1 << ACCURACY)
+ u32 ratio = source * FACTOR / target;
+ return (FACTOR * ratio + FACTOR/2) / FACTOR; }
+
void
intel_fixed_panel_mode(const struct drm_display_mode *fixed_mode,
struct drm_display_mode *adjusted_mode) @@ -42,6 +57,60 @@ intel_fixed_panel_mode(const struct drm_display_mode *fixed_mode,
drm_mode_set_crtcinfo(adjusted_mode, 0); }