From: Akash Goel <[email protected]>

Added a new 'window size' property for connectors.
This can be used to control the output window size
of Panel fitter.
Also addd a new mode 'Manual' to existing 'scaling mode'
property.

Signed-off-by: G Pallavi <[email protected]>
Signed-off-by: Akash Goel <[email protected]>
---
 drivers/gpu/drm/drm_crtc.c         |   1 +
 drivers/gpu/drm/i915/intel_dp.c    |  58 ++++++++++++++++++---
 drivers/gpu/drm/i915/intel_drv.h   |   8 +++
 drivers/gpu/drm/i915/intel_panel.c | 104 +++++++++++++++++++++++++++++++++++++
 include/drm/drm_crtc.h             |   3 ++
 include/uapi/drm/drm_mode.h        |   1 +
 6 files changed, 167 insertions(+), 8 deletions(-)

diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c
index 35ea15d..1d237b5 100644
--- a/drivers/gpu/drm/drm_crtc.c
+++ b/drivers/gpu/drm/drm_crtc.c
@@ -123,6 +123,7 @@ static const struct drm_prop_enum_list 
drm_scaling_mode_enum_list[] =
        { DRM_MODE_SCALE_FULLSCREEN, "Full" },
        { DRM_MODE_SCALE_CENTER, "Center" },
        { DRM_MODE_SCALE_ASPECT, "Full aspect" },
+       { DRM_MODE_SCALE_MANUAL, "Manual" },
 };
 
 /*
diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index c512d78..c697b7a 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -886,12 +886,22 @@ intel_dp_compute_config(struct intel_encoder *encoder,
        if (is_edp(intel_dp) && intel_connector->panel.fixed_mode) {
                intel_fixed_panel_mode(intel_connector->panel.fixed_mode,
                                       adjusted_mode);
-               if (!HAS_PCH_SPLIT(dev))
-                       intel_gmch_panel_fitting(intel_crtc, pipe_config,
-                                                
intel_connector->panel.fitting_mode);
-               else
-                       intel_pch_panel_fitting(intel_crtc, pipe_config,
-                                               
intel_connector->panel.fitting_mode);
+               if (!HAS_PCH_SPLIT(dev)) {
+                       if (intel_connector->panel.fitting_mode == 
DRM_MODE_SCALE_MANUAL)
+                               intel_gmch_manual_panel_fitting(intel_crtc, 
pipe_config,
+                                                       
intel_connector->panel.display_window_size);
+                       else
+                               intel_gmch_panel_fitting(intel_crtc, 
pipe_config,
+                                                        
intel_connector->panel.fitting_mode);
+               }
+               else {
+                       if (intel_connector->panel.fitting_mode == 
DRM_MODE_SCALE_MANUAL)
+                               intel_pch_manual_panel_fitting(intel_crtc, 
pipe_config,
+                                                       
intel_connector->panel.display_window_size);
+                       else
+                               intel_pch_panel_fitting(intel_crtc, pipe_config,
+                                                       
intel_connector->panel.fitting_mode);
+               }
        }
 
        if (adjusted_mode->flags & DRM_MODE_FLAG_DBLCLK)
@@ -3376,14 +3386,36 @@ intel_dp_set_property(struct drm_connector *connector,
                }
 
                if (intel_connector->panel.fitting_mode == val) {
-                       /* the eDP scaling property is not changed */
-                       return 0;
+                       /* Check if display window size has changed */
+                       if ((val == DRM_MODE_SCALE_MANUAL) &&
+                            intel_connector->panel.display_window_size_changed)
+                               
intel_connector->panel.display_window_size_changed = 0;
+                       else {
+                               /* the eDP scaling property is not changed */
+                               return 0;
+                       }
                }
                intel_connector->panel.fitting_mode = val;
 
+               if (val != DRM_MODE_SCALE_MANUAL)
+                       intel_connector->panel.display_window_size = 0;
+
                goto done;
        }
 
+       if (is_edp(intel_dp) &&
+           property == connector->dev->mode_config.window_size_property) {
+               if (intel_connector->panel.display_window_size == val) {
+                       /* the eDP panel window size property is not changed */
+                       intel_connector->panel.display_window_size_changed = 0;
+                       return 0;
+               }
+               intel_connector->panel.display_window_size = val;
+               intel_connector->panel.display_window_size_changed = 1;
+
+               return 0;
+       }
+
        return -EINVAL;
 
 done:
