On Wed, May 23, 2018 at 12:31:00PM -0700, Jeykumar Sankaran wrote:
Remove dpu crtc custom properties and its handlers.
Signed-off-by: Jeykumar Sankaran jsanka@codeaurora.org
Reviewed-by: Sean Paul seanpaul@chromium.org
drivers/gpu/drm/msm/Makefile | 1 - drivers/gpu/drm/msm/disp/dpu1/dpu_core_perf.c | 28 - drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c | 856 +------------------------- drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.h | 27 +- drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c | 12 - drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ds.c | 149 ----- drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ds.h | 111 ---- drivers/gpu/drm/msm/disp/dpu1/dpu_hw_lm.c | 67 -- drivers/gpu/drm/msm/disp/dpu1/dpu_hw_lm.h | 14 - drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h | 16 - drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c | 71 +-- drivers/gpu/drm/msm/msm_drv.h | 15 - 12 files changed, 11 insertions(+), 1356 deletions(-) delete mode 100644 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ds.c delete mode 100644 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ds.h
diff --git a/drivers/gpu/drm/msm/Makefile b/drivers/gpu/drm/msm/Makefile index 7bc3921..d289503 100644 --- a/drivers/gpu/drm/msm/Makefile +++ b/drivers/gpu/drm/msm/Makefile @@ -57,7 +57,6 @@ msm-y := \ disp/dpu1/dpu_hw_catalog.o \ disp/dpu1/dpu_hw_cdm.o \ disp/dpu1/dpu_hw_ctl.o \
- disp/dpu1/dpu_hw_ds.o \ disp/dpu1/dpu_hw_interrupts.o \ disp/dpu1/dpu_hw_intf.o \ disp/dpu1/dpu_hw_lm.o \
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_core_perf.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_core_perf.c index 981f77f..c4820de 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_core_perf.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_core_perf.c @@ -102,34 +102,6 @@ static void _dpu_core_perf_calc_crtc(struct dpu_kms *kms, dpu_cstate = to_dpu_crtc_state(state); memset(perf, 0, sizeof(struct dpu_core_perf_params));
- perf->bw_ctl[DPU_POWER_HANDLE_DBUS_ID_MNOC] =
dpu_crtc_get_property(dpu_cstate, CRTC_PROP_CORE_AB);
- perf->max_per_pipe_ib[DPU_POWER_HANDLE_DBUS_ID_MNOC] =
dpu_crtc_get_property(dpu_cstate, CRTC_PROP_CORE_IB);
- if (dpu_cstate->bw_split_vote) {
perf->bw_ctl[DPU_POWER_HANDLE_DBUS_ID_LLCC] =
dpu_crtc_get_property(dpu_cstate, CRTC_PROP_LLCC_AB);
perf->max_per_pipe_ib[DPU_POWER_HANDLE_DBUS_ID_LLCC] =
dpu_crtc_get_property(dpu_cstate, CRTC_PROP_LLCC_IB);
perf->bw_ctl[DPU_POWER_HANDLE_DBUS_ID_EBI] =
dpu_crtc_get_property(dpu_cstate, CRTC_PROP_DRAM_AB);
perf->max_per_pipe_ib[DPU_POWER_HANDLE_DBUS_ID_EBI] =
dpu_crtc_get_property(dpu_cstate, CRTC_PROP_DRAM_IB);
- } else {
perf->bw_ctl[DPU_POWER_HANDLE_DBUS_ID_LLCC] =
dpu_crtc_get_property(dpu_cstate, CRTC_PROP_CORE_AB);
perf->max_per_pipe_ib[DPU_POWER_HANDLE_DBUS_ID_LLCC] =
dpu_crtc_get_property(dpu_cstate, CRTC_PROP_CORE_IB);
perf->bw_ctl[DPU_POWER_HANDLE_DBUS_ID_EBI] =
dpu_crtc_get_property(dpu_cstate, CRTC_PROP_CORE_AB);
perf->max_per_pipe_ib[DPU_POWER_HANDLE_DBUS_ID_EBI] =
dpu_crtc_get_property(dpu_cstate, CRTC_PROP_CORE_IB);
- }
- perf->core_clk_rate =
dpu_crtc_get_property(dpu_cstate, CRTC_PROP_CORE_CLK);
- if (!dpu_cstate->bw_control) { for (i = 0; i < DPU_POWER_HANDLE_DBUS_ID_MAX; i++) { perf->bw_ctl[i] = kms->catalog->perf.max_bw_high *
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c index a0b702f..b0a3a30 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c @@ -570,18 +570,6 @@ static void _dpu_crtc_deinit_events(struct dpu_crtc *dpu_crtc) return; }
-/**
- dpu_crtc_destroy_dest_scaler - free memory allocated for scaler lut
- @dpu_crtc: Pointer to dpu crtc
- */
-static void _dpu_crtc_destroy_dest_scaler(struct dpu_crtc *dpu_crtc) -{
- if (!dpu_crtc)
return;
- kfree(dpu_crtc->scl3_lut_cfg);
-}
static void dpu_crtc_destroy(struct drm_crtc *crtc) { struct dpu_crtc *dpu_crtc = to_dpu_crtc(crtc); @@ -594,7 +582,6 @@ static void dpu_crtc_destroy(struct drm_crtc *crtc) if (dpu_crtc->blob_info) drm_property_blob_put(dpu_crtc->blob_info); msm_property_destroy(&dpu_crtc->property_info);
_dpu_crtc_destroy_dest_scaler(dpu_crtc);
_dpu_crtc_deinit_events(dpu_crtc);
@@ -679,71 +666,6 @@ static void _dpu_crtc_setup_blend_cfg(struct dpu_crtc_mixer *mixer, format->alpha_enable, fg_alpha, bg_alpha, blend_op); }
-static void _dpu_crtc_setup_dim_layer_cfg(struct drm_crtc *crtc,
struct dpu_crtc *dpu_crtc, struct dpu_crtc_mixer *mixer,
struct dpu_hw_dim_layer *dim_layer)
-{
- struct dpu_crtc_state *cstate;
- struct dpu_hw_mixer *lm;
- struct dpu_hw_dim_layer split_dim_layer;
- int i;
- if (!dim_layer->rect.w || !dim_layer->rect.h) {
DPU_DEBUG("empty dim_layer\n");
return;
- }
- cstate = to_dpu_crtc_state(crtc->state);
- DPU_DEBUG("dim_layer - flags:%d, stage:%d\n",
dim_layer->flags, dim_layer->stage);
- split_dim_layer.stage = dim_layer->stage;
- split_dim_layer.color_fill = dim_layer->color_fill;
- /*
* traverse through the layer mixers attached to crtc and find the
* intersecting dim layer rect in each LM and program accordingly.
*/
- for (i = 0; i < dpu_crtc->num_mixers; i++) {
split_dim_layer.flags = dim_layer->flags;
dpu_kms_rect_intersect(&cstate->lm_bounds[i], &dim_layer->rect,
&split_dim_layer.rect);
if (dpu_kms_rect_is_null(&split_dim_layer.rect)) {
/*
* no extra programming required for non-intersecting
* layer mixers with INCLUSIVE dim layer
*/
if (split_dim_layer.flags & DPU_DRM_DIM_LAYER_INCLUSIVE)
continue;
/*
* program the other non-intersecting layer mixers with
* INCLUSIVE dim layer of full size for uniformity
* with EXCLUSIVE dim layer config.
*/
split_dim_layer.flags &= ~DPU_DRM_DIM_LAYER_EXCLUSIVE;
split_dim_layer.flags |= DPU_DRM_DIM_LAYER_INCLUSIVE;
memcpy(&split_dim_layer.rect, &cstate->lm_bounds[i],
sizeof(split_dim_layer.rect));
} else {
split_dim_layer.rect.x =
split_dim_layer.rect.x -
cstate->lm_bounds[i].x;
}
DPU_DEBUG("split_dim_layer - LM:%d, rect:{%d,%d,%d,%d}}\n",
i, split_dim_layer.rect.x, split_dim_layer.rect.y,
split_dim_layer.rect.w, split_dim_layer.rect.h);
lm = mixer[i].hw_lm;
mixer[i].mixer_op_mode |= 1 << split_dim_layer.stage;
lm->ops.setup_dim_layer(lm, &split_dim_layer);
- }
-}
static void _dpu_crtc_program_lm_output_roi(struct drm_crtc *crtc) { struct dpu_crtc *dpu_crtc; @@ -787,7 +709,6 @@ static void _dpu_crtc_blend_setup_mixer(struct drm_crtc *crtc, u32 flush_mask; uint32_t stage_idx, lm_idx; int zpos_cnt[DPU_STAGE_MAX + 1] = { 0 };
int i; bool bg_alpha_enable = false;
if (!dpu_crtc || !mixer) {
@@ -863,13 +784,6 @@ static void _dpu_crtc_blend_setup_mixer(struct drm_crtc *crtc, } }
- if (lm && lm->ops.setup_dim_layer) {
cstate = to_dpu_crtc_state(crtc->state);
for (i = 0; i < cstate->num_dim_layers; i++)
_dpu_crtc_setup_dim_layer_cfg(crtc, dpu_crtc,
mixer, &cstate->dim_layer[i]);
- }
- _dpu_crtc_program_lm_output_roi(crtc);
}
@@ -911,11 +825,6 @@ static void _dpu_crtc_blend_setup(struct drm_crtc *crtc) if (mixer[i].hw_ctl->ops.clear_all_blendstages) mixer[i].hw_ctl->ops.clear_all_blendstages( mixer[i].hw_ctl);
/* clear dim_layer settings */
lm = mixer[i].hw_lm;
if (lm->ops.clear_dim_layer)
lm->ops.clear_dim_layer(lm);
}
/* initialize stage cfg */
@@ -947,163 +856,6 @@ static void _dpu_crtc_blend_setup(struct drm_crtc *crtc) }
/**
- _dpu_crtc_setup_scaler3_lut - Set up scaler lut
- LUTs are configured only once during boot
- @dpu_crtc: Pointer to dpu crtc
- @cstate: Pointer to dpu crtc state
- */
-static int _dpu_crtc_set_dest_scaler_lut(struct dpu_crtc *dpu_crtc,
struct dpu_crtc_state *cstate, uint32_t lut_idx)
-{
- struct dpu_hw_scaler3_lut_cfg *cfg;
- u32 *lut_data = NULL;
- size_t len = 0;
- int ret = 0;
- if (!dpu_crtc || !cstate || !dpu_crtc->scl3_lut_cfg) {
DPU_ERROR("invalid args\n");
return -EINVAL;
- }
- if (dpu_crtc->scl3_lut_cfg->is_configured) {
DPU_DEBUG("lut already configured\n");
return 0;
- }
- lut_data = msm_property_get_blob(&dpu_crtc->property_info,
&cstate->property_state, &len, lut_idx);
- if (!lut_data || !len) {
DPU_ERROR("lut(%d): no data, len(%zu)\n", lut_idx, len);
return -ENODATA;
- }
- cfg = dpu_crtc->scl3_lut_cfg;
- switch (lut_idx) {
- case CRTC_PROP_DEST_SCALER_LUT_ED:
cfg->dir_lut = lut_data;
cfg->dir_len = len;
break;
- case CRTC_PROP_DEST_SCALER_LUT_CIR:
cfg->cir_lut = lut_data;
cfg->cir_len = len;
break;
- case CRTC_PROP_DEST_SCALER_LUT_SEP:
cfg->sep_lut = lut_data;
cfg->sep_len = len;
break;
- default:
ret = -EINVAL;
DPU_ERROR("invalid LUT index = %d", lut_idx);
break;
- }
- if (cfg->dir_lut && cfg->cir_lut && cfg->sep_lut)
cfg->is_configured = true;
- return ret;
-}
-/**
- _dpu_crtc_dest_scaler_setup - Set up dest scaler block
- @crtc: Pointer to drm crtc
- */
-static void _dpu_crtc_dest_scaler_setup(struct drm_crtc *crtc) -{
- struct dpu_crtc *dpu_crtc;
- struct dpu_crtc_state *cstate;
- struct dpu_hw_mixer *hw_lm;
- struct dpu_hw_ctl *hw_ctl;
- struct dpu_hw_ds *hw_ds;
- struct dpu_hw_ds_cfg *cfg;
- struct dpu_kms *kms;
- u32 flush_mask = 0, op_mode = 0;
- u32 lm_idx = 0, num_mixers = 0;
- int i, count = 0;
- if (!crtc)
return;
- dpu_crtc = to_dpu_crtc(crtc);
- cstate = to_dpu_crtc_state(crtc->state);
- kms = _dpu_crtc_get_kms(crtc);
- num_mixers = dpu_crtc->num_mixers;
- DPU_DEBUG("crtc%d\n", crtc->base.id);
- if (!cstate->ds_dirty) {
DPU_DEBUG("no change in settings, skip commit\n");
- } else if (!kms || !kms->catalog) {
DPU_ERROR("invalid parameters\n");
- } else if (!kms->catalog->mdp[0].has_dest_scaler) {
DPU_DEBUG("dest scaler feature not supported\n");
- } else if (num_mixers > CRTC_DUAL_MIXERS) {
DPU_ERROR("invalid number mixers: %d\n", num_mixers);
- } else if (!dpu_crtc->scl3_lut_cfg->is_configured) {
DPU_DEBUG("no LUT data available\n");
- } else {
count = cstate->num_ds_enabled ? cstate->num_ds : num_mixers;
for (i = 0; i < count; i++) {
cfg = &cstate->ds_cfg[i];
if (!cfg->flags)
continue;
lm_idx = cfg->ndx;
hw_lm = dpu_crtc->mixers[lm_idx].hw_lm;
hw_ctl = dpu_crtc->mixers[lm_idx].hw_ctl;
hw_ds = dpu_crtc->mixers[lm_idx].hw_ds;
/* Setup op mode - Dual/single */
if (cfg->flags & DPU_DRM_DESTSCALER_ENABLE)
op_mode |= BIT(hw_ds->idx - DS_0);
if ((i == count-1) && hw_ds->ops.setup_opmode) {
op_mode |= (cstate->num_ds_enabled ==
CRTC_DUAL_MIXERS) ?
DPU_DS_OP_MODE_DUAL : 0;
hw_ds->ops.setup_opmode(hw_ds, op_mode);
DPU_EVT32(DRMID(crtc), op_mode);
}
/* Setup scaler */
if ((cfg->flags & DPU_DRM_DESTSCALER_SCALE_UPDATE) ||
(cfg->flags &
DPU_DRM_DESTSCALER_ENHANCER_UPDATE)) {
if (hw_ds->ops.setup_scaler)
hw_ds->ops.setup_scaler(hw_ds,
cfg->scl3_cfg,
dpu_crtc->scl3_lut_cfg);
/**
* Clear the flags as the block doesn't have to
* be programmed in each commit if no updates
*/
cfg->flags &= ~DPU_DRM_DESTSCALER_SCALE_UPDATE;
cfg->flags &=
~DPU_DRM_DESTSCALER_ENHANCER_UPDATE;
}
/*
* Dest scaler shares the flush bit of the LM in control
*/
if (cfg->set_lm_flush && hw_lm && hw_ctl &&
hw_ctl->ops.get_bitmask_mixer) {
flush_mask = hw_ctl->ops.get_bitmask_mixer(
hw_ctl, hw_lm->idx);
DPU_DEBUG("Set lm[%d] flush = %d",
hw_lm->idx, flush_mask);
hw_ctl->ops.update_pending_flush(hw_ctl,
flush_mask);
}
cfg->set_lm_flush = false;
}
cstate->ds_dirty = false;
- }
-}
-/**
- _dpu_crtc_complete_flip - signal pending page_flip events
- Any pending vblank events are added to the vblank_event_list
- so that the next vblank interrupt shall signal them.
@@ -1361,448 +1113,6 @@ void dpu_crtc_complete_commit(struct drm_crtc *crtc, DPU_EVT32_VERBOSE(DRMID(crtc)); }
-/* _dpu_crtc_set_idle_timeout - update idle timeout wait duration */ -static void _dpu_crtc_set_idle_timeout(struct drm_crtc *crtc, u64 val) -{
- struct drm_encoder *encoder;
- if (!crtc) {
DPU_ERROR("invalid crtc\n");
return;
- }
- drm_for_each_encoder(encoder, crtc->dev) {
if (encoder->crtc != crtc)
continue;
dpu_encoder_set_idle_timeout(encoder, (u32) val);
- }
-}
-/**
- _dpu_crtc_set_dim_layer_v1 - copy dim layer settings from userspace
- @cstate: Pointer to dpu crtc state
- @user_ptr: User ptr for dpu_drm_dim_layer_v1 struct
- */
-static void _dpu_crtc_set_dim_layer_v1(struct dpu_crtc_state *cstate,
void __user *usr_ptr)
-{
- struct dpu_drm_dim_layer_v1 dim_layer_v1;
- struct dpu_drm_dim_layer_cfg *user_cfg;
- struct dpu_hw_dim_layer *dim_layer;
- u32 count, i;
- if (!cstate) {
DPU_ERROR("invalid cstate\n");
return;
- }
- dim_layer = cstate->dim_layer;
- if (!usr_ptr) {
DPU_DEBUG("dim_layer data removed\n");
return;
- }
- if (copy_from_user(&dim_layer_v1, usr_ptr, sizeof(dim_layer_v1))) {
DPU_ERROR("failed to copy dim_layer data\n");
return;
- }
- count = dim_layer_v1.num_layers;
- if (count > DPU_MAX_DIM_LAYERS) {
DPU_ERROR("invalid number of dim_layers:%d", count);
return;
- }
- /* populate from user space */
- cstate->num_dim_layers = count;
- for (i = 0; i < count; i++) {
user_cfg = &dim_layer_v1.layer_cfg[i];
dim_layer[i].flags = user_cfg->flags;
dim_layer[i].stage = user_cfg->stage + DPU_STAGE_0;
dim_layer[i].rect.x = user_cfg->rect.x1;
dim_layer[i].rect.y = user_cfg->rect.y1;
dim_layer[i].rect.w = user_cfg->rect.x2 - user_cfg->rect.x1;
dim_layer[i].rect.h = user_cfg->rect.y2 - user_cfg->rect.y1;
dim_layer[i].color_fill = (struct dpu_mdss_color) {
user_cfg->color_fill.color_0,
user_cfg->color_fill.color_1,
user_cfg->color_fill.color_2,
user_cfg->color_fill.color_3,
};
DPU_DEBUG("dim_layer[%d] - flags:%d, stage:%d\n",
i, dim_layer[i].flags, dim_layer[i].stage);
DPU_DEBUG(" rect:{%d,%d,%d,%d}, color:{%d,%d,%d,%d}\n",
dim_layer[i].rect.x, dim_layer[i].rect.y,
dim_layer[i].rect.w, dim_layer[i].rect.h,
dim_layer[i].color_fill.color_0,
dim_layer[i].color_fill.color_1,
dim_layer[i].color_fill.color_2,
dim_layer[i].color_fill.color_3);
- }
-}
-/**
- _dpu_crtc_dest_scaler_init - allocate memory for scaler lut
- @dpu_crtc : Pointer to dpu crtc
- @catalog : Pointer to mdss catalog info
- */
-static void _dpu_crtc_dest_scaler_init(struct dpu_crtc *dpu_crtc,
struct dpu_mdss_cfg *catalog)
-{
- if (!dpu_crtc || !catalog)
return;
- if (!catalog->mdp[0].has_dest_scaler) {
DPU_DEBUG("dest scaler feature not supported\n");
return;
- }
- dpu_crtc->scl3_lut_cfg = kzalloc(sizeof(struct dpu_hw_scaler3_lut_cfg),
GFP_KERNEL);
- if (!dpu_crtc->scl3_lut_cfg)
DPU_ERROR("failed to create scale LUT for dest scaler");
-}
-/**
- _dpu_crtc_set_dest_scaler - copy dest scaler settings from userspace
- @dpu_crtc : Pointer to dpu crtc
- @cstate : Pointer to dpu crtc state
- @usr_ptr: User ptr for dpu_drm_dest_scaler_data struct
- */
-static int _dpu_crtc_set_dest_scaler(struct dpu_crtc *dpu_crtc,
struct dpu_crtc_state *cstate,
void __user *usr_ptr)
-{
- struct dpu_drm_dest_scaler_data ds_data;
- struct dpu_drm_dest_scaler_cfg *ds_cfg_usr;
- struct dpu_drm_scaler_v2 scaler_v2;
- void __user *scaler_v2_usr;
- int i, count, ret = 0;
- if (!dpu_crtc || !cstate) {
DPU_ERROR("invalid dpu_crtc/state\n");
return -EINVAL;
- }
- DPU_DEBUG("crtc %s\n", dpu_crtc->name);
- cstate->num_ds = 0;
- cstate->ds_dirty = false;
- if (!usr_ptr) {
DPU_DEBUG("ds data removed\n");
return 0;
- }
- if (copy_from_user(&ds_data, usr_ptr, sizeof(ds_data))) {
DPU_ERROR("failed to copy dest scaler data from user\n");
return -EINVAL;
- }
- count = ds_data.num_dest_scaler;
- if (!dpu_crtc->num_mixers || count > dpu_crtc->num_mixers ||
(count && (count != dpu_crtc->num_mixers) &&
!(ds_data.ds_cfg[0].flags & DPU_DRM_DESTSCALER_PU_ENABLE))) {
DPU_ERROR("invalid config:num ds(%d), mixers(%d),flags(%d)\n",
count, dpu_crtc->num_mixers, ds_data.ds_cfg[0].flags);
return -EINVAL;
- }
- /* Populate from user space */
- for (i = 0; i < count; i++) {
ds_cfg_usr = &ds_data.ds_cfg[i];
cstate->ds_cfg[i].ndx = ds_cfg_usr->index;
cstate->ds_cfg[i].flags = ds_cfg_usr->flags;
cstate->ds_cfg[i].lm_width = ds_cfg_usr->lm_width;
cstate->ds_cfg[i].lm_height = ds_cfg_usr->lm_height;
cstate->ds_cfg[i].scl3_cfg = NULL;
if (ds_cfg_usr->scaler_cfg) {
scaler_v2_usr =
(void __user *)((uintptr_t)ds_cfg_usr->scaler_cfg);
memset(&scaler_v2, 0, sizeof(scaler_v2));
cstate->ds_cfg[i].scl3_cfg =
kzalloc(sizeof(struct dpu_hw_scaler3_cfg),
GFP_KERNEL);
if (!cstate->ds_cfg[i].scl3_cfg) {
ret = -ENOMEM;
goto err;
}
if (copy_from_user(&scaler_v2, scaler_v2_usr,
sizeof(scaler_v2))) {
DPU_ERROR("scale data:copy from user failed\n");
ret = -EINVAL;
goto err;
}
dpu_set_scaler_v2(cstate->ds_cfg[i].scl3_cfg,
&scaler_v2);
DPU_DEBUG("en(%d)dir(%d)de(%d) src(%dx%d) dst(%dx%d)\n",
scaler_v2.enable, scaler_v2.dir_en,
scaler_v2.de.enable, scaler_v2.src_width[0],
scaler_v2.src_height[0], scaler_v2.dst_width,
scaler_v2.dst_height);
DPU_EVT32_VERBOSE(DRMID(&dpu_crtc->base),
scaler_v2.enable, scaler_v2.dir_en,
scaler_v2.de.enable, scaler_v2.src_width[0],
scaler_v2.src_height[0], scaler_v2.dst_width,
scaler_v2.dst_height);
}
DPU_DEBUG("ds cfg[%d]-ndx(%d) flags(%d) lm(%dx%d)\n",
i, ds_cfg_usr->index, ds_cfg_usr->flags,
ds_cfg_usr->lm_width, ds_cfg_usr->lm_height);
DPU_EVT32_VERBOSE(DRMID(&dpu_crtc->base), i, ds_cfg_usr->index,
ds_cfg_usr->flags, ds_cfg_usr->lm_width,
ds_cfg_usr->lm_height);
- }
- cstate->num_ds = count;
- cstate->ds_dirty = true;
- return 0;
-err:
- for (; i >= 0; i--)
kfree(cstate->ds_cfg[i].scl3_cfg);
- return ret;
-}
-/**
- _dpu_crtc_check_dest_scaler_data - validate the dest scaler data
- @crtc : Pointer to drm crtc
- @state : Pointer to drm crtc state
- */
-static int _dpu_crtc_check_dest_scaler_data(struct drm_crtc *crtc,
struct drm_crtc_state *state)
-{
- struct dpu_crtc *dpu_crtc;
- struct dpu_crtc_state *cstate;
- struct drm_display_mode *mode;
- struct dpu_kms *kms;
- struct dpu_hw_ds *hw_ds;
- struct dpu_hw_ds_cfg *cfg;
- u32 i, ret = 0, lm_idx;
- u32 num_ds_enable = 0;
- u32 max_in_width = 0, max_out_width = 0;
- u32 prev_lm_width = 0, prev_lm_height = 0;
- if (!crtc || !state)
return -EINVAL;
- dpu_crtc = to_dpu_crtc(crtc);
- cstate = to_dpu_crtc_state(state);
- kms = _dpu_crtc_get_kms(crtc);
- mode = &state->adjusted_mode;
- DPU_DEBUG("crtc%d\n", crtc->base.id);
- if (!cstate->ds_dirty && !cstate->num_ds_enabled) {
DPU_DEBUG("dest scaler property not set, skip validation\n");
return 0;
- }
- if (!kms || !kms->catalog) {
DPU_ERROR("invalid parameters\n");
return -EINVAL;
- }
- if (!kms->catalog->mdp[0].has_dest_scaler) {
DPU_DEBUG("dest scaler feature not supported\n");
return 0;
- }
- if (!dpu_crtc->num_mixers) {
DPU_ERROR("mixers not allocated\n");
return -EINVAL;
- }
- /**
* Check if sufficient hw resources are
* available as per target caps & topology
*/
- if (dpu_crtc->num_mixers > CRTC_DUAL_MIXERS) {
DPU_ERROR("invalid config: mixers(%d) max(%d)\n",
dpu_crtc->num_mixers, CRTC_DUAL_MIXERS);
ret = -EINVAL;
goto err;
- }
- for (i = 0; i < dpu_crtc->num_mixers; i++) {
if (!dpu_crtc->mixers[i].hw_lm || !dpu_crtc->mixers[i].hw_ds) {
DPU_ERROR("insufficient HW resources allocated\n");
ret = -EINVAL;
goto err;
}
- }
- /**
* Check if DS needs to be enabled or disabled
* In case of enable, validate the data
*/
- if (!cstate->ds_dirty || !cstate->num_ds ||
!(cstate->ds_cfg[0].flags & DPU_DRM_DESTSCALER_ENABLE)) {
DPU_DEBUG("disable dest scaler,dirty(%d)num(%d)flags(%d)\n",
cstate->ds_dirty, cstate->num_ds,
cstate->ds_cfg[0].flags);
goto disable;
- }
- /**
* No of dest scalers shouldn't exceed hw ds block count and
* also, match the num of mixers unless it is partial update
* left only/right only use case - currently PU + DS is not supported
*/
- if (cstate->num_ds > kms->catalog->ds_count ||
((cstate->num_ds != dpu_crtc->num_mixers) &&
!(cstate->ds_cfg[0].flags & DPU_DRM_DESTSCALER_PU_ENABLE))) {
DPU_ERROR("invalid cfg: num_ds(%d), hw_ds_cnt(%d) flags(%d)\n",
cstate->num_ds, kms->catalog->ds_count,
cstate->ds_cfg[0].flags);
ret = -EINVAL;
goto err;
- }
- /* Validate the DS data */
- for (i = 0; i < cstate->num_ds; i++) {
cfg = &cstate->ds_cfg[i];
lm_idx = cfg->ndx;
/**
* Validate against topology
* No of dest scalers should match the num of mixers
* unless it is partial update left only/right only use case
*/
if (lm_idx >= dpu_crtc->num_mixers || (i != lm_idx &&
!(cfg->flags & DPU_DRM_DESTSCALER_PU_ENABLE))) {
DPU_ERROR("invalid user data(%d):idx(%d), flags(%d)\n",
i, lm_idx, cfg->flags);
ret = -EINVAL;
goto err;
}
hw_ds = dpu_crtc->mixers[lm_idx].hw_ds;
if (!max_in_width && !max_out_width) {
max_in_width = hw_ds->scl->top->maxinputwidth;
max_out_width = hw_ds->scl->top->maxoutputwidth;
if (cstate->num_ds == CRTC_DUAL_MIXERS)
max_in_width -= DPU_DS_OVERFETCH_SIZE;
DPU_DEBUG("max DS width [%d,%d] for num_ds = %d\n",
max_in_width, max_out_width, cstate->num_ds);
}
/* Check LM width and height */
if (cfg->lm_width > (mode->hdisplay/dpu_crtc->num_mixers) ||
cfg->lm_height > mode->vdisplay ||
!cfg->lm_width || !cfg->lm_height) {
DPU_ERROR("invalid lm size[%d,%d] display [%d,%d]\n",
cfg->lm_width,
cfg->lm_height,
mode->hdisplay/dpu_crtc->num_mixers,
mode->vdisplay);
ret = -E2BIG;
goto err;
}
if (!prev_lm_width && !prev_lm_height) {
prev_lm_width = cfg->lm_width;
prev_lm_height = cfg->lm_height;
} else {
if (cfg->lm_width != prev_lm_width ||
cfg->lm_height != prev_lm_height) {
DPU_ERROR("lm size:left[%d,%d], right[%d %d]\n",
cfg->lm_width, cfg->lm_height,
prev_lm_width, prev_lm_height);
ret = -EINVAL;
goto err;
}
}
/* Check scaler data */
if (cfg->flags & DPU_DRM_DESTSCALER_SCALE_UPDATE ||
cfg->flags & DPU_DRM_DESTSCALER_ENHANCER_UPDATE) {
if (!cfg->scl3_cfg) {
ret = -EINVAL;
DPU_ERROR("null scale data\n");
goto err;
}
if (cfg->scl3_cfg->src_width[0] > max_in_width ||
cfg->scl3_cfg->dst_width > max_out_width ||
!cfg->scl3_cfg->src_width[0] ||
!cfg->scl3_cfg->dst_width) {
DPU_ERROR("scale width(%d %d) for ds-%d:\n",
cfg->scl3_cfg->src_width[0],
cfg->scl3_cfg->dst_width,
hw_ds->idx - DS_0);
DPU_ERROR("scale_en = %d, DE_en =%d\n",
cfg->scl3_cfg->enable,
cfg->scl3_cfg->de.enable);
cfg->flags &=
~DPU_DRM_DESTSCALER_SCALE_UPDATE;
cfg->flags &=
~DPU_DRM_DESTSCALER_ENHANCER_UPDATE;
ret = -EINVAL;
goto err;
}
}
if (cfg->flags & DPU_DRM_DESTSCALER_ENABLE)
num_ds_enable++;
/**
* Validation successful, indicator for flush to be issued
*/
cfg->set_lm_flush = true;
DPU_DEBUG("ds[%d]: flags = 0x%X\n",
hw_ds->idx - DS_0, cfg->flags);
- }
-disable:
- DPU_DEBUG("dest scaler enable status, old = %d, new = %d",
cstate->num_ds_enabled, num_ds_enable);
- DPU_EVT32(DRMID(crtc), cstate->num_ds_enabled, num_ds_enable,
cstate->ds_dirty);
- if (cstate->num_ds_enabled != num_ds_enable) {
/* Disabling destination scaler */
if (!num_ds_enable) {
for (i = 0; i < dpu_crtc->num_mixers; i++) {
cfg = &cstate->ds_cfg[i];
cfg->ndx = i;
/* Update scaler settings in disable case */
cfg->flags = DPU_DRM_DESTSCALER_SCALE_UPDATE;
cfg->scl3_cfg->enable = 0;
cfg->scl3_cfg->de.enable = 0;
cfg->set_lm_flush = true;
}
}
cstate->num_ds_enabled = num_ds_enable;
cstate->ds_dirty = true;
- }
- return 0;
-err:
- cstate->ds_dirty = false;
- return ret;
-}
static void _dpu_crtc_setup_mixer_for_encoder( struct drm_crtc *crtc, struct drm_encoder *enc) @@ -1813,11 +1123,10 @@ static void _dpu_crtc_setup_mixer_for_encoder( struct dpu_crtc_mixer *mixer; struct dpu_hw_ctl *last_valid_ctl = NULL; int i;
- struct dpu_rm_hw_iter lm_iter, ctl_iter, ds_iter;
struct dpu_rm_hw_iter lm_iter, ctl_iter;
dpu_rm_init_hw_iter(&lm_iter, enc->base.id, DPU_HW_BLK_LM); dpu_rm_init_hw_iter(&ctl_iter, enc->base.id, DPU_HW_BLK_CTL);
dpu_rm_init_hw_iter(&ds_iter, enc->base.id, DPU_HW_BLK_DS);
/* Set up all the mixers and ctls reserved by this encoder */ for (i = dpu_crtc->num_mixers; i < ARRAY_SIZE(dpu_crtc->mixers); i++) {
@@ -1844,10 +1153,6 @@ static void _dpu_crtc_setup_mixer_for_encoder( return; }
/* DS may be null */
(void) dpu_rm_get_hw(rm, &ds_iter);
mixer->hw_ds = (struct dpu_hw_ds *)ds_iter.hw;
mixer->encoder = enc;
dpu_crtc->num_mixers++;
@@ -1855,9 +1160,6 @@ static void _dpu_crtc_setup_mixer_for_encoder( i, mixer->hw_lm->idx - LM_0); DPU_DEBUG("setup mixer %d: ctl %d\n", i, mixer->hw_ctl->idx - CTL_0);
if (mixer->hw_ds)
DPU_DEBUG("setup mixer %d: ds %d\n",
}i, mixer->hw_ds->idx - DS_0);
}
@@ -1973,7 +1275,6 @@ static void dpu_crtc_atomic_begin(struct drm_crtc *crtc, return;
_dpu_crtc_blend_setup(crtc);
_dpu_crtc_dest_scaler_setup(crtc);
/*
- PP_DONE irq is only used by command mode for now.
@@ -2672,13 +1973,6 @@ static int dpu_crtc_atomic_check(struct drm_crtc *crtc,
memset(pipe_staged, 0, sizeof(pipe_staged));
rc = _dpu_crtc_check_dest_scaler_data(crtc, state);
if (rc) {
DPU_ERROR("crtc%d failed dest scaler check %d\n",
crtc->base.id, rc);
goto end;
}
mixer_width = dpu_crtc_get_mixer_width(dpu_crtc, cstate, mode);
_dpu_crtc_setup_lm_bounds(crtc, state);
@@ -2699,19 +1993,6 @@ static int dpu_crtc_atomic_check(struct drm_crtc *crtc, pstates[cnt].stage = pstate->normalized_zpos; pstates[cnt].pipe_id = dpu_plane_pipe(plane);
/* check dim layer stage with every plane */
for (i = 0; i < cstate->num_dim_layers; i++) {
if (cstate->dim_layer[i].stage
== (pstates[cnt].stage + DPU_STAGE_0)) {
DPU_ERROR(
"plane:%d/dim_layer:%i-same stage:%d\n",
plane->base.id, i,
cstate->dim_layer[i].stage);
rc = -EINVAL;
goto end;
}
}
- if (pipe_staged[pstates[cnt].pipe_id]) { multirect_plane[multirect_count].r0 = pipe_staged[pstates[cnt].pipe_id];
@@ -2947,52 +2228,11 @@ static void dpu_crtc_install_properties(struct drm_crtc *crtc, return; }
/* range properties */
msm_property_install_range(&dpu_crtc->property_info,
"core_clk", 0x0, 0, U64_MAX,
dpu_kms->perf.max_core_clk_rate,
CRTC_PROP_CORE_CLK);
msm_property_install_range(&dpu_crtc->property_info,
"core_ab", 0x0, 0, U64_MAX,
catalog->perf.max_bw_high * 1000ULL,
CRTC_PROP_CORE_AB);
msm_property_install_range(&dpu_crtc->property_info,
"core_ib", 0x0, 0, U64_MAX,
catalog->perf.max_bw_high * 1000ULL,
CRTC_PROP_CORE_IB);
msm_property_install_range(&dpu_crtc->property_info,
"llcc_ab", 0x0, 0, U64_MAX,
catalog->perf.max_bw_high * 1000ULL,
CRTC_PROP_LLCC_AB);
msm_property_install_range(&dpu_crtc->property_info,
"llcc_ib", 0x0, 0, U64_MAX,
catalog->perf.max_bw_high * 1000ULL,
CRTC_PROP_LLCC_IB);
msm_property_install_range(&dpu_crtc->property_info,
"dram_ab", 0x0, 0, U64_MAX,
catalog->perf.max_bw_high * 1000ULL,
CRTC_PROP_DRAM_AB);
msm_property_install_range(&dpu_crtc->property_info,
"dram_ib", 0x0, 0, U64_MAX,
catalog->perf.max_bw_high * 1000ULL,
CRTC_PROP_DRAM_IB);
msm_property_install_range(&dpu_crtc->property_info,
"idle_timeout", IDLE_TIMEOUT, 0, U64_MAX, 0,
CRTC_PROP_IDLE_TIMEOUT);
msm_property_install_blob(&dpu_crtc->property_info, "capabilities", DRM_MODE_PROP_IMMUTABLE, CRTC_PROP_INFO);
dpu_kms_info_reset(info);
if (catalog->caps->has_dim_layer) {
msm_property_install_volatile_range(&dpu_crtc->property_info,
"dim_layer_v1", 0x0, 0, ~0, 0, CRTC_PROP_DIM_LAYER_V1);
dpu_kms_info_add_keyint(info, "dim_layer_v1_max_layers",
DPU_MAX_DIM_LAYERS);
}
dpu_kms_info_add_keyint(info, "hw_version", catalog->hwversion); dpu_kms_info_add_keyint(info, "max_linewidth", catalog->caps->max_mixer_width);
@@ -3012,39 +2252,6 @@ static void dpu_crtc_install_properties(struct drm_crtc *crtc, "smart_dma_rev", "smart_dma_v2"); }
- if (catalog->mdp[0].has_dest_scaler) {
dpu_kms_info_add_keyint(info, "has_dest_scaler",
catalog->mdp[0].has_dest_scaler);
dpu_kms_info_add_keyint(info, "dest_scaler_count",
catalog->ds_count);
if (catalog->ds[0].top) {
dpu_kms_info_add_keyint(info,
"max_dest_scaler_input_width",
catalog->ds[0].top->maxinputwidth);
dpu_kms_info_add_keyint(info,
"max_dest_scaler_output_width",
catalog->ds[0].top->maxinputwidth);
dpu_kms_info_add_keyint(info, "max_dest_scale_up",
catalog->ds[0].top->maxupscale);
}
if (catalog->ds[0].features & BIT(DPU_SSPP_SCALER_QSEED3)) {
msm_property_install_volatile_range(
&dpu_crtc->property_info, "dest_scaler",
0x0, 0, ~0, 0, CRTC_PROP_DEST_SCALER);
msm_property_install_blob(&dpu_crtc->property_info,
"ds_lut_ed", 0,
CRTC_PROP_DEST_SCALER_LUT_ED);
msm_property_install_blob(&dpu_crtc->property_info,
"ds_lut_cir", 0,
CRTC_PROP_DEST_SCALER_LUT_CIR);
msm_property_install_blob(&dpu_crtc->property_info,
"ds_lut_sep", 0,
CRTC_PROP_DEST_SCALER_LUT_SEP);
}
- }
- dpu_kms_info_add_keyint(info, "has_src_split", catalog->caps->has_src_split); if (catalog->perf.max_bw_low)
@@ -3113,7 +2320,7 @@ static int dpu_crtc_atomic_set_property(struct drm_crtc *crtc, { struct dpu_crtc *dpu_crtc; struct dpu_crtc_state *cstate;
- int idx, ret = -EINVAL;
int ret = -EINVAL;
if (!crtc || !state || !property) { DPU_ERROR("invalid argument(s)\n");
@@ -3122,45 +2329,8 @@ static int dpu_crtc_atomic_set_property(struct drm_crtc *crtc, cstate = to_dpu_crtc_state(state); ret = msm_property_atomic_set(&dpu_crtc->property_info, &cstate->property_state, property, val);
if (!ret) {
idx = msm_property_index(&dpu_crtc->property_info,
property);
switch (idx) {
case CRTC_PROP_DIM_LAYER_V1:
_dpu_crtc_set_dim_layer_v1(cstate,
u64_to_user_ptr(val));
break;
case CRTC_PROP_DEST_SCALER:
ret = _dpu_crtc_set_dest_scaler(dpu_crtc,
cstate, u64_to_user_ptr(val));
break;
case CRTC_PROP_DEST_SCALER_LUT_ED:
case CRTC_PROP_DEST_SCALER_LUT_CIR:
case CRTC_PROP_DEST_SCALER_LUT_SEP:
ret = _dpu_crtc_set_dest_scaler_lut(dpu_crtc,
cstate, idx);
break;
case CRTC_PROP_CORE_CLK:
case CRTC_PROP_CORE_AB:
case CRTC_PROP_CORE_IB:
cstate->bw_control = true;
break;
case CRTC_PROP_LLCC_AB:
case CRTC_PROP_LLCC_IB:
case CRTC_PROP_DRAM_AB:
case CRTC_PROP_DRAM_IB:
cstate->bw_control = true;
cstate->bw_split_vote = true;
break;
case CRTC_PROP_IDLE_TIMEOUT:
_dpu_crtc_set_idle_timeout(crtc, val);
default:
/* nothing to do */
break;
}
} else {
if (ret) DRM_ERROR("failed to set the property\n");
}
DPU_DEBUG("crtc%d %s[%d] <= 0x%llx ret=%d\n", crtc->base.id, property->name, property->base.id, val, ret);
@@ -3276,23 +2446,6 @@ static int _dpu_debugfs_status_show(struct seq_file *s, void *data)
seq_puts(s, "\n");
- for (i = 0; i < cstate->num_dim_layers; i++) {
struct dpu_hw_dim_layer *dim_layer = &cstate->dim_layer[i];
seq_printf(s, "\tdim_layer:%d] stage:%d flags:%d\n",
i, dim_layer->stage, dim_layer->flags);
seq_printf(s, "\tdst_x:%d dst_y:%d dst_w:%d dst_h:%d\n",
dim_layer->rect.x, dim_layer->rect.y,
dim_layer->rect.w, dim_layer->rect.h);
seq_printf(s,
"\tcolor_0:%d color_1:%d color_2:%d color_3:%d\n",
dim_layer->color_fill.color_0,
dim_layer->color_fill.color_1,
dim_layer->color_fill.color_2,
dim_layer->color_fill.color_3);
seq_puts(s, "\n");
- }
- drm_atomic_crtc_for_each_plane(plane, crtc) { pstate = to_dpu_plane_state(plane->state); state = plane->state;
@@ -3779,9 +2932,6 @@ struct drm_crtc *dpu_crtc_init(struct drm_device *dev, struct drm_plane *plane)
dpu_crtc_install_properties(crtc, kms->catalog);
- /* Init dest scaler */
- _dpu_crtc_dest_scaler_init(dpu_crtc, kms->catalog);
- DPU_DEBUG("%s: successfully initialized crtc\n", dpu_crtc->name); return crtc;
} diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.h index 5f380b8..6628eb3 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.h +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.h @@ -26,7 +26,6 @@ #include "dpu_kms.h" #include "dpu_core_perf.h" #include "dpu_hw_blk.h" -#include "dpu_hw_ds.h"
#define DPU_CRTC_NAME_SIZE 12
@@ -87,7 +86,6 @@ struct dpu_crtc_smmu_state_data {
- struct dpu_crtc_mixer: stores the map for each virtual pipeline in the CRTC
- @hw_lm: LM HW Driver context
- @hw_ctl: CTL Path HW driver context
- @hw_ds: DS HW driver context
- @encoder: Encoder attached to this lm & ctl
- @mixer_op_mode: mixer blending operation mode
- @flush_mask: mixer flush mask for ctl, mixer and pipe
@@ -95,7 +93,6 @@ struct dpu_crtc_smmu_state_data { struct dpu_crtc_mixer { struct dpu_hw_mixer *hw_lm; struct dpu_hw_ctl *hw_ctl;
- struct dpu_hw_ds *hw_ds; struct drm_encoder *encoder; u32 mixer_op_mode; u32 flush_mask;
@@ -314,12 +311,6 @@ struct dpu_crtc_respool {
- @property_state: Local storage for msm_prop properties
- @property_values: Current crtc property values
- @input_fence_timeout_ns : Cached input fence timeout, in ns
- @num_dim_layers: Number of dim layers
- @dim_layer: Dim layer configs
- @num_ds: Number of destination scalers to be configured
- @num_ds_enabled: Number of destination scalers enabled
- @ds_dirty: Boolean to indicate if dirty or not
*/
- @ds_cfg: Destination scaler config
- @new_perf: new performance state being requested
struct dpu_crtc_state { @@ -336,12 +327,6 @@ struct dpu_crtc_state { struct msm_property_state property_state; struct msm_property_value property_values[CRTC_PROP_COUNT]; uint64_t input_fence_timeout_ns;
uint32_t num_dim_layers;
struct dpu_hw_dim_layer dim_layer[DPU_MAX_DIM_LAYERS];
uint32_t num_ds;
uint32_t num_ds_enabled;
bool ds_dirty;
struct dpu_hw_ds_cfg ds_cfg[DPU_MAX_DS_COUNT];
struct dpu_core_perf_params new_perf; struct dpu_crtc_respool rp;
@@ -362,7 +347,6 @@ struct dpu_crtc_state { /**
- dpu_crtc_get_mixer_width - get the mixer width
- Mixer width will be same as panel width(/2 for split)
*/
- unless destination scaler feature is enabled
static inline int dpu_crtc_get_mixer_width(struct dpu_crtc *dpu_crtc, struct dpu_crtc_state *cstate, struct drm_display_mode *mode) @@ -372,10 +356,7 @@ static inline int dpu_crtc_get_mixer_width(struct dpu_crtc *dpu_crtc, if (!dpu_crtc || !cstate || !mode) return 0;
- if (cstate->num_ds_enabled)
mixer_width = cstate->ds_cfg[0].lm_width;
- else
mixer_width = (dpu_crtc->num_mixers == CRTC_DUAL_MIXERS ?
mixer_width = (dpu_crtc->num_mixers == CRTC_DUAL_MIXERS ? mode->hdisplay / CRTC_DUAL_MIXERS : mode->hdisplay);
return mixer_width;
@@ -383,8 +364,7 @@ static inline int dpu_crtc_get_mixer_width(struct dpu_crtc *dpu_crtc,
/**
- dpu_crtc_get_mixer_height - get the mixer height
- Mixer height will be same as panel height unless
- destination scaler feature is enabled
*/
- Mixer height will be same as panel height
static inline int dpu_crtc_get_mixer_height(struct dpu_crtc *dpu_crtc, struct dpu_crtc_state *cstate, struct drm_display_mode *mode) @@ -392,8 +372,7 @@ static inline int dpu_crtc_get_mixer_height(struct dpu_crtc *dpu_crtc, if (!dpu_crtc || !cstate || !mode) return 0;
- return (cstate->num_ds_enabled ?
cstate->ds_cfg[0].lm_height : mode->vdisplay);
- return mode->vdisplay;
}
/** diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c index 77d3571..62660e0 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c @@ -230,18 +230,6 @@ struct dpu_encoder_virt { };
#define to_dpu_encoder_virt(x) container_of(x, struct dpu_encoder_virt, base)
-void dpu_encoder_set_idle_timeout(struct drm_encoder *drm_enc, u32 idle_timeout) -{
- struct dpu_encoder_virt *dpu_enc;
- if (!drm_enc)
return;
- dpu_enc = to_dpu_encoder_virt(drm_enc);
- dpu_enc->idle_timeout = idle_timeout;
-}
static inline int _dpu_encoder_power_enable(struct dpu_encoder_virt *dpu_enc, bool enable) { diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ds.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ds.c deleted file mode 100644 index fad19fb..0000000 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ds.c +++ /dev/null @@ -1,149 +0,0 @@ -/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License version 2 and
- only version 2 as published by the Free Software Foundation.
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
- */
-#include "dpu_hw_ds.h" -#include "dpu_formats.h" -#include "dpu_dbg.h" -#include "dpu_kms.h"
-/* Destination scaler TOP registers */ -#define DEST_SCALER_OP_MODE 0x00 -#define DEST_SCALER_HW_VERSION 0x10
-static void dpu_hw_ds_setup_opmode(struct dpu_hw_ds *hw_ds,
u32 op_mode)
-{
- struct dpu_hw_blk_reg_map *hw = &hw_ds->hw;
- DPU_REG_WRITE(hw, DEST_SCALER_OP_MODE, op_mode);
-}
-static void dpu_hw_ds_setup_scaler3(struct dpu_hw_ds *hw_ds,
void *scaler_cfg, void *scaler_lut_cfg)
-{
- struct dpu_hw_scaler3_cfg *scl3_cfg = scaler_cfg;
- struct dpu_hw_scaler3_lut_cfg *scl3_lut_cfg = scaler_lut_cfg;
- if (!hw_ds || !hw_ds->scl || !scl3_cfg || !scl3_lut_cfg)
return;
- /*
* copy LUT values to scaler structure
*/
- if (scl3_lut_cfg->is_configured) {
scl3_cfg->dir_lut = scl3_lut_cfg->dir_lut;
scl3_cfg->dir_len = scl3_lut_cfg->dir_len;
scl3_cfg->cir_lut = scl3_lut_cfg->cir_lut;
scl3_cfg->cir_len = scl3_lut_cfg->cir_len;
scl3_cfg->sep_lut = scl3_lut_cfg->sep_lut;
scl3_cfg->sep_len = scl3_lut_cfg->sep_len;
- }
- dpu_hw_setup_scaler3(&hw_ds->hw, scl3_cfg,
hw_ds->scl->base,
hw_ds->scl->version,
dpu_get_dpu_format(DRM_FORMAT_XBGR2101010));
-}
-static void _setup_ds_ops(struct dpu_hw_ds_ops *ops, unsigned long features) -{
- ops->setup_opmode = dpu_hw_ds_setup_opmode;
- if (test_bit(DPU_SSPP_SCALER_QSEED3, &features))
ops->setup_scaler = dpu_hw_ds_setup_scaler3;
-}
-static struct dpu_ds_cfg *_ds_offset(enum dpu_ds ds,
struct dpu_mdss_cfg *m,
void __iomem *addr,
struct dpu_hw_blk_reg_map *b)
-{
- int i;
- if (!m || !addr || !b)
return ERR_PTR(-EINVAL);
- for (i = 0; i < m->ds_count; i++) {
if ((ds == m->ds[i].id) &&
(m->ds[i].top)) {
b->base_off = addr;
b->blk_off = m->ds[i].top->base;
b->length = m->ds[i].top->len;
b->hwversion = m->hwversion;
b->log_mask = DPU_DBG_MASK_DS;
return &m->ds[i];
}
- }
- return ERR_PTR(-EINVAL);
-}
-static struct dpu_hw_blk_ops dpu_hw_ops = {
- .start = NULL,
- .stop = NULL,
-};
-struct dpu_hw_ds *dpu_hw_ds_init(enum dpu_ds idx,
void __iomem *addr,
struct dpu_mdss_cfg *m)
-{
- struct dpu_hw_ds *hw_ds;
- struct dpu_ds_cfg *cfg;
- int rc;
- if (!addr || !m)
return ERR_PTR(-EINVAL);
- hw_ds = kzalloc(sizeof(*hw_ds), GFP_KERNEL);
- if (!hw_ds)
return ERR_PTR(-ENOMEM);
- cfg = _ds_offset(idx, m, addr, &hw_ds->hw);
- if (IS_ERR_OR_NULL(cfg)) {
DPU_ERROR("failed to get ds cfg\n");
kfree(hw_ds);
return ERR_PTR(-EINVAL);
- }
- /* Assign ops */
- hw_ds->idx = idx;
- hw_ds->scl = cfg;
- _setup_ds_ops(&hw_ds->ops, hw_ds->scl->features);
- rc = dpu_hw_blk_init(&hw_ds->base, DPU_HW_BLK_DS, idx, &dpu_hw_ops);
- if (rc) {
DPU_ERROR("failed to init hw blk %d\n", rc);
goto blk_init_error;
- }
- if (cfg->len) {
dpu_dbg_reg_register_dump_range(DPU_DBG_NAME, cfg->name,
hw_ds->hw.blk_off + cfg->base,
hw_ds->hw.blk_off + cfg->base + cfg->len,
hw_ds->hw.xin_id);
- }
- return hw_ds;
-blk_init_error:
- kzfree(hw_ds);
- return ERR_PTR(rc);
-}
-void dpu_hw_ds_destroy(struct dpu_hw_ds *hw_ds) -{
- if (hw_ds)
dpu_hw_blk_destroy(&hw_ds->base);
- kfree(hw_ds);
-} diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ds.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ds.h deleted file mode 100644 index 2455920..0000000 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ds.h +++ /dev/null @@ -1,111 +0,0 @@ -/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License version 2 and
- only version 2 as published by the Free Software Foundation.
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
- */
-#ifndef _DPU_HW_DS_H -#define _DPU_HW_DS_H
-#include "dpu_hw_mdss.h" -#include "dpu_hw_util.h" -#include "dpu_hw_catalog.h" -#include "dpu_hw_blk.h"
-struct dpu_hw_ds;
-/* Destination Scaler DUAL mode overfetch pixel count */ -#define DPU_DS_OVERFETCH_SIZE 5
-/* Destination scaler DUAL mode operation bit */ -#define DPU_DS_OP_MODE_DUAL BIT(16)
-/* struct dpu_hw_ds_cfg - destination scaler config
- @ndx : DS selection index
- @flags : Flag to switch between mode for DS
- @lm_width : Layer mixer width configuration
- @lm_heigh : Layer mixer height configuration
- @set_lm_flush : LM flush bit
- @scl3_cfg : Pointer to dpu_hw_scaler3_cfg.
- */
-struct dpu_hw_ds_cfg {
- u32 ndx;
- int flags;
- u32 lm_width;
- u32 lm_height;
- bool set_lm_flush;
- struct dpu_hw_scaler3_cfg *scl3_cfg;
-};
-/**
- struct dpu_hw_ds_ops - interface to the destination scaler
- hardware driver functions
- Caller must call the init function to get the ds context for each ds
- Assumption is these functions will be called after clocks are enabled
- */
-struct dpu_hw_ds_ops {
- /**
* setup_opmode - destination scaler op mode setup
* @hw_ds : Pointer to ds context
* @op_mode : Op mode configuration
*/
- void (*setup_opmode)(struct dpu_hw_ds *hw_ds,
u32 op_mode);
- /**
* setup_scaler - destination scaler block setup
* @hw_ds : Pointer to ds context
* @scaler_cfg : Pointer to scaler data
* @scaler_lut_cfg : Pointer to scaler lut
*/
- void (*setup_scaler)(struct dpu_hw_ds *hw_ds,
void *scaler_cfg,
void *scaler_lut_cfg);
-};
-/**
- struct dpu_hw_ds - destination scaler description
- @base : Hardware block base structure
- @hw : Block hardware details
- @idx : Destination scaler index
- @scl : Pointer to
- scaler offset relative to top offset
- capabilities
- @ops : Pointer to operations for this DS
- */
-struct dpu_hw_ds {
- struct dpu_hw_blk base;
- struct dpu_hw_blk_reg_map hw;
- enum dpu_ds idx;
- const struct dpu_ds_cfg *scl;
- struct dpu_hw_ds_ops ops;
-};
-/**
- dpu_hw_ds_init - initializes the destination scaler
- hw driver object and should be called once before
- accessing every destination scaler
- @idx : DS index for which driver object is required
- @addr: Mapped register io address of MDP
- @m : MDSS catalog information
- @Return: pointer to structure or ERR_PTR
- */
-struct dpu_hw_ds *dpu_hw_ds_init(enum dpu_ds idx,
void __iomem *addr,
struct dpu_mdss_cfg *m);
-/**
- dpu_hw_ds_destroy - destroys destination scaler
- driver context
- @hw_ds: Pointer to DS context
- */
-void dpu_hw_ds_destroy(struct dpu_hw_ds *hw_ds);
-#endif /*_DPU_HW_DS_H */ diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_lm.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_lm.c index 75a30db..830b69e 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_lm.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_lm.c @@ -172,68 +172,6 @@ static void dpu_hw_lm_gc(struct dpu_hw_mixer *mixer, { }
-static void dpu_hw_lm_clear_dim_layer(struct dpu_hw_mixer *ctx) -{
- struct dpu_hw_blk_reg_map *c = &ctx->hw;
- const struct dpu_lm_sub_blks *sblk = ctx->cap->sblk;
- int stage_off, i;
- u32 reset = BIT(16), val;
- reset = ~reset;
- for (i = DPU_STAGE_0; i < sblk->maxblendstages; i++) {
stage_off = _stage_offset(ctx, i);
if (WARN_ON(stage_off < 0))
return;
/*
* read the existing blendn_op register and clear only DIM layer
* bit (color_fill bit)
*/
val = DPU_REG_READ(c, LM_BLEND0_OP + stage_off);
val &= reset;
DPU_REG_WRITE(c, LM_BLEND0_OP + stage_off, val);
- }
-}
-static void dpu_hw_lm_setup_dim_layer(struct dpu_hw_mixer *ctx,
struct dpu_hw_dim_layer *dim_layer)
-{
- struct dpu_hw_blk_reg_map *c = &ctx->hw;
- int stage_off;
- u32 val = 0, alpha = 0;
- stage_off = _stage_offset(ctx, dim_layer->stage);
- if (stage_off < 0) {
DPU_ERROR("invalid stage_off:%d for dim layer\n", stage_off);
return;
- }
- alpha = dim_layer->color_fill.color_3 & 0xFF;
- val = ((dim_layer->color_fill.color_1 << 2) & 0xFFF) << 16 |
((dim_layer->color_fill.color_0 << 2) & 0xFFF);
- DPU_REG_WRITE(c, LM_FG_COLOR_FILL_COLOR_0 + stage_off, val);
- val = (alpha << 4) << 16 |
((dim_layer->color_fill.color_2 << 2) & 0xFFF);
- DPU_REG_WRITE(c, LM_FG_COLOR_FILL_COLOR_1 + stage_off, val);
- val = dim_layer->rect.h << 16 | dim_layer->rect.w;
- DPU_REG_WRITE(c, LM_FG_COLOR_FILL_SIZE + stage_off, val);
- val = dim_layer->rect.y << 16 | dim_layer->rect.x;
- DPU_REG_WRITE(c, LM_FG_COLOR_FILL_XY + stage_off, val);
- val = BIT(16); /* enable dim layer */
- val |= DPU_BLEND_FG_ALPHA_FG_CONST | DPU_BLEND_BG_ALPHA_BG_CONST;
- if (dim_layer->flags & DPU_DRM_DIM_LAYER_EXCLUSIVE)
val |= BIT(17);
- else
val &= ~BIT(17);
- DPU_REG_WRITE(c, LM_BLEND0_OP + stage_off, val);
- val = (alpha << 16) | (0xff - alpha);
- DPU_REG_WRITE(c, LM_BLEND0_CONST_ALPHA + stage_off, val);
-}
static void dpu_hw_lm_setup_misr(struct dpu_hw_mixer *ctx, bool enable, u32 frame_count) { @@ -272,11 +210,6 @@ static void _setup_mixer_ops(struct dpu_mdss_cfg *m, ops->setup_gc = dpu_hw_lm_gc; ops->setup_misr = dpu_hw_lm_setup_misr; ops->collect_misr = dpu_hw_lm_collect_misr;
- if (test_bit(DPU_DIM_LAYER, &features)) {
ops->setup_dim_layer = dpu_hw_lm_setup_dim_layer;
ops->clear_dim_layer = dpu_hw_lm_clear_dim_layer;
- }
};
static struct dpu_hw_blk_ops dpu_hw_ops = { diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_lm.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_lm.h index ef22c86..e29e5da 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_lm.h +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_lm.h @@ -67,20 +67,6 @@ struct dpu_hw_lm_ops { void (*setup_gc)(struct dpu_hw_mixer *mixer, void *cfg);
- /**
* setup_dim_layer: configure dim layer settings
* @ctx: Pointer to layer mixer context
* @dim_layer: dim layer configs
*/
- void (*setup_dim_layer)(struct dpu_hw_mixer *ctx,
struct dpu_hw_dim_layer *dim_layer);
- /**
* clear_dim_layer: clear dim layer settings
* @ctx: Pointer to layer mixer context
*/
- void (*clear_dim_layer)(struct dpu_hw_mixer *ctx);
- /* setup_misr: enables/disables MISR in HW register */ void (*setup_misr)(struct dpu_hw_mixer *ctx, bool enable, u32 frame_count);
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h index fcd164f..836ff9e 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h @@ -99,7 +99,6 @@ enum dpu_hw_blk_type { DPU_HW_BLK_TOP = 0, DPU_HW_BLK_SSPP, DPU_HW_BLK_LM,
- DPU_HW_BLK_DS, DPU_HW_BLK_CTL, DPU_HW_BLK_CDM, DPU_HW_BLK_PINGPONG,
@@ -469,20 +468,5 @@ struct dpu_mdss_color { #define DPU_DBG_MASK_TOP (1 << 8) #define DPU_DBG_MASK_VBIF (1 << 9) #define DPU_DBG_MASK_ROT (1 << 10) -#define DPU_DBG_MASK_DS (1 << 11)
-/**
- struct dpu_hw_dim_layer: dim layer configs
- @flags: Flag to represent INCLUSIVE/EXCLUSIVE
- @stage: Blending stage of dim layer
- @color_fill: Color fill to be used for the layer
- @rect: Dim layer coordinates
- */
-struct dpu_hw_dim_layer {
- uint32_t flags;
- uint32_t stage;
- struct dpu_mdss_color color_fill;
- struct dpu_rect rect;
-};
#endif /* _DPU_HW_MDSS_H */ diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c index f467bf1..0af2996 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c @@ -17,7 +17,6 @@ #include "dpu_hw_lm.h" #include "dpu_hw_ctl.h" #include "dpu_hw_cdm.h" -#include "dpu_hw_ds.h" #include "dpu_hw_pingpong.h" #include "dpu_hw_intf.h" #include "dpu_hw_wb.h" @@ -235,9 +234,6 @@ static void _dpu_rm_hw_destroy(enum dpu_hw_blk_type type, void *hw) case DPU_HW_BLK_LM: dpu_hw_lm_destroy(hw); break;
- case DPU_HW_BLK_DS:
dpu_hw_ds_destroy(hw);
case DPU_HW_BLK_CTL: dpu_hw_ctl_destroy(hw); break;break;
@@ -317,9 +313,6 @@ static int _dpu_rm_hw_blk_create( case DPU_HW_BLK_LM: hw = dpu_hw_lm_init(id, mmio, cat); break;
- case DPU_HW_BLK_DS:
hw = dpu_hw_ds_init(id, mmio, cat);
case DPU_HW_BLK_CTL: hw = dpu_hw_ctl_init(id, mmio, cat); break;break;
@@ -427,17 +420,6 @@ int dpu_rm_init(struct dpu_rm *rm, } }
- if (cat->mdp[0].has_dest_scaler) {
for (i = 0; i < cat->ds_count; i++) {
rc = _dpu_rm_hw_blk_create(rm, cat, mmio, DPU_HW_BLK_DS,
cat->ds[i].id, &cat->ds[i]);
if (rc) {
DPU_ERROR("failed: ds hw not available\n");
goto fail;
}
}
- }
- for (i = 0; i < cat->pingpong_count; i++) { rc = _dpu_rm_hw_blk_create(rm, cat, mmio, DPU_HW_BLK_PINGPONG, cat->pingpong[i].id, &cat->pingpong[i]);
@@ -516,20 +498,16 @@ static bool _dpu_rm_check_lm_and_get_connected_blks( struct dpu_rm_rsvp *rsvp, struct dpu_rm_requirements *reqs, struct dpu_rm_hw_blk *lm,
struct dpu_rm_hw_blk **pp, struct dpu_rm_hw_blk *primary_lm)struct dpu_rm_hw_blk **ds,
{ const struct dpu_lm_cfg *lm_cfg = to_dpu_hw_mixer(lm->hw)->cap; struct dpu_rm_hw_iter iter;
bool is_valid_ds;
*ds = NULL; *pp = NULL;
DPU_DEBUG("check lm %d ds %d pp %d\n",
lm_cfg->id,
lm_cfg->ds, lm_cfg->pingpong);
DPU_DEBUG("check lm %d pp %d\n",
lm_cfg->id, lm_cfg->pingpong);
/* Check if this layer mixer is a peer of the proposed primary LM */ if (primary_lm) {
@@ -543,43 +521,12 @@ static bool _dpu_rm_check_lm_and_get_connected_blks( } }
is_valid_ds = (lm_cfg->ds != DS_MAX) ? true : false;
if (RM_RQ_DS(reqs) && !is_valid_ds) {
DPU_DEBUG("fail:lm(%d)req_ds(%d)ds(%d)\n",
lm_cfg->id, (bool)(RM_RQ_DS(reqs)), lm_cfg->ds);
return false;
}
/* Already reserved? */ if (RESERVED_BY_OTHER(lm, rsvp)) { DPU_DEBUG("lm %d already reserved\n", lm_cfg->id); return false; }
if (lm_cfg->ds != DS_MAX) {
dpu_rm_init_hw_iter(&iter, 0, DPU_HW_BLK_DS);
while (_dpu_rm_get_hw_locked(rm, &iter)) {
if (iter.blk->id == lm_cfg->ds) {
*ds = iter.blk;
break;
}
}
if (!*ds) {
DPU_DEBUG("lm %d failed to retrieve ds %d\n", lm->id,
lm_cfg->ds);
return false;
}
if (RESERVED_BY_OTHER(*ds, rsvp)) {
DPU_DEBUG("lm %d ds %d already reserved\n",
lm->id, (*ds)->id);
return false;
}
}
dpu_rm_init_hw_iter(&iter, 0, DPU_HW_BLK_PINGPONG); while (_dpu_rm_get_hw_locked(rm, &iter)) { if (iter.blk->id == lm_cfg->pingpong) {
@@ -596,7 +543,6 @@ static bool _dpu_rm_check_lm_and_get_connected_blks( if (RESERVED_BY_OTHER(*pp, rsvp)) { DPU_DEBUG("lm %d pp %d already reserved\n", lm->id, (*pp)->id);
return false; }*ds = NULL;
@@ -610,7 +556,6 @@ static int _dpu_rm_reserve_lms(
{ struct dpu_rm_hw_blk *lm[MAX_BLOCKS];
- struct dpu_rm_hw_blk *ds[MAX_BLOCKS]; struct dpu_rm_hw_blk *pp[MAX_BLOCKS]; struct dpu_rm_hw_iter iter_i, iter_j; int lm_count = 0;
@@ -626,14 +571,13 @@ static int _dpu_rm_reserve_lms( while (lm_count != reqs->topology->num_lm && _dpu_rm_get_hw_locked(rm, &iter_i)) { memset(&lm, 0, sizeof(lm));
memset(&ds, 0, sizeof(ds));
memset(&pp, 0, sizeof(pp));
lm_count = 0; lm[lm_count] = iter_i.blk;
if (!_dpu_rm_check_lm_and_get_connected_blks(
rm, rsvp, reqs, lm[lm_count], &ds[lm_count],
rm, rsvp, reqs, lm[lm_count], &pp[lm_count], NULL)) continue;
@@ -649,8 +593,7 @@ static int _dpu_rm_reserve_lms(
if (!_dpu_rm_check_lm_and_get_connected_blks( rm, rsvp, reqs, iter_j.blk,
&ds[lm_count], &pp[lm_count],
iter_i.blk))
&pp[lm_count], iter_i.blk)) continue; lm[lm_count] = iter_j.blk;
@@ -670,11 +613,7 @@ static int _dpu_rm_reserve_lms( lm[i]->rsvp_nxt = rsvp; pp[i]->rsvp_nxt = rsvp;
if (ds[i])
ds[i]->rsvp_nxt = rsvp;
DPU_EVT32(lm[i]->type, rsvp->enc_id, lm[i]->id, pp[i]->id,
ds[i] ? ds[i]->id : 0);
DPU_EVT32(lm[i]->type, rsvp->enc_id, lm[i]->id, pp[i]->id);
}
return rc;
diff --git a/drivers/gpu/drm/msm/msm_drv.h b/drivers/gpu/drm/msm/msm_drv.h index 5baff27..8e80b4b 100644 --- a/drivers/gpu/drm/msm/msm_drv.h +++ b/drivers/gpu/drm/msm/msm_drv.h @@ -89,25 +89,10 @@ enum msm_mdp_plane_property {
enum msm_mdp_crtc_property { CRTC_PROP_INFO,
CRTC_PROP_DEST_SCALER_LUT_ED,
CRTC_PROP_DEST_SCALER_LUT_CIR,
CRTC_PROP_DEST_SCALER_LUT_SEP,
/* # of blob properties */ CRTC_PROP_BLOBCOUNT,
/* range properties */
CRTC_PROP_DIM_LAYER_V1 = CRTC_PROP_BLOBCOUNT,
CRTC_PROP_CORE_CLK,
CRTC_PROP_CORE_AB,
CRTC_PROP_CORE_IB,
CRTC_PROP_LLCC_AB,
CRTC_PROP_LLCC_IB,
CRTC_PROP_DRAM_AB,
CRTC_PROP_DRAM_IB,
CRTC_PROP_IDLE_TIMEOUT,
CRTC_PROP_DEST_SCALER,
/* total # of properties */ CRTC_PROP_COUNT
};
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, a Linux Foundation Collaborative Project