|
@@ -604,59 +604,102 @@ static void _sde_enc_phys_wb_detect_cwb(struct sde_encoder_phys *phys_enc,
|
|
|
|
|
|
static int _sde_enc_phys_wb_validate_cwb(struct sde_encoder_phys *phys_enc,
|
|
static int _sde_enc_phys_wb_validate_cwb(struct sde_encoder_phys *phys_enc,
|
|
struct drm_crtc_state *crtc_state,
|
|
struct drm_crtc_state *crtc_state,
|
|
- struct drm_connector_state *conn_state)
|
|
|
|
|
|
+ struct drm_connector_state *conn_state)
|
|
{
|
|
{
|
|
|
|
+ struct drm_framebuffer *fb;
|
|
struct sde_crtc_state *cstate = to_sde_crtc_state(crtc_state);
|
|
struct sde_crtc_state *cstate = to_sde_crtc_state(crtc_state);
|
|
|
|
+ const struct drm_display_mode *mode = &crtc_state->mode;
|
|
struct sde_rect wb_roi = {0,};
|
|
struct sde_rect wb_roi = {0,};
|
|
struct sde_rect pu_roi = {0,};
|
|
struct sde_rect pu_roi = {0,};
|
|
|
|
+ int out_width = 0, out_height = 0;
|
|
|
|
+ int ds_srcw = 0, ds_srch = 0, ds_outw = 0, ds_outh = 0;
|
|
int data_pt;
|
|
int data_pt;
|
|
- int ds_outw = 0;
|
|
|
|
- int ds_outh = 0;
|
|
|
|
int ds_in_use = false;
|
|
int ds_in_use = false;
|
|
int i = 0;
|
|
int i = 0;
|
|
int ret = 0;
|
|
int ret = 0;
|
|
|
|
|
|
- if (!phys_enc->in_clone_mode) {
|
|
|
|
- SDE_DEBUG("not in CWB mode. early return\n");
|
|
|
|
- goto exit;
|
|
|
|
|
|
+ fb = sde_wb_connector_state_get_output_fb(conn_state);
|
|
|
|
+ if (!fb) {
|
|
|
|
+ SDE_DEBUG("no output framebuffer\n");
|
|
|
|
+ return 0;
|
|
}
|
|
}
|
|
|
|
|
|
ret = sde_wb_connector_state_get_output_roi(conn_state, &wb_roi);
|
|
ret = sde_wb_connector_state_get_output_roi(conn_state, &wb_roi);
|
|
if (ret) {
|
|
if (ret) {
|
|
SDE_ERROR("failed to get roi %d\n", ret);
|
|
SDE_ERROR("failed to get roi %d\n", ret);
|
|
- goto exit;
|
|
|
|
|
|
+ return ret;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if (!wb_roi.w || !wb_roi.h) {
|
|
|
|
+ SDE_ERROR("cwb roi is not set wxh:%dx%d\n", wb_roi.w, wb_roi.h);
|
|
|
|
+ return -EINVAL;
|
|
}
|
|
}
|
|
|
|
|
|
data_pt = sde_crtc_get_property(cstate, CRTC_PROP_CAPTURE_OUTPUT);
|
|
data_pt = sde_crtc_get_property(cstate, CRTC_PROP_CAPTURE_OUTPUT);
|
|
|
|
|
|
/* compute cumulative ds output dimensions if in use */
|
|
/* compute cumulative ds output dimensions if in use */
|
|
- for (i = 0; i < cstate->num_ds; i++)
|
|
|
|
|
|
+ for (i = 0; i < cstate->num_ds; i++) {
|
|
if (cstate->ds_cfg[i].scl3_cfg.enable) {
|
|
if (cstate->ds_cfg[i].scl3_cfg.enable) {
|
|
ds_in_use = true;
|
|
ds_in_use = true;
|
|
ds_outw += cstate->ds_cfg[i].scl3_cfg.dst_width;
|
|
ds_outw += cstate->ds_cfg[i].scl3_cfg.dst_width;
|
|
ds_outh = cstate->ds_cfg[i].scl3_cfg.dst_height;
|
|
ds_outh = cstate->ds_cfg[i].scl3_cfg.dst_height;
|
|
|
|
+ ds_srcw += cstate->ds_cfg[i].lm_width;
|
|
|
|
+ ds_srch = cstate->ds_cfg[i].lm_height;
|
|
}
|
|
}
|
|
|
|
+ }
|
|
|
|
|
|
- /* if ds in use check wb roi against ds output dimensions */
|
|
|
|
- if ((data_pt == CAPTURE_DSPP_OUT) && ds_in_use &&
|
|
|
|
- ((wb_roi.w != ds_outw) || (wb_roi.h != ds_outh))) {
|
|
|
|
- SDE_ERROR("invalid wb roi with dest scalar [%dx%d vs %dx%d]\n",
|
|
|
|
- wb_roi.w, wb_roi.h, ds_outw, ds_outh);
|
|
|
|
- ret = -EINVAL;
|
|
|
|
- goto exit;
|
|
|
|
|
|
+ if ((ds_in_use && (!ds_outw || !ds_outh || !ds_srcw || !ds_srch))) {
|
|
|
|
+ SDE_ERROR("invalid ds cfg src:%dx%d dst:%dx%d\n",
|
|
|
|
+ ds_srcw, ds_srch, ds_outw, ds_outh);
|
|
|
|
+ return -EINVAL;
|
|
}
|
|
}
|
|
|
|
|
|
- /* validate conn roi against pu rect */
|
|
|
|
|
|
+ /* 1) No DS case: same restrictions for LM & DSSPP tap point
|
|
|
|
+ * a) wb-roi should be inside FB
|
|
|
|
+ * b) mode resolution & wb-roi should be same
|
|
|
|
+ * 2) With DS case: restrictions would change based on tap point
|
|
|
|
+ * 2.1) LM Tap Point:
|
|
|
|
+ * a) wb-roi should be inside FB
|
|
|
|
+ * b) wb-roi should be same as crtc-LM bounds
|
|
|
|
+ * 2.2) DSPP Tap point: same as No DS case
|
|
|
|
+ * a) wb-roi should be inside FB
|
|
|
|
+ * b) mode resolution & wb-roi should be same
|
|
|
|
+ */
|
|
|
|
+ if (ds_in_use && data_pt == CAPTURE_DSPP_OUT) {
|
|
|
|
+ out_width = ds_outw;
|
|
|
|
+ out_height = ds_outh;
|
|
|
|
+ } else if (ds_in_use) { /* LM tap point */
|
|
|
|
+ out_width = ds_srcw;
|
|
|
|
+ out_height = ds_srch;
|
|
|
|
+ } else {
|
|
|
|
+ out_width = mode->hdisplay;
|
|
|
|
+ out_height = mode->vdisplay;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if ((wb_roi.w != out_width) || (wb_roi.h != out_height)) {
|
|
|
|
+ SDE_ERROR("invalid wb roi[%dx%d] with ds_use:%d out[%dx%d]\n",
|
|
|
|
+ wb_roi.w, wb_roi.h, out_width, out_height);
|
|
|
|
+ return -EINVAL;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if (((wb_roi.x + wb_roi.w) > fb->width) ||
|
|
|
|
+ ((wb_roi.y + wb_roi.h) > fb->height)) {
|
|
|
|
+ SDE_ERROR("invalid wb roi[%d,%d,%d,%d] fb[%dx%d]\n",
|
|
|
|
+ wb_roi.x, wb_roi.y, wb_roi.w, wb_roi.h,
|
|
|
|
+ fb->width, fb->height);
|
|
|
|
+ return -EINVAL;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /* validate wb roi against pu rect */
|
|
if (cstate->user_roi_list.num_rects) {
|
|
if (cstate->user_roi_list.num_rects) {
|
|
sde_kms_rect_merge_rectangles(&cstate->user_roi_list, &pu_roi);
|
|
sde_kms_rect_merge_rectangles(&cstate->user_roi_list, &pu_roi);
|
|
if (wb_roi.w != pu_roi.w || wb_roi.h != pu_roi.h) {
|
|
if (wb_roi.w != pu_roi.w || wb_roi.h != pu_roi.h) {
|
|
SDE_ERROR("invalid wb roi with pu [%dx%d vs %dx%d]\n",
|
|
SDE_ERROR("invalid wb roi with pu [%dx%d vs %dx%d]\n",
|
|
wb_roi.w, wb_roi.h, pu_roi.w, pu_roi.h);
|
|
wb_roi.w, wb_roi.h, pu_roi.w, pu_roi.h);
|
|
- ret = -EINVAL;
|
|
|
|
- goto exit;
|
|
|
|
|
|
+ return -EINVAL;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
-exit:
|
|
|
|
|
|
+
|
|
return ret;
|
|
return ret;
|
|
}
|
|
}
|
|
|
|
|
|
@@ -742,6 +785,16 @@ static int sde_encoder_phys_wb_atomic_check(
|
|
if (SDE_FORMAT_IS_YUV(fmt) != !!phys_enc->hw_cdm)
|
|
if (SDE_FORMAT_IS_YUV(fmt) != !!phys_enc->hw_cdm)
|
|
crtc_state->mode_changed = true;
|
|
crtc_state->mode_changed = true;
|
|
|
|
|
|
|
|
+ /* if in clone mode, return after cwb validation */
|
|
|
|
+ if (phys_enc->in_clone_mode) {
|
|
|
|
+ rc = _sde_enc_phys_wb_validate_cwb(phys_enc, crtc_state,
|
|
|
|
+ conn_state);
|
|
|
|
+ if (rc)
|
|
|
|
+ SDE_ERROR("failed in cwb validation %d\n", rc);
|
|
|
|
+
|
|
|
|
+ return rc;
|
|
|
|
+ }
|
|
|
|
+
|
|
if (wb_roi.w && wb_roi.h) {
|
|
if (wb_roi.w && wb_roi.h) {
|
|
if (wb_roi.w != mode->hdisplay) {
|
|
if (wb_roi.w != mode->hdisplay) {
|
|
SDE_ERROR("invalid roi w=%d, mode w=%d\n", wb_roi.w,
|
|
SDE_ERROR("invalid roi w=%d, mode w=%d\n", wb_roi.w,
|
|
@@ -786,12 +839,6 @@ static int sde_encoder_phys_wb_atomic_check(
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
- rc = _sde_enc_phys_wb_validate_cwb(phys_enc, crtc_state, conn_state);
|
|
|
|
- if (rc) {
|
|
|
|
- SDE_ERROR("failed in cwb validation %d\n", rc);
|
|
|
|
- return rc;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
return rc;
|
|
return rc;
|
|
}
|
|
}
|
|
|
|
|