Adding pipe destination co-ordinate and size property as crtc atomic drm property to dynamically change pipe destination attributes on GEN9. Signed-off-by: Nabendu Maiti <nabendu.bikash.maiti@xxxxxxxxx> --- drivers/gpu/drm/drm_atomic.c | 20 +++++++++++ drivers/gpu/drm/drm_crtc.c | 32 +++++++++++++++++ drivers/gpu/drm/i915/intel_display.c | 70 +++++++++++++++++++++++++++++++++--- drivers/gpu/drm/i915/intel_drv.h | 2 ++ include/drm/drm_crtc.h | 5 +++ include/uapi/drm/drm_mode.h | 1 + 6 files changed, 126 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/drm_atomic.c b/drivers/gpu/drm/drm_atomic.c index 3fddfa4..3df78c0 100644 --- a/drivers/gpu/drm/drm_atomic.c +++ b/drivers/gpu/drm/drm_atomic.c @@ -502,6 +502,18 @@ int drm_atomic_crtc_set_property(struct drm_crtc *crtc, } else if (property == config->prop_fitting_mode) { state->fitting_mode = val; state->pipescaler_changed = true; + } else if (property == config->prop_pipe_dst_x) { + state->dst_x = val; + state->pipescaler_changed = true; + } else if (property == config->prop_pipe_dst_y) { + state->dst_y = val; + state->pipescaler_changed = true; + } else if (property == config->prop_pipe_dst_w) { + state->dst_w = val; + state->pipescaler_changed = true; + } else if (property == config->prop_pipe_dst_h) { + state->dst_h = val; + state->pipescaler_changed = true; } else if (crtc->funcs->atomic_set_property) return crtc->funcs->atomic_set_property(crtc, state, property, val); else @@ -550,6 +562,14 @@ drm_atomic_crtc_get_property(struct drm_crtc *crtc, *val = state->src_h; else if (property == config->prop_fitting_mode) *val = state->fitting_mode; + else if (property == config->prop_pipe_dst_x) + *val = state->dst_x; + else if (property == config->prop_pipe_dst_y) + *val = state->dst_y; + else if (property == config->prop_pipe_dst_w) + *val = state->dst_w; + else if (property == config->prop_pipe_dst_h) + *val = state->dst_h; else if (crtc->funcs->atomic_get_property) return crtc->funcs->atomic_get_property(crtc, state, property, val); else diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c index b24e839..c941f58 100644 --- a/drivers/gpu/drm/drm_crtc.c +++ b/drivers/gpu/drm/drm_crtc.c @@ -383,6 +383,14 @@ int drm_crtc_init_with_planes(struct drm_device *dev, struct drm_crtc *crtc, config->prop_pipe_src_h, 0); drm_object_attach_property(&crtc->base, config->prop_fitting_mode, 0); + drm_object_attach_property(&crtc->base, + config->prop_pipe_dst_x, 0); + drm_object_attach_property(&crtc->base, + config->prop_pipe_dst_y, 0); + drm_object_attach_property(&crtc->base, + config->prop_pipe_dst_w, 0); + drm_object_attach_property(&crtc->base, + config->prop_pipe_dst_h, 0); } return 0; @@ -967,6 +975,30 @@ static int drm_mode_create_standard_properties(struct drm_device *dev) return -ENOMEM; dev->mode_config.prop_fitting_mode = prop; + prop = drm_property_create_range(dev, DRM_MODE_PROP_ATOMIC, + "PIPE_DST_X", 0, INT_MAX); + if (!prop) + return -ENOMEM; + dev->mode_config.prop_pipe_dst_x = prop; + + prop = drm_property_create_range(dev, DRM_MODE_PROP_ATOMIC, + "PIPE_DST_Y", 0, INT_MAX); + if (!prop) + return -ENOMEM; + dev->mode_config.prop_pipe_dst_y = prop; + + prop = drm_property_create_range(dev, DRM_MODE_PROP_ATOMIC, + "PIPE_DST_W", 0, INT_MAX); + if (!prop) + return -ENOMEM; + dev->mode_config.prop_pipe_dst_w = prop; + + prop = drm_property_create_range(dev, DRM_MODE_PROP_ATOMIC, + "PIPE_DST_H", 0, INT_MAX); + if (!prop) + return -ENOMEM; + dev->mode_config.prop_pipe_dst_h = prop; + return 0; } diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index e3ecb8b..9c7434f 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -12548,6 +12548,35 @@ static bool check_single_encoder_cloning(struct drm_atomic_state *state, return true; } +void +intel_gen9_pipe_scale(struct intel_crtc *intel_crtc, + struct intel_crtc_state *pipe_config, + int fitting_mode) +{ + const struct drm_display_mode *adjusted_mode = + &pipe_config->base.adjusted_mode; + int x = 0, y = 0, width = 0, height = 0; + + /* Native modes don't need fitting */ + if ((adjusted_mode->crtc_hdisplay == pipe_config->pipe_src_w && + adjusted_mode->crtc_vdisplay == pipe_config->pipe_src_h) && + ((pipe_config->pipe_dst_x + pipe_config->pipe_dst_w) == + pipe_config->pipe_src_w) && + ((pipe_config->pipe_dst_y + pipe_config->pipe_dst_h) == + pipe_config->pipe_src_w)) + goto done; + + x = pipe_config->pipe_dst_x; + y = pipe_config->pipe_dst_y; + width = pipe_config->pipe_dst_w; + height = pipe_config->pipe_dst_h; + +done: + pipe_config->pch_pfit.pos = (x << 16) | y; + pipe_config->pch_pfit.size = (width << 16) | height; + pipe_config->pch_pfit.enabled = pipe_config->pch_pfit.size != 0; +} + static int skylake_pfiter_calculate(struct drm_crtc *crtc, struct drm_crtc_state *crtc_state) { @@ -12560,16 +12589,36 @@ static int skylake_pfiter_calculate(struct drm_crtc *crtc, if (((pipe_config->pipe_scaling_mode != intel_crtc->config->pipe_scaling_mode) || (pipe_config->pipe_src_w != intel_crtc->config->pipe_src_w) || - (pipe_config->pipe_src_h != intel_crtc->config->pipe_src_h)) && + (pipe_config->pipe_src_h != intel_crtc->config->pipe_src_h) || + (pipe_config->pipe_dst_x != intel_crtc->config->pipe_dst_x) || + (pipe_config->pipe_dst_y != intel_crtc->config->pipe_dst_y) || + (pipe_config->pipe_dst_w != intel_crtc->config->pipe_dst_w) || + (pipe_config->pipe_dst_h != intel_crtc->config->pipe_dst_h)) && (!mode_changed)) { pipe_config->update_pipe = true; } if ((mode_changed) || (pipe_config->update_pipe)) { ret = skl_update_scaler_crtc(pipe_config); - if (!ret) - intel_pch_panel_fitting(intel_crtc, pipe_config, - pipe_config->pipe_scaling_mode); + if (!ret) { + if (pipe_config->pipe_scaling_mode == + DRM_MODE_SCALE_CUSTOM) { + intel_gen9_pipe_scale(intel_crtc, pipe_config, + pipe_config->pipe_scaling_mode); + } else { + intel_pch_panel_fitting(intel_crtc, + pipe_config, + pipe_config->pipe_scaling_mode); + pipe_config->pipe_dst_x = + (pipe_config->pch_pfit.pos >> 16); + pipe_config->pipe_dst_y = + (pipe_config->pch_pfit.pos & 0xffff); + pipe_config->pipe_dst_w = + (pipe_config->pch_pfit.size >> 16); + pipe_config->pipe_dst_h = + (pipe_config->pch_pfit.size & 0xffff); + } + } } return ret; } @@ -13045,6 +13094,10 @@ intel_modeset_pipe_config(struct drm_crtc *crtc, pipe_config->output_types |= 1 << encoder->type; } + pipe_config->pipe_dst_w = pipe_config->pipe_src_w; + pipe_config->pipe_dst_h = pipe_config->pipe_src_h; + + encoder_retry: /* Ensure the port clock defaults are reset when retrying. */ pipe_config->port_clock = 0; @@ -14028,11 +14081,20 @@ static int intel_atomic_check(struct drm_device *dev, crtc_state->src_w = adjusted_mode->hdisplay; crtc_state->src_h = adjusted_mode->vdisplay; + crtc_state->dst_w = adjusted_mode->hdisplay; + crtc_state->dst_h = adjusted_mode->vdisplay; + crtc_state->dst_x = 0; + crtc_state->dst_y = 0; + crtc_state->fitting_mode = 0; } pipe_config->pipe_src_w = crtc_state->src_w; pipe_config->pipe_src_h = crtc_state->src_h; pipe_config->pipe_scaling_mode = crtc_state->fitting_mode; + pipe_config->pipe_dst_x = crtc_state->dst_x; + pipe_config->pipe_dst_y = crtc_state->dst_y; + pipe_config->pipe_dst_w = crtc_state->dst_w; + pipe_config->pipe_dst_h = crtc_state->dst_h; crtc_state->pipescaler_changed = false; } diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 189856c..eab05d5 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -533,6 +533,8 @@ struct intel_crtc_state { * and get clipped at the edges. */ int pipe_src_w, pipe_src_h; u32 pipe_scaling_mode; + int pipe_dst_x, pipe_dst_y; + int pipe_dst_w, pipe_dst_h; /* Whether to set up the PCH/FDI. Note that we never allow sharing * between pch encoders and cpu encoders. */ diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h index e245746..99ff789 100644 --- a/include/drm/drm_crtc.h +++ b/include/drm/drm_crtc.h @@ -201,6 +201,7 @@ struct drm_crtc_state { bool pipescaler_changed; u32 src_w, src_h; u32 fitting_mode; + u32 dst_x, dst_y, dst_w, dst_h; }; /** @@ -1950,6 +1951,10 @@ struct drm_mode_config { struct drm_property *prop_pipe_src_w; struct drm_property *prop_pipe_src_h; struct drm_property *prop_fitting_mode; + struct drm_property *prop_pipe_dst_x; + struct drm_property *prop_pipe_dst_y; + struct drm_property *prop_pipe_dst_w; + struct drm_property *prop_pipe_dst_h; /** * @dvi_i_subconnector_property: Optional DVI-I property to diff --git a/include/uapi/drm/drm_mode.h b/include/uapi/drm/drm_mode.h index 49a7265..91bd0f7 100644 --- a/include/uapi/drm/drm_mode.h +++ b/include/uapi/drm/drm_mode.h @@ -91,6 +91,7 @@ extern "C" { #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_CUSTOM 4 /* Custom pipe scaling */ /* Picture aspect ratio options */ #define DRM_MODE_PICTURE_ASPECT_NONE 0 -- 1.9.1 _______________________________________________ Intel-gfx mailing list Intel-gfx@xxxxxxxxxxxxxxxxxxxxx https://lists.freedesktop.org/mailman/listinfo/intel-gfx