@@ -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
@@ -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;
}
@@ -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;
}
@@ -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. */
@@ -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
@@ -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
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@intel.com> --- 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(-)