Loading drivers/gpu/drm/msm/sde/sde_color_processing.c +140 −46 Original line number Diff line number Diff line Loading @@ -22,7 +22,7 @@ #include "sde_hw_dspp.h" #include "sde_hw_lm.h" struct sde_color_process_node { struct sde_cp_node { u32 property_id; u32 prop_flags; u32 feature; Loading @@ -39,7 +39,7 @@ struct sde_color_process_node { struct sde_cp_prop_attach { struct drm_crtc *crtc; struct drm_property *prop; struct sde_color_process_node *prop_node; struct sde_cp_node *prop_node; const struct sde_pp_blk *pp_blk; u32 feature; void *ops; Loading @@ -62,6 +62,7 @@ enum { SDE_CP_CRTC_DSPP_DITHER, SDE_CP_CRTC_DSPP_HIST, SDE_CP_CRTC_DSPP_AD, SDE_CP_CRTC_DSPP_VLUT, SDE_CP_CRTC_DSPP_MAX, /* DSPP features end */ Loading @@ -84,8 +85,43 @@ enum { (p)->val = val; \ } while (0) static int sde_cp_disable_crtc_blob_property( struct sde_color_process_node *prop_node) static void sde_cp_get_hw_payload(struct sde_cp_node *prop_node, struct sde_hw_cp_cfg *hw_cfg, bool *feature_enabled) { struct drm_property_blob *blob = NULL; memset(hw_cfg, 0, sizeof(*hw_cfg)); *feature_enabled = false; blob = prop_node->blob_ptr; if (prop_node->prop_flags & DRM_MODE_PROP_BLOB) { if (blob) { hw_cfg->len = blob->length; hw_cfg->payload = blob->data; *feature_enabled = true; } } else if (prop_node->prop_flags & DRM_MODE_PROP_RANGE) { /* Check if local blob is Set */ if (!blob) { hw_cfg->len = sizeof(prop_node->prop_val); if (prop_node->prop_val) hw_cfg->payload = &prop_node->prop_val; } else { hw_cfg->len = (prop_node->prop_val) ? blob->length : 0; hw_cfg->payload = (prop_node->prop_val) ? blob->data : NULL; } if (prop_node->prop_val) *feature_enabled = true; } else { DRM_ERROR("property type is not supported\n"); } } static int sde_cp_disable_crtc_blob_property(struct sde_cp_node *prop_node) { struct drm_property_blob *blob = prop_node->blob_ptr; Loading @@ -96,23 +132,84 @@ static int sde_cp_disable_crtc_blob_property( return 0; } static int sde_cp_disable_crtc_property(struct drm_crtc *crtc, struct drm_property *property, struct sde_color_process_node *prop_node) static int sde_cp_create_local_blob(struct drm_crtc *crtc, u32 feature, int len) { int ret = -EINVAL; bool found = false; struct sde_cp_node *prop_node = NULL; struct drm_property_blob *blob_ptr; struct sde_crtc *sde_crtc = to_sde_crtc(crtc); list_for_each_entry(prop_node, &sde_crtc->feature_list, feature_list) { if (prop_node->feature == feature) { found = true; break; } } if (!found || prop_node->prop_flags & DRM_MODE_PROP_BLOB) { DRM_ERROR("local blob create failed prop found %d flags %d\n", found, prop_node->prop_flags); return ret; } blob_ptr = drm_property_create_blob(crtc->dev, len, NULL); ret = (IS_ERR_OR_NULL(blob_ptr)) ? PTR_ERR(blob_ptr) : 0; if (!ret) prop_node->blob_ptr = blob_ptr; return ret; } static void sde_cp_destroy_local_blob(struct sde_cp_node *prop_node) { if (!(prop_node->prop_flags & DRM_MODE_PROP_BLOB) && prop_node->blob_ptr) drm_property_unreference_blob(prop_node->blob_ptr); } static int sde_cp_handle_range_property(struct sde_cp_node *prop_node, uint64_t val) { int ret = 0; struct drm_property_blob *blob_ptr = prop_node->blob_ptr; if (property->flags & DRM_MODE_PROP_BLOB) { ret = sde_cp_disable_crtc_blob_property(prop_node); } else if (property->flags & DRM_MODE_PROP_RANGE) { if (!blob_ptr) { prop_node->prop_val = val; return 0; } if (!val) { prop_node->prop_val = 0; ret = 0; return 0; } ret = copy_from_user(blob_ptr->data, (void *)val, blob_ptr->length); if (ret) { DRM_ERROR("failed to get the property info ret %d", ret); ret = -EFAULT; } else { prop_node->prop_val = val; } return ret; } static int sde_cp_disable_crtc_property(struct drm_crtc *crtc, struct drm_property *property, struct sde_cp_node *prop_node) { int ret = -EINVAL; if (property->flags & DRM_MODE_PROP_BLOB) ret = sde_cp_disable_crtc_blob_property(prop_node); else if (property->flags & DRM_MODE_PROP_RANGE) ret = sde_cp_handle_range_property(prop_node, 0); return ret; } static int sde_cp_enable_crtc_blob_property(struct drm_crtc *crtc, struct sde_color_process_node *prop_node, struct sde_cp_node *prop_node, uint64_t val) { struct drm_property_blob *blob = NULL; Loading @@ -136,17 +233,15 @@ static int sde_cp_enable_crtc_blob_property(struct drm_crtc *crtc, static int sde_cp_enable_crtc_property(struct drm_crtc *crtc, struct drm_property *property, struct sde_color_process_node *prop_node, struct sde_cp_node *prop_node, uint64_t val) { int ret = -EINVAL; if (property->flags & DRM_MODE_PROP_BLOB) ret = sde_cp_enable_crtc_blob_property(crtc, prop_node, val); else if (property->flags & DRM_MODE_PROP_RANGE) { ret = 0; prop_node->prop_val = val; } else if (property->flags & DRM_MODE_PROP_RANGE) ret = sde_cp_handle_range_property(prop_node, val); return ret; } Loading Loading @@ -215,7 +310,7 @@ static void sde_cp_crtc_install_immutable_property(struct drm_crtc *crtc, u32 feature) { struct drm_property *prop; struct sde_color_process_node *prop_node = NULL; struct sde_cp_node *prop_node = NULL; struct msm_drm_private *priv; struct sde_cp_prop_attach prop_attach; uint64_t val = 0; Loading Loading @@ -257,7 +352,7 @@ static void sde_cp_crtc_install_range_property(struct drm_crtc *crtc, uint64_t val) { struct drm_property *prop; struct sde_color_process_node *prop_node = NULL; struct sde_cp_node *prop_node = NULL; struct msm_drm_private *priv; struct sde_cp_prop_attach prop_attach; Loading Loading @@ -295,7 +390,7 @@ static void sde_cp_crtc_create_blob_property(struct drm_crtc *crtc, char *name, u32 feature, void *ops) { struct drm_property *prop; struct sde_color_process_node *prop_node = NULL; struct sde_cp_node *prop_node = NULL; struct msm_drm_private *priv; uint64_t val = 0; struct sde_cp_prop_attach prop_attach; Loading Loading @@ -331,15 +426,14 @@ static void sde_cp_crtc_create_blob_property(struct drm_crtc *crtc, char *name, } static void sde_cp_crtc_setfeature(struct sde_color_process_node *prop_node, static void sde_cp_crtc_setfeature(struct sde_cp_node *prop_node, struct sde_crtc *sde_crtc) { u32 num_mixers = sde_crtc->num_mixers; uint64_t val = 0; struct drm_property_blob *blob = NULL; struct sde_hw_cp_cfg hw_cfg; u32 num_mixers = sde_crtc->num_mixers; int i = 0; bool is_dspp = true; bool feature_enabled = false; if (!prop_node->dspp_feature_op && !prop_node->lm_feature_op) { DRM_ERROR("ops not set for dspp/lm\n"); Loading @@ -347,21 +441,7 @@ static void sde_cp_crtc_setfeature(struct sde_color_process_node *prop_node, } is_dspp = !prop_node->lm_feature_op; memset(&hw_cfg, 0, sizeof(hw_cfg)); if (prop_node->prop_flags & DRM_MODE_PROP_BLOB) { blob = prop_node->blob_ptr; if (blob) { hw_cfg.len = blob->length; hw_cfg.payload = blob->data; } } else if (prop_node->prop_flags & DRM_MODE_PROP_RANGE) { val = prop_node->prop_val; hw_cfg.len = sizeof(prop_node->prop_val); hw_cfg.payload = &prop_node->prop_val; } else { DRM_ERROR("property type is not supported\n"); return; } sde_cp_get_hw_payload(prop_node, &hw_cfg, &feature_enabled); for (i = 0; i < num_mixers; i++) { if (is_dspp) { Loading @@ -377,7 +457,7 @@ static void sde_cp_crtc_setfeature(struct sde_color_process_node *prop_node, } } if (blob || val) { if (feature_enabled) { DRM_DEBUG_DRIVER("Add feature to active list %d\n", prop_node->property_id); list_add_tail(&prop_node->active_list, &sde_crtc->active_list); Loading @@ -394,7 +474,7 @@ void sde_cp_crtc_apply_properties(struct drm_crtc *crtc) { struct sde_crtc *sde_crtc = NULL; bool set_dspp_flush = false, set_lm_flush = false; struct sde_color_process_node *prop_node = NULL, *n = NULL; struct sde_cp_node *prop_node = NULL, *n = NULL; struct sde_hw_ctl *ctl; uint32_t flush_mask = 0; u32 num_mixers = 0, i = 0; Loading Loading @@ -549,6 +629,19 @@ void sde_cp_crtc_install_properties(struct drm_crtc *crtc) sde_cp_crtc_install_immutable_property(crtc, feature_name, SDE_CP_CRTC_DSPP_AD); break; case SDE_DSPP_VLUT: snprintf(feature_name, ARRAY_SIZE(feature_name), "%s%d", "SDE_DSPP_VLUT_V", (hw_dspp->cap->sblk->vlut.version >> 16)); sde_cp_crtc_install_range_property(crtc, feature_name, &hw_dspp->cap->sblk->vlut, SDE_CP_CRTC_DSPP_VLUT, hw_dspp->ops.setup_vlut, 0, U64_MAX, 0); /* TODO: if blob creation fails destroy the property */ sde_cp_create_local_blob(crtc, SDE_CP_CRTC_DSPP_VLUT, sizeof(struct drm_msm_pa_vlut)); break; default: break; } Loading Loading @@ -585,7 +678,7 @@ int sde_cp_crtc_set_property(struct drm_crtc *crtc, struct drm_property *property, uint64_t val) { struct sde_color_process_node *prop_node = NULL; struct sde_cp_node *prop_node = NULL; struct sde_crtc *sde_crtc = NULL; int ret = 0; u8 found = 0; Loading Loading @@ -632,7 +725,7 @@ int sde_cp_crtc_set_property(struct drm_crtc *crtc, int sde_cp_crtc_get_property(struct drm_crtc *crtc, struct drm_property *property, uint64_t *val) { struct sde_color_process_node *prop_node = NULL; struct sde_cp_node *prop_node = NULL; struct sde_crtc *sde_crtc = NULL; int ret = -EINVAL; Loading Loading @@ -661,7 +754,7 @@ int sde_cp_crtc_get_property(struct drm_crtc *crtc, void sde_cp_crtc_destroy_properties(struct drm_crtc *crtc) { struct sde_crtc *sde_crtc = NULL; struct sde_color_process_node *prop_node = NULL, *n = NULL; struct sde_cp_node *prop_node = NULL, *n = NULL; if (!crtc) { DRM_ERROR("invalid crtc %pK\n", crtc); Loading @@ -683,6 +776,7 @@ void sde_cp_crtc_destroy_properties(struct drm_crtc *crtc) list_del_init(&prop_node->active_list); list_del_init(&prop_node->dirty_list); list_del_init(&prop_node->feature_list); sde_cp_destroy_local_blob(prop_node); kfree(prop_node); } Loading @@ -694,7 +788,7 @@ void sde_cp_crtc_destroy_properties(struct drm_crtc *crtc) void sde_cp_crtc_suspend(struct drm_crtc *crtc) { struct sde_crtc *sde_crtc = NULL; struct sde_color_process_node *prop_node = NULL, *n = NULL; struct sde_cp_node *prop_node = NULL, *n = NULL; if (!crtc) { DRM_ERROR("crtc %pK\n", crtc); Loading drivers/gpu/drm/msm/sde/sde_hw_catalog.h +5 −1 Original line number Diff line number Diff line Loading @@ -127,7 +127,9 @@ enum { * @SDE_DSPP_SIXZONE Six zone block * @SDE_DSPP_GAMUT Gamut bloc * @SDE_DSPP_DITHER Dither block * @SDE_DSPP_HIST Histogram bloc * @SDE_DSPP_HIST Histogram block * @SDE_DSPP_VLUT PA VLUT block * @SDE_DSPP_AD AD block * @SDE_DSPP_MAX maximum value */ enum { Loading @@ -140,6 +142,7 @@ enum { SDE_DSPP_GAMUT, SDE_DSPP_DITHER, SDE_DSPP_HIST, SDE_DSPP_VLUT, SDE_DSPP_AD, SDE_DSPP_MAX }; Loading Loading @@ -358,6 +361,7 @@ struct sde_dspp_sub_blks { struct sde_pp_blk dither; struct sde_pp_blk hist; struct sde_pp_blk ad; struct sde_pp_blk vlut; }; struct sde_pingpong_sub_blks { Loading drivers/gpu/drm/msm/sde/sde_hw_catalog_8996.c +3 −1 Original line number Diff line number Diff line Loading @@ -41,7 +41,7 @@ (BIT(SDE_DSPP_IGC) | BIT(SDE_DSPP_PCC) |\ BIT(SDE_DSPP_GC) | BIT(SDE_DSPP_HSIC) | BIT(SDE_DSPP_GAMUT) |\ BIT(SDE_DSPP_DITHER) | BIT(SDE_DSPP_HIST) | BIT(SDE_DSPP_MEMCOLOR) |\ BIT(SDE_DSPP_SIXZONE) | BIT(SDE_DSPP_AD)) BIT(SDE_DSPP_SIXZONE) | BIT(SDE_DSPP_AD) | BIT(SDE_DSPP_VLUT)) #define PINGPONG_17X_MASK \ (BIT(SDE_PINGPONG_TE) | BIT(SDE_PINGPONG_DSC)) Loading Loading @@ -362,6 +362,8 @@ static inline int set_cfg_1xx_init(struct sde_mdss_cfg *cfg) .version = SDE_COLOR_PROCESS_VER(0x1, 0x0)}, .ad = {.id = SDE_DSPP_AD, .base = 0x00, .len = 0x0, .version = SDE_COLOR_PROCESS_VER(0x3, 0x0)}, .vlut = {.id = SDE_DSPP_VLUT, .base = 0x1400, .len = 0x0, .version = SDE_COLOR_PROCESS_VER(0x1, 0x0)}, }; /* PINGPONG capability */ Loading drivers/gpu/drm/msm/sde/sde_hw_dspp.c +70 −0 Original line number Diff line number Diff line Loading @@ -28,6 +28,28 @@ #define PCC_CONST_COEFF_MASK 0xFFFF #define PCC_COEFF_MASK 0x3FFFF #define REG_MASK(n) ((BIT(n)) - 1) #define PA_SZ_VAL_MASK BIT(31) #define PA_SZ_SAT_MASK BIT(30) #define PA_SZ_HUE_MASK BIT(29) #define PA_CONT_MASK BIT(28) #define PA_VAL_MASK BIT(27) #define PA_SAT_MASK BIT(26) #define PA_HUE_MASK BIT(25) #define PA_LUTV_MASK BIT(19) #define PA_HIST_MASK BIT(16) #define PA_MEM_SKY_MASK BIT(7) #define PA_MEM_FOL_MASK BIT(6) #define PA_MEM_SKIN_MASK BIT(5) #define PA_ENABLE BIT(20) #define PA_ENABLE_MASK (PA_SZ_VAL_MASK | PA_SZ_SAT_MASK | PA_SZ_HUE_MASK \ | PA_CONT_MASK | PA_VAL_MASK | PA_SAT_MASK \ | PA_HUE_MASK | PA_LUTV_MASK | PA_HIST_MASK \ | PA_MEM_SKY_MASK | PA_MEM_FOL_MASK | PA_MEM_SKIN_MASK) #define PA_LUT_SWAP_OFF 0x234 static struct sde_dspp_cfg *_dspp_offset(enum sde_dspp dspp, struct sde_mdss_cfg *m, void __iomem *addr, Loading Loading @@ -68,6 +90,49 @@ void sde_dspp_setup_hue(struct sde_hw_dspp *dspp, void *cfg) { } void sde_dspp_setup_vlut(struct sde_hw_dspp *ctx, void *cfg) { struct drm_msm_pa_vlut *payload = NULL; struct sde_hw_cp_cfg *hw_cfg = cfg; u32 op_mode, tmp; int i = 0, j = 0; if (!hw_cfg || (hw_cfg->payload && hw_cfg->len != sizeof(struct drm_msm_pa_vlut))) { DRM_ERROR("hw %pK payload %pK payloadsize %d exp size %zd\n", hw_cfg, ((hw_cfg) ? hw_cfg->payload : NULL), ((hw_cfg) ? hw_cfg->len : 0), sizeof(struct drm_msm_pa_vlut)); return; } op_mode = SDE_REG_READ(&ctx->hw, 0); if (!hw_cfg->payload) { DRM_DEBUG_DRIVER("Disable vlut feature\n"); /** * In the PA_VLUT disable case, remove PA_VLUT enable bit(19) * first, then check whether any other PA sub-features are * enabled or not. If none of the sub-features are enabled, * remove the PA global enable bit(20). */ op_mode &= ~((u32)PA_LUTV_MASK); if (!(op_mode & PA_ENABLE_MASK)) op_mode &= ~((u32)PA_ENABLE); SDE_REG_WRITE(&ctx->hw, 0, op_mode); return; } payload = hw_cfg->payload; DRM_DEBUG_DRIVER("Enable vlut feature flags %llx\n", payload->flags); for (i = 0, j = 0; i < ARRAY_SIZE(payload->val); i += 2, j += 4) { tmp = (payload->val[i] & REG_MASK(10)) | ((payload->val[i + 1] & REG_MASK(10)) << 16); SDE_REG_WRITE(&ctx->hw, (ctx->cap->sblk->vlut.base + j), tmp); } SDE_REG_WRITE(&ctx->hw, PA_LUT_SWAP_OFF, 1); op_mode |= PA_ENABLE | PA_LUTV_MASK; SDE_REG_WRITE(&ctx->hw, 0, op_mode); } void sde_dspp_setup_pcc(struct sde_hw_dspp *ctx, void *cfg) { struct sde_hw_cp_cfg *hw_cfg = cfg; Loading Loading @@ -194,6 +259,11 @@ static void _setup_dspp_ops(struct sde_hw_dspp *c, unsigned long features) (SDE_COLOR_PROCESS_VER(0x1, 0x0))) c->ops.setup_hue = sde_dspp_setup_hue; break; case SDE_DSPP_VLUT: if (c->cap->sblk->vlut.version == (SDE_COLOR_PROCESS_VER(0x1, 0x0))) { c->ops.setup_vlut = sde_dspp_setup_vlut; } default: break; } Loading drivers/gpu/drm/msm/sde/sde_hw_dspp.h +7 −0 Original line number Diff line number Diff line Loading @@ -118,6 +118,13 @@ struct sde_hw_dspp_ops { * @cfg: Pointer to configuration */ void (*setup_cont)(struct sde_hw_dspp *ctx, void *cfg); /** * setup_vlut - setup dspp PA VLUT * @ctx: Pointer to dspp context * @cfg: Pointer to configuration */ void (*setup_vlut)(struct sde_hw_dspp *ctx, void *cfg); }; /** Loading Loading
drivers/gpu/drm/msm/sde/sde_color_processing.c +140 −46 Original line number Diff line number Diff line Loading @@ -22,7 +22,7 @@ #include "sde_hw_dspp.h" #include "sde_hw_lm.h" struct sde_color_process_node { struct sde_cp_node { u32 property_id; u32 prop_flags; u32 feature; Loading @@ -39,7 +39,7 @@ struct sde_color_process_node { struct sde_cp_prop_attach { struct drm_crtc *crtc; struct drm_property *prop; struct sde_color_process_node *prop_node; struct sde_cp_node *prop_node; const struct sde_pp_blk *pp_blk; u32 feature; void *ops; Loading @@ -62,6 +62,7 @@ enum { SDE_CP_CRTC_DSPP_DITHER, SDE_CP_CRTC_DSPP_HIST, SDE_CP_CRTC_DSPP_AD, SDE_CP_CRTC_DSPP_VLUT, SDE_CP_CRTC_DSPP_MAX, /* DSPP features end */ Loading @@ -84,8 +85,43 @@ enum { (p)->val = val; \ } while (0) static int sde_cp_disable_crtc_blob_property( struct sde_color_process_node *prop_node) static void sde_cp_get_hw_payload(struct sde_cp_node *prop_node, struct sde_hw_cp_cfg *hw_cfg, bool *feature_enabled) { struct drm_property_blob *blob = NULL; memset(hw_cfg, 0, sizeof(*hw_cfg)); *feature_enabled = false; blob = prop_node->blob_ptr; if (prop_node->prop_flags & DRM_MODE_PROP_BLOB) { if (blob) { hw_cfg->len = blob->length; hw_cfg->payload = blob->data; *feature_enabled = true; } } else if (prop_node->prop_flags & DRM_MODE_PROP_RANGE) { /* Check if local blob is Set */ if (!blob) { hw_cfg->len = sizeof(prop_node->prop_val); if (prop_node->prop_val) hw_cfg->payload = &prop_node->prop_val; } else { hw_cfg->len = (prop_node->prop_val) ? blob->length : 0; hw_cfg->payload = (prop_node->prop_val) ? blob->data : NULL; } if (prop_node->prop_val) *feature_enabled = true; } else { DRM_ERROR("property type is not supported\n"); } } static int sde_cp_disable_crtc_blob_property(struct sde_cp_node *prop_node) { struct drm_property_blob *blob = prop_node->blob_ptr; Loading @@ -96,23 +132,84 @@ static int sde_cp_disable_crtc_blob_property( return 0; } static int sde_cp_disable_crtc_property(struct drm_crtc *crtc, struct drm_property *property, struct sde_color_process_node *prop_node) static int sde_cp_create_local_blob(struct drm_crtc *crtc, u32 feature, int len) { int ret = -EINVAL; bool found = false; struct sde_cp_node *prop_node = NULL; struct drm_property_blob *blob_ptr; struct sde_crtc *sde_crtc = to_sde_crtc(crtc); list_for_each_entry(prop_node, &sde_crtc->feature_list, feature_list) { if (prop_node->feature == feature) { found = true; break; } } if (!found || prop_node->prop_flags & DRM_MODE_PROP_BLOB) { DRM_ERROR("local blob create failed prop found %d flags %d\n", found, prop_node->prop_flags); return ret; } blob_ptr = drm_property_create_blob(crtc->dev, len, NULL); ret = (IS_ERR_OR_NULL(blob_ptr)) ? PTR_ERR(blob_ptr) : 0; if (!ret) prop_node->blob_ptr = blob_ptr; return ret; } static void sde_cp_destroy_local_blob(struct sde_cp_node *prop_node) { if (!(prop_node->prop_flags & DRM_MODE_PROP_BLOB) && prop_node->blob_ptr) drm_property_unreference_blob(prop_node->blob_ptr); } static int sde_cp_handle_range_property(struct sde_cp_node *prop_node, uint64_t val) { int ret = 0; struct drm_property_blob *blob_ptr = prop_node->blob_ptr; if (property->flags & DRM_MODE_PROP_BLOB) { ret = sde_cp_disable_crtc_blob_property(prop_node); } else if (property->flags & DRM_MODE_PROP_RANGE) { if (!blob_ptr) { prop_node->prop_val = val; return 0; } if (!val) { prop_node->prop_val = 0; ret = 0; return 0; } ret = copy_from_user(blob_ptr->data, (void *)val, blob_ptr->length); if (ret) { DRM_ERROR("failed to get the property info ret %d", ret); ret = -EFAULT; } else { prop_node->prop_val = val; } return ret; } static int sde_cp_disable_crtc_property(struct drm_crtc *crtc, struct drm_property *property, struct sde_cp_node *prop_node) { int ret = -EINVAL; if (property->flags & DRM_MODE_PROP_BLOB) ret = sde_cp_disable_crtc_blob_property(prop_node); else if (property->flags & DRM_MODE_PROP_RANGE) ret = sde_cp_handle_range_property(prop_node, 0); return ret; } static int sde_cp_enable_crtc_blob_property(struct drm_crtc *crtc, struct sde_color_process_node *prop_node, struct sde_cp_node *prop_node, uint64_t val) { struct drm_property_blob *blob = NULL; Loading @@ -136,17 +233,15 @@ static int sde_cp_enable_crtc_blob_property(struct drm_crtc *crtc, static int sde_cp_enable_crtc_property(struct drm_crtc *crtc, struct drm_property *property, struct sde_color_process_node *prop_node, struct sde_cp_node *prop_node, uint64_t val) { int ret = -EINVAL; if (property->flags & DRM_MODE_PROP_BLOB) ret = sde_cp_enable_crtc_blob_property(crtc, prop_node, val); else if (property->flags & DRM_MODE_PROP_RANGE) { ret = 0; prop_node->prop_val = val; } else if (property->flags & DRM_MODE_PROP_RANGE) ret = sde_cp_handle_range_property(prop_node, val); return ret; } Loading Loading @@ -215,7 +310,7 @@ static void sde_cp_crtc_install_immutable_property(struct drm_crtc *crtc, u32 feature) { struct drm_property *prop; struct sde_color_process_node *prop_node = NULL; struct sde_cp_node *prop_node = NULL; struct msm_drm_private *priv; struct sde_cp_prop_attach prop_attach; uint64_t val = 0; Loading Loading @@ -257,7 +352,7 @@ static void sde_cp_crtc_install_range_property(struct drm_crtc *crtc, uint64_t val) { struct drm_property *prop; struct sde_color_process_node *prop_node = NULL; struct sde_cp_node *prop_node = NULL; struct msm_drm_private *priv; struct sde_cp_prop_attach prop_attach; Loading Loading @@ -295,7 +390,7 @@ static void sde_cp_crtc_create_blob_property(struct drm_crtc *crtc, char *name, u32 feature, void *ops) { struct drm_property *prop; struct sde_color_process_node *prop_node = NULL; struct sde_cp_node *prop_node = NULL; struct msm_drm_private *priv; uint64_t val = 0; struct sde_cp_prop_attach prop_attach; Loading Loading @@ -331,15 +426,14 @@ static void sde_cp_crtc_create_blob_property(struct drm_crtc *crtc, char *name, } static void sde_cp_crtc_setfeature(struct sde_color_process_node *prop_node, static void sde_cp_crtc_setfeature(struct sde_cp_node *prop_node, struct sde_crtc *sde_crtc) { u32 num_mixers = sde_crtc->num_mixers; uint64_t val = 0; struct drm_property_blob *blob = NULL; struct sde_hw_cp_cfg hw_cfg; u32 num_mixers = sde_crtc->num_mixers; int i = 0; bool is_dspp = true; bool feature_enabled = false; if (!prop_node->dspp_feature_op && !prop_node->lm_feature_op) { DRM_ERROR("ops not set for dspp/lm\n"); Loading @@ -347,21 +441,7 @@ static void sde_cp_crtc_setfeature(struct sde_color_process_node *prop_node, } is_dspp = !prop_node->lm_feature_op; memset(&hw_cfg, 0, sizeof(hw_cfg)); if (prop_node->prop_flags & DRM_MODE_PROP_BLOB) { blob = prop_node->blob_ptr; if (blob) { hw_cfg.len = blob->length; hw_cfg.payload = blob->data; } } else if (prop_node->prop_flags & DRM_MODE_PROP_RANGE) { val = prop_node->prop_val; hw_cfg.len = sizeof(prop_node->prop_val); hw_cfg.payload = &prop_node->prop_val; } else { DRM_ERROR("property type is not supported\n"); return; } sde_cp_get_hw_payload(prop_node, &hw_cfg, &feature_enabled); for (i = 0; i < num_mixers; i++) { if (is_dspp) { Loading @@ -377,7 +457,7 @@ static void sde_cp_crtc_setfeature(struct sde_color_process_node *prop_node, } } if (blob || val) { if (feature_enabled) { DRM_DEBUG_DRIVER("Add feature to active list %d\n", prop_node->property_id); list_add_tail(&prop_node->active_list, &sde_crtc->active_list); Loading @@ -394,7 +474,7 @@ void sde_cp_crtc_apply_properties(struct drm_crtc *crtc) { struct sde_crtc *sde_crtc = NULL; bool set_dspp_flush = false, set_lm_flush = false; struct sde_color_process_node *prop_node = NULL, *n = NULL; struct sde_cp_node *prop_node = NULL, *n = NULL; struct sde_hw_ctl *ctl; uint32_t flush_mask = 0; u32 num_mixers = 0, i = 0; Loading Loading @@ -549,6 +629,19 @@ void sde_cp_crtc_install_properties(struct drm_crtc *crtc) sde_cp_crtc_install_immutable_property(crtc, feature_name, SDE_CP_CRTC_DSPP_AD); break; case SDE_DSPP_VLUT: snprintf(feature_name, ARRAY_SIZE(feature_name), "%s%d", "SDE_DSPP_VLUT_V", (hw_dspp->cap->sblk->vlut.version >> 16)); sde_cp_crtc_install_range_property(crtc, feature_name, &hw_dspp->cap->sblk->vlut, SDE_CP_CRTC_DSPP_VLUT, hw_dspp->ops.setup_vlut, 0, U64_MAX, 0); /* TODO: if blob creation fails destroy the property */ sde_cp_create_local_blob(crtc, SDE_CP_CRTC_DSPP_VLUT, sizeof(struct drm_msm_pa_vlut)); break; default: break; } Loading Loading @@ -585,7 +678,7 @@ int sde_cp_crtc_set_property(struct drm_crtc *crtc, struct drm_property *property, uint64_t val) { struct sde_color_process_node *prop_node = NULL; struct sde_cp_node *prop_node = NULL; struct sde_crtc *sde_crtc = NULL; int ret = 0; u8 found = 0; Loading Loading @@ -632,7 +725,7 @@ int sde_cp_crtc_set_property(struct drm_crtc *crtc, int sde_cp_crtc_get_property(struct drm_crtc *crtc, struct drm_property *property, uint64_t *val) { struct sde_color_process_node *prop_node = NULL; struct sde_cp_node *prop_node = NULL; struct sde_crtc *sde_crtc = NULL; int ret = -EINVAL; Loading Loading @@ -661,7 +754,7 @@ int sde_cp_crtc_get_property(struct drm_crtc *crtc, void sde_cp_crtc_destroy_properties(struct drm_crtc *crtc) { struct sde_crtc *sde_crtc = NULL; struct sde_color_process_node *prop_node = NULL, *n = NULL; struct sde_cp_node *prop_node = NULL, *n = NULL; if (!crtc) { DRM_ERROR("invalid crtc %pK\n", crtc); Loading @@ -683,6 +776,7 @@ void sde_cp_crtc_destroy_properties(struct drm_crtc *crtc) list_del_init(&prop_node->active_list); list_del_init(&prop_node->dirty_list); list_del_init(&prop_node->feature_list); sde_cp_destroy_local_blob(prop_node); kfree(prop_node); } Loading @@ -694,7 +788,7 @@ void sde_cp_crtc_destroy_properties(struct drm_crtc *crtc) void sde_cp_crtc_suspend(struct drm_crtc *crtc) { struct sde_crtc *sde_crtc = NULL; struct sde_color_process_node *prop_node = NULL, *n = NULL; struct sde_cp_node *prop_node = NULL, *n = NULL; if (!crtc) { DRM_ERROR("crtc %pK\n", crtc); Loading
drivers/gpu/drm/msm/sde/sde_hw_catalog.h +5 −1 Original line number Diff line number Diff line Loading @@ -127,7 +127,9 @@ enum { * @SDE_DSPP_SIXZONE Six zone block * @SDE_DSPP_GAMUT Gamut bloc * @SDE_DSPP_DITHER Dither block * @SDE_DSPP_HIST Histogram bloc * @SDE_DSPP_HIST Histogram block * @SDE_DSPP_VLUT PA VLUT block * @SDE_DSPP_AD AD block * @SDE_DSPP_MAX maximum value */ enum { Loading @@ -140,6 +142,7 @@ enum { SDE_DSPP_GAMUT, SDE_DSPP_DITHER, SDE_DSPP_HIST, SDE_DSPP_VLUT, SDE_DSPP_AD, SDE_DSPP_MAX }; Loading Loading @@ -358,6 +361,7 @@ struct sde_dspp_sub_blks { struct sde_pp_blk dither; struct sde_pp_blk hist; struct sde_pp_blk ad; struct sde_pp_blk vlut; }; struct sde_pingpong_sub_blks { Loading
drivers/gpu/drm/msm/sde/sde_hw_catalog_8996.c +3 −1 Original line number Diff line number Diff line Loading @@ -41,7 +41,7 @@ (BIT(SDE_DSPP_IGC) | BIT(SDE_DSPP_PCC) |\ BIT(SDE_DSPP_GC) | BIT(SDE_DSPP_HSIC) | BIT(SDE_DSPP_GAMUT) |\ BIT(SDE_DSPP_DITHER) | BIT(SDE_DSPP_HIST) | BIT(SDE_DSPP_MEMCOLOR) |\ BIT(SDE_DSPP_SIXZONE) | BIT(SDE_DSPP_AD)) BIT(SDE_DSPP_SIXZONE) | BIT(SDE_DSPP_AD) | BIT(SDE_DSPP_VLUT)) #define PINGPONG_17X_MASK \ (BIT(SDE_PINGPONG_TE) | BIT(SDE_PINGPONG_DSC)) Loading Loading @@ -362,6 +362,8 @@ static inline int set_cfg_1xx_init(struct sde_mdss_cfg *cfg) .version = SDE_COLOR_PROCESS_VER(0x1, 0x0)}, .ad = {.id = SDE_DSPP_AD, .base = 0x00, .len = 0x0, .version = SDE_COLOR_PROCESS_VER(0x3, 0x0)}, .vlut = {.id = SDE_DSPP_VLUT, .base = 0x1400, .len = 0x0, .version = SDE_COLOR_PROCESS_VER(0x1, 0x0)}, }; /* PINGPONG capability */ Loading
drivers/gpu/drm/msm/sde/sde_hw_dspp.c +70 −0 Original line number Diff line number Diff line Loading @@ -28,6 +28,28 @@ #define PCC_CONST_COEFF_MASK 0xFFFF #define PCC_COEFF_MASK 0x3FFFF #define REG_MASK(n) ((BIT(n)) - 1) #define PA_SZ_VAL_MASK BIT(31) #define PA_SZ_SAT_MASK BIT(30) #define PA_SZ_HUE_MASK BIT(29) #define PA_CONT_MASK BIT(28) #define PA_VAL_MASK BIT(27) #define PA_SAT_MASK BIT(26) #define PA_HUE_MASK BIT(25) #define PA_LUTV_MASK BIT(19) #define PA_HIST_MASK BIT(16) #define PA_MEM_SKY_MASK BIT(7) #define PA_MEM_FOL_MASK BIT(6) #define PA_MEM_SKIN_MASK BIT(5) #define PA_ENABLE BIT(20) #define PA_ENABLE_MASK (PA_SZ_VAL_MASK | PA_SZ_SAT_MASK | PA_SZ_HUE_MASK \ | PA_CONT_MASK | PA_VAL_MASK | PA_SAT_MASK \ | PA_HUE_MASK | PA_LUTV_MASK | PA_HIST_MASK \ | PA_MEM_SKY_MASK | PA_MEM_FOL_MASK | PA_MEM_SKIN_MASK) #define PA_LUT_SWAP_OFF 0x234 static struct sde_dspp_cfg *_dspp_offset(enum sde_dspp dspp, struct sde_mdss_cfg *m, void __iomem *addr, Loading Loading @@ -68,6 +90,49 @@ void sde_dspp_setup_hue(struct sde_hw_dspp *dspp, void *cfg) { } void sde_dspp_setup_vlut(struct sde_hw_dspp *ctx, void *cfg) { struct drm_msm_pa_vlut *payload = NULL; struct sde_hw_cp_cfg *hw_cfg = cfg; u32 op_mode, tmp; int i = 0, j = 0; if (!hw_cfg || (hw_cfg->payload && hw_cfg->len != sizeof(struct drm_msm_pa_vlut))) { DRM_ERROR("hw %pK payload %pK payloadsize %d exp size %zd\n", hw_cfg, ((hw_cfg) ? hw_cfg->payload : NULL), ((hw_cfg) ? hw_cfg->len : 0), sizeof(struct drm_msm_pa_vlut)); return; } op_mode = SDE_REG_READ(&ctx->hw, 0); if (!hw_cfg->payload) { DRM_DEBUG_DRIVER("Disable vlut feature\n"); /** * In the PA_VLUT disable case, remove PA_VLUT enable bit(19) * first, then check whether any other PA sub-features are * enabled or not. If none of the sub-features are enabled, * remove the PA global enable bit(20). */ op_mode &= ~((u32)PA_LUTV_MASK); if (!(op_mode & PA_ENABLE_MASK)) op_mode &= ~((u32)PA_ENABLE); SDE_REG_WRITE(&ctx->hw, 0, op_mode); return; } payload = hw_cfg->payload; DRM_DEBUG_DRIVER("Enable vlut feature flags %llx\n", payload->flags); for (i = 0, j = 0; i < ARRAY_SIZE(payload->val); i += 2, j += 4) { tmp = (payload->val[i] & REG_MASK(10)) | ((payload->val[i + 1] & REG_MASK(10)) << 16); SDE_REG_WRITE(&ctx->hw, (ctx->cap->sblk->vlut.base + j), tmp); } SDE_REG_WRITE(&ctx->hw, PA_LUT_SWAP_OFF, 1); op_mode |= PA_ENABLE | PA_LUTV_MASK; SDE_REG_WRITE(&ctx->hw, 0, op_mode); } void sde_dspp_setup_pcc(struct sde_hw_dspp *ctx, void *cfg) { struct sde_hw_cp_cfg *hw_cfg = cfg; Loading Loading @@ -194,6 +259,11 @@ static void _setup_dspp_ops(struct sde_hw_dspp *c, unsigned long features) (SDE_COLOR_PROCESS_VER(0x1, 0x0))) c->ops.setup_hue = sde_dspp_setup_hue; break; case SDE_DSPP_VLUT: if (c->cap->sblk->vlut.version == (SDE_COLOR_PROCESS_VER(0x1, 0x0))) { c->ops.setup_vlut = sde_dspp_setup_vlut; } default: break; } Loading
drivers/gpu/drm/msm/sde/sde_hw_dspp.h +7 −0 Original line number Diff line number Diff line Loading @@ -118,6 +118,13 @@ struct sde_hw_dspp_ops { * @cfg: Pointer to configuration */ void (*setup_cont)(struct sde_hw_dspp *ctx, void *cfg); /** * setup_vlut - setup dspp PA VLUT * @ctx: Pointer to dspp context * @cfg: Pointer to configuration */ void (*setup_vlut)(struct sde_hw_dspp *ctx, void *cfg); }; /** Loading