@@ -3517,6 +3549,16 @@ intel_dp_add_properties(struct intel_dp *intel_dp, 
struct drm_connector *connect
                        connector->dev->mode_config.scaling_mode_property,
                        DRM_MODE_SCALE_ASPECT);
                intel_connector->panel.fitting_mode = DRM_MODE_SCALE_ASPECT;
+
+               connector->dev->mode_config.window_size_property =
+                       drm_property_create_range(connector->dev, 0,
+                                               "window size", 0, 0xFFFFFFFF);
+               drm_object_attach_property(
+                       &connector->base,
+                       connector->dev->mode_config.window_size_property,
+                       0);
+               intel_connector->panel.display_window_size = 0;
+               intel_connector->panel.display_window_size_changed = 0;
        }
 }
 
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index a4ffc02..5247b6b 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -157,6 +157,8 @@ struct intel_panel {
        struct drm_display_mode *fixed_mode;
        struct drm_display_mode *downclock_mode;
        int fitting_mode;
+       u32 display_window_size;
+       bool display_window_size_changed;
 
        /* backlight */
        struct {
@@ -841,9 +843,15 @@ void intel_fixed_panel_mode(const struct drm_display_mode 
*fixed_mode,
 void intel_pch_panel_fitting(struct intel_crtc *crtc,
                             struct intel_crtc_config *pipe_config,
                             int fitting_mode);
+void intel_pch_manual_panel_fitting(struct intel_crtc *intel_crtc,
+                                   struct intel_crtc_config *pipe_config,
+                                   u32 display_window_size);
 void intel_gmch_panel_fitting(struct intel_crtc *crtc,
                              struct intel_crtc_config *pipe_config,
                              int fitting_mode);
+void intel_gmch_manual_panel_fitting(struct intel_crtc *crtc,
+                             struct intel_crtc_config *pipe_config,
+                             u32 display_window_size);
 void intel_panel_set_backlight(struct intel_connector *connector, u32 level,
                               u32 max);
 int intel_panel_setup_backlight(struct drm_connector *connector);
diff --git a/drivers/gpu/drm/i915/intel_panel.c 
b/drivers/gpu/drm/i915/intel_panel.c
index cb05840..2965975 100644
--- a/drivers/gpu/drm/i915/intel_panel.c
+++ b/drivers/gpu/drm/i915/intel_panel.c
@@ -114,6 +114,48 @@ done:
        pipe_config->pch_pfit.enabled = pipe_config->pch_pfit.size != 0;
 }
 
+void
+intel_pch_manual_panel_fitting(struct intel_crtc *intel_crtc,
+                       struct intel_crtc_config *pipe_config,
+                       u32 display_window_size)
+{
+       struct drm_display_mode *adjusted_mode;
+       int x, y;
+       u32 tot_width, tot_height;
+       u32 dst_width, dst_height;
+
+       adjusted_mode = &pipe_config->adjusted_mode;
+
+       tot_width  = adjusted_mode->crtc_hdisplay;
+       tot_height = adjusted_mode->crtc_vdisplay;
+
+       dst_width  = ((display_window_size >> 16) & 0xffff);
+       dst_height = (display_window_size & 0xffff);
+
+       x = y = 0;
+
+       if (tot_width < dst_width) {
+               DRM_ERROR("width is too big\n");
+               return;
+       } else if (dst_width & 1) {
+               DRM_ERROR("width must be even\n");
+               return;
+       } else if (tot_height < dst_height) {
+               DRM_ERROR("height is too big\n");
+               return;
+       } else if (dst_height & 1) {
+               DRM_ERROR("height must be even\n");
+               return;
+       }
+
+       x = (adjusted_mode->hdisplay - dst_width + 1)/2;
+       y = (adjusted_mode->vdisplay - dst_height + 1)/2;
+
+       pipe_config->pch_pfit.pos = (x << 16) | y;
+       pipe_config->pch_pfit.size = (dst_width << 16) | dst_height;
+       pipe_config->pch_pfit.enabled = pipe_config->pch_pfit.size != 0;
+}
+
 static void
 centre_horizontally(struct drm_display_mode *mode,
                    int width)
@@ -323,6 +365,68 @@ out:
        pipe_config->gmch_pfit.lvds_border_bits = border;
 }
 
+void intel_gmch_manual_panel_fitting(struct intel_crtc *intel_crtc,
+                                    struct intel_crtc_config *pipe_config,
+                                    u32 display_window_size)
+{
+       u32 pfit_control = 0, border = 0;
+       u32 pf_horizontal_ratio, pf_vertical_ratio;
+       struct drm_display_mode *adjusted_mode;
+       u32 tot_width, tot_height;
+       u32 src_width, src_height; /* pipesrc.x, pipesrc.y */
+       u32 dst_width, dst_height;
+
+       adjusted_mode = &pipe_config->adjusted_mode;
+
+       src_width = pipe_config->pipe_src_w;
+       src_height = pipe_config->pipe_src_h;
+
+       tot_width  = adjusted_mode->crtc_hdisplay;
+       tot_height = adjusted_mode->crtc_vdisplay;
+
+       dst_width  = ((display_window_size >> 16) & 0xffff);
+       dst_height = (display_window_size & 0xffff);
+
+       pf_horizontal_ratio = panel_fitter_scaling(src_width, dst_width);
+       pf_vertical_ratio   = panel_fitter_scaling(src_height, dst_height);
+
+/* Max Downscale ratio of 1.125, expressed in 1.12 fixed point format */
+#define MAX_DOWNSCALE_RATIO  (0x9 << 9)
+
+       if (pf_horizontal_ratio > MAX_DOWNSCALE_RATIO) {
+                       DRM_ERROR("width is too small\n");
+                       return;
+       } else if (tot_width < dst_width) {
+                       DRM_ERROR("width is too big\n");
+                       return;
+       } else if (dst_width & 1) {
+                       DRM_ERROR("width must be even\n");
+                       return;
+       } else if (pf_vertical_ratio > MAX_DOWNSCALE_RATIO) {
+                       DRM_ERROR("height is too small\n");
+                       return;
+       } else if (tot_height < dst_height) {
+                       DRM_ERROR("height is too big\n");
+                       return;
+       } else if (dst_height & 1) {
+                       DRM_ERROR("height must be even\n");
+                       return;
+       }
+
+       centre_horizontally(adjusted_mode, dst_width);
+       centre_vertically(adjusted_mode, dst_height);
+       border = LVDS_BORDER_ENABLE;
+
+       /* PFIT_SCALING_PROGRAMMED is de-featured on BYT */
+       pfit_control |= PFIT_ENABLE | PFIT_SCALING_AUTO;
+       pfit_control |= ((intel_crtc->pipe << PFIT_PIPE_SHIFT) | 
PFIT_FILTER_FUZZY);
+
+       pipe_config->gmch_pfit.control = pfit_control;
+       pipe_config->gmch_pfit.lvds_border_bits = border;
+
+       return;
+}
+
 static u32 intel_panel_compute_brightness(struct intel_connector *connector,
                                          u32 val)
 {
diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h
index f764654..625d7fd 100644
--- a/include/drm/drm_crtc.h
+++ b/include/drm/drm_crtc.h
@@ -902,6 +902,9 @@ struct drm_mode_config {
        struct drm_property *scaling_mode_property;
        struct drm_property *dirty_info_property;
 
+       /* Panel fitter output property */
+       struct drm_property *window_size_property;
+
        /* dumb ioctl parameters */
        uint32_t preferred_depth, prefer_shadow;
 
diff --git a/include/uapi/drm/drm_mode.h b/include/uapi/drm/drm_mode.h
index f104c26..a187dac 100644
--- a/include/uapi/drm/drm_mode.h
+++ b/include/uapi/drm/drm_mode.h
@@ -87,6 +87,7 @@
 #define DRM_MODE_SCALE_FULLSCREEN      1 /* Full screen, ignore aspect */
 #define DRM_MODE_SCALE_CENTER          2 /* Centered, no scaling */
 #define DRM_MODE_SCALE_ASPECT          3 /* Full screen, preserve aspect */
+#define DRM_MODE_SCALE_MANUAL          4 /* User can control display window 
size */
 
 /* Dithering mode options */
 #define DRM_MODE_DITHERING_OFF 0
-- 
1.8.5.2

_______________________________________________
Intel-gfx mailing list
[email protected]
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

Reply via email to