Loading include/uapi/display/drm/msm_drm_pp.h +3 −1 Original line number Original line Diff line number Diff line Loading @@ -412,10 +412,12 @@ struct drm_msm_ad4_cfg { }; }; #define DITHER_MATRIX_SZ 16 #define DITHER_MATRIX_SZ 16 #define DITHER_LUMA_MODE (1 << 0) /** /** * struct drm_msm_dither - dither feature structure * struct drm_msm_dither - dither feature structure * @flags: for customizing operations * @flags: flags for the feature customization, values can be: -DITHER_LUMA_MODE: Enable LUMA dither mode * @temporal_en: temperal dither enable * @temporal_en: temperal dither enable * @c0_bitdepth: c0 component bit depth * @c0_bitdepth: c0 component bit depth * @c1_bitdepth: c1 component bit depth * @c1_bitdepth: c1 component bit depth Loading msm/sde/sde_connector.c +27 −80 Original line number Original line Diff line number Diff line Loading @@ -29,9 +29,6 @@ #define SDE_ERROR_CONN(c, fmt, ...) SDE_ERROR("conn%d " fmt,\ #define SDE_ERROR_CONN(c, fmt, ...) SDE_ERROR("conn%d " fmt,\ (c) ? (c)->base.base.id : -1, ##__VA_ARGS__) (c) ? (c)->base.base.id : -1, ##__VA_ARGS__) static u32 dither_matrix[DITHER_MATRIX_SZ] = { 15, 7, 13, 5, 3, 11, 1, 9, 12, 4, 14, 6, 0, 8, 2, 10 }; static const struct drm_prop_enum_list e_topology_name[] = { static const struct drm_prop_enum_list e_topology_name[] = { {SDE_RM_TOPOLOGY_NONE, "sde_none"}, {SDE_RM_TOPOLOGY_NONE, "sde_none"}, Loading Loading @@ -245,60 +242,12 @@ void sde_connector_unregister_event(struct drm_connector *connector, (void)sde_connector_register_event(connector, event_idx, 0, 0); (void)sde_connector_register_event(connector, event_idx, 0, 0); } } static int _sde_connector_get_default_dither_cfg_v1( struct sde_connector *c_conn, void *cfg) { struct drm_msm_dither *dither_cfg = (struct drm_msm_dither *)cfg; enum dsi_pixel_format dst_format = DSI_PIXEL_FORMAT_MAX; if (!c_conn || !cfg) { SDE_ERROR("invalid argument(s), c_conn %pK, cfg %pK\n", c_conn, cfg); return -EINVAL; } if (!c_conn->ops.get_dst_format) { SDE_DEBUG("get_dst_format is unavailable\n"); return 0; } dst_format = c_conn->ops.get_dst_format(&c_conn->base, c_conn->display); switch (dst_format) { case DSI_PIXEL_FORMAT_RGB888: dither_cfg->c0_bitdepth = 8; dither_cfg->c1_bitdepth = 8; dither_cfg->c2_bitdepth = 8; dither_cfg->c3_bitdepth = 8; break; case DSI_PIXEL_FORMAT_RGB666: case DSI_PIXEL_FORMAT_RGB666_LOOSE: dither_cfg->c0_bitdepth = 6; dither_cfg->c1_bitdepth = 6; dither_cfg->c2_bitdepth = 6; dither_cfg->c3_bitdepth = 6; break; default: SDE_DEBUG("no default dither config for dst_format %d\n", dst_format); return -ENODATA; } memcpy(&dither_cfg->matrix, dither_matrix, sizeof(u32) * DITHER_MATRIX_SZ); dither_cfg->temporal_en = 0; return 0; } static void _sde_connector_install_dither_property(struct drm_device *dev, static void _sde_connector_install_dither_property(struct drm_device *dev, struct sde_kms *sde_kms, struct sde_connector *c_conn) struct sde_kms *sde_kms, struct sde_connector *c_conn) { { char prop_name[DRM_PROP_NAME_LEN]; char prop_name[DRM_PROP_NAME_LEN]; struct sde_mdss_cfg *catalog = NULL; struct sde_mdss_cfg *catalog = NULL; struct drm_property_blob *blob_ptr; u32 version = 0; void *cfg; int ret = 0; u32 version = 0, len = 0; bool defalut_dither_needed = false; if (!dev || !sde_kms || !c_conn) { if (!dev || !sde_kms || !c_conn) { SDE_ERROR("invld args (s), dev %pK, sde_kms %pK, c_conn %pK\n", SDE_ERROR("invld args (s), dev %pK, sde_kms %pK, c_conn %pK\n", Loading @@ -313,57 +262,55 @@ static void _sde_connector_install_dither_property(struct drm_device *dev, "SDE_PP_DITHER_V", version); "SDE_PP_DITHER_V", version); switch (version) { switch (version) { case 1: case 1: case 2: msm_property_install_blob(&c_conn->property_info, prop_name, msm_property_install_blob(&c_conn->property_info, prop_name, DRM_MODE_PROP_BLOB, DRM_MODE_PROP_BLOB, CONNECTOR_PROP_PP_DITHER); CONNECTOR_PROP_PP_DITHER); len = sizeof(struct drm_msm_dither); cfg = kzalloc(len, GFP_KERNEL); if (!cfg) return; ret = _sde_connector_get_default_dither_cfg_v1(c_conn, cfg); if (!ret) defalut_dither_needed = true; break; break; default: default: SDE_ERROR("unsupported dither version %d\n", version); SDE_ERROR("unsupported dither version %d\n", version); return; return; } } if (defalut_dither_needed) { blob_ptr = drm_property_create_blob(dev, len, cfg); if (IS_ERR_OR_NULL(blob_ptr)) goto exit; c_conn->blob_dither = blob_ptr; } exit: kfree(cfg); } } int sde_connector_get_dither_cfg(struct drm_connector *conn, int sde_connector_get_dither_cfg(struct drm_connector *conn, struct drm_connector_state *state, void **cfg, struct drm_connector_state *state, void **cfg, size_t *len) size_t *len, bool idle_pc) { { struct sde_connector *c_conn = NULL; struct sde_connector *c_conn = NULL; struct sde_connector_state *c_state = NULL; struct sde_connector_state *c_state = NULL; size_t dither_sz = 0; size_t dither_sz = 0; bool is_dirty; u32 *p = (u32 *)cfg; u32 *p = (u32 *)cfg; if (!conn || !state || !p) if (!conn || !state || !p) { SDE_ERROR("invalid arguments\n"); return -EINVAL; return -EINVAL; } c_conn = to_sde_connector(conn); c_conn = to_sde_connector(conn); c_state = to_sde_connector_state(state); c_state = to_sde_connector_state(state); /* try to get user config data first */ is_dirty = msm_property_is_dirty(&c_conn->property_info, &c_state->property_state, CONNECTOR_PROP_PP_DITHER); if (!is_dirty && !idle_pc) { return -ENODATA; } else if (is_dirty || idle_pc) { *cfg = msm_property_get_blob(&c_conn->property_info, *cfg = msm_property_get_blob(&c_conn->property_info, &c_state->property_state, &c_state->property_state, &dither_sz, &dither_sz, CONNECTOR_PROP_PP_DITHER); CONNECTOR_PROP_PP_DITHER); /* if user config data doesn't exist, use default dither blob */ /* if (*cfg == NULL && c_conn->blob_dither) { * in idle_pc use case return early, *cfg = &c_conn->blob_dither->data; * when dither is already disabled. dither_sz = c_conn->blob_dither->length; */ if (idle_pc && *cfg == NULL) return -ENODATA; /* disable dither based on user config data */ else if (*cfg == NULL) return 0; } } *len = dither_sz; *len = dither_sz; return 0; return 0; Loading msm/sde/sde_connector.h +3 −1 Original line number Original line Diff line number Diff line Loading @@ -854,10 +854,12 @@ static inline bool sde_connector_needs_offset(struct drm_connector *connector) * @state: Pointer to drm_connector_state struct * @state: Pointer to drm_connector_state struct * @cfg: Pointer to pointer to dither cfg * @cfg: Pointer to pointer to dither cfg * @len: length of the dither data * @len: length of the dither data * @idle_pc: flag to indicate idle_pc_restore happened * Returns: Zero on success * Returns: Zero on success */ */ int sde_connector_get_dither_cfg(struct drm_connector *conn, int sde_connector_get_dither_cfg(struct drm_connector *conn, struct drm_connector_state *state, void **cfg, size_t *len); struct drm_connector_state *state, void **cfg, size_t *len, bool idle_pc); /** /** * sde_connector_set_blob_data - set connector blob property data * sde_connector_set_blob_data - set connector blob property data Loading msm/sde/sde_encoder.c +57 −49 Original line number Original line Diff line number Diff line Loading @@ -2354,6 +2354,61 @@ static void _sde_encoder_virt_enable_helper(struct drm_encoder *drm_enc) memset(&sde_enc->cur_conn_roi, 0, sizeof(sde_enc->cur_conn_roi)); memset(&sde_enc->cur_conn_roi, 0, sizeof(sde_enc->cur_conn_roi)); } } static void _sde_encoder_setup_dither(struct sde_encoder_phys *phys) { void *dither_cfg = NULL; int ret = 0, i = 0; size_t len = 0; enum sde_rm_topology_name topology; struct drm_encoder *drm_enc; struct msm_display_dsc_info *dsc = NULL; struct sde_encoder_virt *sde_enc; struct sde_hw_pingpong *hw_pp; u32 bpp, bpc; if (!phys || !phys->connector || !phys->hw_pp || !phys->hw_pp->ops.setup_dither || !phys->parent) return; topology = sde_connector_get_topology_name(phys->connector); if ((topology == SDE_RM_TOPOLOGY_PPSPLIT) && (phys->split_role == ENC_ROLE_SLAVE)) return; drm_enc = phys->parent; sde_enc = to_sde_encoder_virt(drm_enc); dsc = &sde_enc->mode_info.comp_info.dsc_info; bpc = dsc->config.bits_per_component; bpp = dsc->config.bits_per_pixel; /* disable dither for 10 bpp or 10bpc dsc config */ if (bpp == 10 || bpc == 10) { phys->hw_pp->ops.setup_dither(phys->hw_pp, NULL, 0); return; } ret = sde_connector_get_dither_cfg(phys->connector, phys->connector->state, &dither_cfg, &len, sde_enc->idle_pc_restore); /* skip reg writes when return values are invalid or no data */ if (ret && ret == -ENODATA) return; if (TOPOLOGY_DUALPIPE_MERGE_MODE(topology)) { for (i = 0; i < MAX_CHANNELS_PER_ENC; i++) { hw_pp = sde_enc->hw_pp[i]; phys->hw_pp->ops.setup_dither(hw_pp, dither_cfg, len); } } else { phys->hw_pp->ops.setup_dither(phys->hw_pp, dither_cfg, len); } } void sde_encoder_virt_restore(struct drm_encoder *drm_enc) void sde_encoder_virt_restore(struct drm_encoder *drm_enc) { { struct sde_encoder_virt *sde_enc = NULL; struct sde_encoder_virt *sde_enc = NULL; Loading Loading @@ -2386,6 +2441,8 @@ void sde_encoder_virt_restore(struct drm_encoder *drm_enc) if ((phys != sde_enc->cur_master) && phys->ops.restore) if ((phys != sde_enc->cur_master) && phys->ops.restore) phys->ops.restore(phys); phys->ops.restore(phys); _sde_encoder_setup_dither(phys); } } if (sde_enc->cur_master->ops.restore) if (sde_enc->cur_master->ops.restore) Loading Loading @@ -3452,55 +3509,6 @@ void sde_encoder_trigger_kickoff_pending(struct drm_encoder *drm_enc) sde_enc->idle_pc_restore = false; sde_enc->idle_pc_restore = false; } } static void _sde_encoder_setup_dither(struct sde_encoder_phys *phys) { void *dither_cfg; int ret = 0, i = 0; size_t len = 0; enum sde_rm_topology_name topology; struct drm_encoder *drm_enc; struct msm_display_dsc_info *dsc = NULL; struct sde_encoder_virt *sde_enc; struct sde_hw_pingpong *hw_pp; u16 bpp; if (!phys || !phys->connector || !phys->hw_pp || !phys->hw_pp->ops.setup_dither || !phys->parent) return; topology = sde_connector_get_topology_name(phys->connector); if ((topology == SDE_RM_TOPOLOGY_PPSPLIT) && (phys->split_role == ENC_ROLE_SLAVE)) return; drm_enc = phys->parent; sde_enc = to_sde_encoder_virt(drm_enc); dsc = &sde_enc->mode_info.comp_info.dsc_info; /* disable dither for 10 bpp or 10bpc dsc config */ bpp = DSC_BPP(dsc->config); if (bpp == 10 || dsc->config.bits_per_component == 10) { phys->hw_pp->ops.setup_dither(phys->hw_pp, NULL, 0); return; } ret = sde_connector_get_dither_cfg(phys->connector, phys->connector->state, &dither_cfg, &len); if (ret) return; if (TOPOLOGY_DUALPIPE_MERGE_MODE(topology)) { for (i = 0; i < MAX_CHANNELS_PER_ENC; i++) { hw_pp = sde_enc->hw_pp[i]; if (hw_pp) { phys->hw_pp->ops.setup_dither(hw_pp, dither_cfg, len); } } } else { phys->hw_pp->ops.setup_dither(phys->hw_pp, dither_cfg, len); } } static u32 _sde_encoder_calculate_linetime(struct sde_encoder_virt *sde_enc, static u32 _sde_encoder_calculate_linetime(struct sde_encoder_virt *sde_enc, struct drm_display_mode *mode) struct drm_display_mode *mode) { { Loading msm/sde/sde_hw_catalog.c +4 −0 Original line number Original line Diff line number Diff line Loading @@ -3344,6 +3344,9 @@ static int sde_pp_parse_dt(struct device_node *np, struct sde_mdss_cfg *sde_cfg) sblk->dither.version = PROP_VALUE_ACCESS(prop_value, DITHER_VER, sblk->dither.version = PROP_VALUE_ACCESS(prop_value, DITHER_VER, 0); 0); if (sde_cfg->dither_luma_mode_support) set_bit(SDE_PINGPONG_DITHER_LUMA, &pp->features); if (prop_exists[PP_MERGE_3D_ID]) { if (prop_exists[PP_MERGE_3D_ID]) { set_bit(SDE_PINGPONG_MERGE_3D, &pp->features); set_bit(SDE_PINGPONG_MERGE_3D, &pp->features); pp->merge_3d_id = PROP_VALUE_ACCESS(prop_value, pp->merge_3d_id = PROP_VALUE_ACCESS(prop_value, Loading Loading @@ -4561,6 +4564,7 @@ static int _sde_hardware_pre_caps(struct sde_mdss_cfg *sde_cfg, uint32_t hw_rev) sde_cfg->true_inline_rot_rev = SDE_INLINE_ROT_VERSION_2_0_0; sde_cfg->true_inline_rot_rev = SDE_INLINE_ROT_VERSION_2_0_0; sde_cfg->uidle_cfg.uidle_rev = SDE_UIDLE_VERSION_1_0_1; sde_cfg->uidle_cfg.uidle_rev = SDE_UIDLE_VERSION_1_0_1; sde_cfg->vbif_disable_inner_outer_shareable = true; sde_cfg->vbif_disable_inner_outer_shareable = true; sde_cfg->dither_luma_mode_support = true; } else { } else { SDE_ERROR("unsupported chipset id:%X\n", hw_rev); SDE_ERROR("unsupported chipset id:%X\n", hw_rev); sde_cfg->perf.min_prefill_lines = 0xffff; sde_cfg->perf.min_prefill_lines = 0xffff; Loading Loading
include/uapi/display/drm/msm_drm_pp.h +3 −1 Original line number Original line Diff line number Diff line Loading @@ -412,10 +412,12 @@ struct drm_msm_ad4_cfg { }; }; #define DITHER_MATRIX_SZ 16 #define DITHER_MATRIX_SZ 16 #define DITHER_LUMA_MODE (1 << 0) /** /** * struct drm_msm_dither - dither feature structure * struct drm_msm_dither - dither feature structure * @flags: for customizing operations * @flags: flags for the feature customization, values can be: -DITHER_LUMA_MODE: Enable LUMA dither mode * @temporal_en: temperal dither enable * @temporal_en: temperal dither enable * @c0_bitdepth: c0 component bit depth * @c0_bitdepth: c0 component bit depth * @c1_bitdepth: c1 component bit depth * @c1_bitdepth: c1 component bit depth Loading
msm/sde/sde_connector.c +27 −80 Original line number Original line Diff line number Diff line Loading @@ -29,9 +29,6 @@ #define SDE_ERROR_CONN(c, fmt, ...) SDE_ERROR("conn%d " fmt,\ #define SDE_ERROR_CONN(c, fmt, ...) SDE_ERROR("conn%d " fmt,\ (c) ? (c)->base.base.id : -1, ##__VA_ARGS__) (c) ? (c)->base.base.id : -1, ##__VA_ARGS__) static u32 dither_matrix[DITHER_MATRIX_SZ] = { 15, 7, 13, 5, 3, 11, 1, 9, 12, 4, 14, 6, 0, 8, 2, 10 }; static const struct drm_prop_enum_list e_topology_name[] = { static const struct drm_prop_enum_list e_topology_name[] = { {SDE_RM_TOPOLOGY_NONE, "sde_none"}, {SDE_RM_TOPOLOGY_NONE, "sde_none"}, Loading Loading @@ -245,60 +242,12 @@ void sde_connector_unregister_event(struct drm_connector *connector, (void)sde_connector_register_event(connector, event_idx, 0, 0); (void)sde_connector_register_event(connector, event_idx, 0, 0); } } static int _sde_connector_get_default_dither_cfg_v1( struct sde_connector *c_conn, void *cfg) { struct drm_msm_dither *dither_cfg = (struct drm_msm_dither *)cfg; enum dsi_pixel_format dst_format = DSI_PIXEL_FORMAT_MAX; if (!c_conn || !cfg) { SDE_ERROR("invalid argument(s), c_conn %pK, cfg %pK\n", c_conn, cfg); return -EINVAL; } if (!c_conn->ops.get_dst_format) { SDE_DEBUG("get_dst_format is unavailable\n"); return 0; } dst_format = c_conn->ops.get_dst_format(&c_conn->base, c_conn->display); switch (dst_format) { case DSI_PIXEL_FORMAT_RGB888: dither_cfg->c0_bitdepth = 8; dither_cfg->c1_bitdepth = 8; dither_cfg->c2_bitdepth = 8; dither_cfg->c3_bitdepth = 8; break; case DSI_PIXEL_FORMAT_RGB666: case DSI_PIXEL_FORMAT_RGB666_LOOSE: dither_cfg->c0_bitdepth = 6; dither_cfg->c1_bitdepth = 6; dither_cfg->c2_bitdepth = 6; dither_cfg->c3_bitdepth = 6; break; default: SDE_DEBUG("no default dither config for dst_format %d\n", dst_format); return -ENODATA; } memcpy(&dither_cfg->matrix, dither_matrix, sizeof(u32) * DITHER_MATRIX_SZ); dither_cfg->temporal_en = 0; return 0; } static void _sde_connector_install_dither_property(struct drm_device *dev, static void _sde_connector_install_dither_property(struct drm_device *dev, struct sde_kms *sde_kms, struct sde_connector *c_conn) struct sde_kms *sde_kms, struct sde_connector *c_conn) { { char prop_name[DRM_PROP_NAME_LEN]; char prop_name[DRM_PROP_NAME_LEN]; struct sde_mdss_cfg *catalog = NULL; struct sde_mdss_cfg *catalog = NULL; struct drm_property_blob *blob_ptr; u32 version = 0; void *cfg; int ret = 0; u32 version = 0, len = 0; bool defalut_dither_needed = false; if (!dev || !sde_kms || !c_conn) { if (!dev || !sde_kms || !c_conn) { SDE_ERROR("invld args (s), dev %pK, sde_kms %pK, c_conn %pK\n", SDE_ERROR("invld args (s), dev %pK, sde_kms %pK, c_conn %pK\n", Loading @@ -313,57 +262,55 @@ static void _sde_connector_install_dither_property(struct drm_device *dev, "SDE_PP_DITHER_V", version); "SDE_PP_DITHER_V", version); switch (version) { switch (version) { case 1: case 1: case 2: msm_property_install_blob(&c_conn->property_info, prop_name, msm_property_install_blob(&c_conn->property_info, prop_name, DRM_MODE_PROP_BLOB, DRM_MODE_PROP_BLOB, CONNECTOR_PROP_PP_DITHER); CONNECTOR_PROP_PP_DITHER); len = sizeof(struct drm_msm_dither); cfg = kzalloc(len, GFP_KERNEL); if (!cfg) return; ret = _sde_connector_get_default_dither_cfg_v1(c_conn, cfg); if (!ret) defalut_dither_needed = true; break; break; default: default: SDE_ERROR("unsupported dither version %d\n", version); SDE_ERROR("unsupported dither version %d\n", version); return; return; } } if (defalut_dither_needed) { blob_ptr = drm_property_create_blob(dev, len, cfg); if (IS_ERR_OR_NULL(blob_ptr)) goto exit; c_conn->blob_dither = blob_ptr; } exit: kfree(cfg); } } int sde_connector_get_dither_cfg(struct drm_connector *conn, int sde_connector_get_dither_cfg(struct drm_connector *conn, struct drm_connector_state *state, void **cfg, struct drm_connector_state *state, void **cfg, size_t *len) size_t *len, bool idle_pc) { { struct sde_connector *c_conn = NULL; struct sde_connector *c_conn = NULL; struct sde_connector_state *c_state = NULL; struct sde_connector_state *c_state = NULL; size_t dither_sz = 0; size_t dither_sz = 0; bool is_dirty; u32 *p = (u32 *)cfg; u32 *p = (u32 *)cfg; if (!conn || !state || !p) if (!conn || !state || !p) { SDE_ERROR("invalid arguments\n"); return -EINVAL; return -EINVAL; } c_conn = to_sde_connector(conn); c_conn = to_sde_connector(conn); c_state = to_sde_connector_state(state); c_state = to_sde_connector_state(state); /* try to get user config data first */ is_dirty = msm_property_is_dirty(&c_conn->property_info, &c_state->property_state, CONNECTOR_PROP_PP_DITHER); if (!is_dirty && !idle_pc) { return -ENODATA; } else if (is_dirty || idle_pc) { *cfg = msm_property_get_blob(&c_conn->property_info, *cfg = msm_property_get_blob(&c_conn->property_info, &c_state->property_state, &c_state->property_state, &dither_sz, &dither_sz, CONNECTOR_PROP_PP_DITHER); CONNECTOR_PROP_PP_DITHER); /* if user config data doesn't exist, use default dither blob */ /* if (*cfg == NULL && c_conn->blob_dither) { * in idle_pc use case return early, *cfg = &c_conn->blob_dither->data; * when dither is already disabled. dither_sz = c_conn->blob_dither->length; */ if (idle_pc && *cfg == NULL) return -ENODATA; /* disable dither based on user config data */ else if (*cfg == NULL) return 0; } } *len = dither_sz; *len = dither_sz; return 0; return 0; Loading
msm/sde/sde_connector.h +3 −1 Original line number Original line Diff line number Diff line Loading @@ -854,10 +854,12 @@ static inline bool sde_connector_needs_offset(struct drm_connector *connector) * @state: Pointer to drm_connector_state struct * @state: Pointer to drm_connector_state struct * @cfg: Pointer to pointer to dither cfg * @cfg: Pointer to pointer to dither cfg * @len: length of the dither data * @len: length of the dither data * @idle_pc: flag to indicate idle_pc_restore happened * Returns: Zero on success * Returns: Zero on success */ */ int sde_connector_get_dither_cfg(struct drm_connector *conn, int sde_connector_get_dither_cfg(struct drm_connector *conn, struct drm_connector_state *state, void **cfg, size_t *len); struct drm_connector_state *state, void **cfg, size_t *len, bool idle_pc); /** /** * sde_connector_set_blob_data - set connector blob property data * sde_connector_set_blob_data - set connector blob property data Loading
msm/sde/sde_encoder.c +57 −49 Original line number Original line Diff line number Diff line Loading @@ -2354,6 +2354,61 @@ static void _sde_encoder_virt_enable_helper(struct drm_encoder *drm_enc) memset(&sde_enc->cur_conn_roi, 0, sizeof(sde_enc->cur_conn_roi)); memset(&sde_enc->cur_conn_roi, 0, sizeof(sde_enc->cur_conn_roi)); } } static void _sde_encoder_setup_dither(struct sde_encoder_phys *phys) { void *dither_cfg = NULL; int ret = 0, i = 0; size_t len = 0; enum sde_rm_topology_name topology; struct drm_encoder *drm_enc; struct msm_display_dsc_info *dsc = NULL; struct sde_encoder_virt *sde_enc; struct sde_hw_pingpong *hw_pp; u32 bpp, bpc; if (!phys || !phys->connector || !phys->hw_pp || !phys->hw_pp->ops.setup_dither || !phys->parent) return; topology = sde_connector_get_topology_name(phys->connector); if ((topology == SDE_RM_TOPOLOGY_PPSPLIT) && (phys->split_role == ENC_ROLE_SLAVE)) return; drm_enc = phys->parent; sde_enc = to_sde_encoder_virt(drm_enc); dsc = &sde_enc->mode_info.comp_info.dsc_info; bpc = dsc->config.bits_per_component; bpp = dsc->config.bits_per_pixel; /* disable dither for 10 bpp or 10bpc dsc config */ if (bpp == 10 || bpc == 10) { phys->hw_pp->ops.setup_dither(phys->hw_pp, NULL, 0); return; } ret = sde_connector_get_dither_cfg(phys->connector, phys->connector->state, &dither_cfg, &len, sde_enc->idle_pc_restore); /* skip reg writes when return values are invalid or no data */ if (ret && ret == -ENODATA) return; if (TOPOLOGY_DUALPIPE_MERGE_MODE(topology)) { for (i = 0; i < MAX_CHANNELS_PER_ENC; i++) { hw_pp = sde_enc->hw_pp[i]; phys->hw_pp->ops.setup_dither(hw_pp, dither_cfg, len); } } else { phys->hw_pp->ops.setup_dither(phys->hw_pp, dither_cfg, len); } } void sde_encoder_virt_restore(struct drm_encoder *drm_enc) void sde_encoder_virt_restore(struct drm_encoder *drm_enc) { { struct sde_encoder_virt *sde_enc = NULL; struct sde_encoder_virt *sde_enc = NULL; Loading Loading @@ -2386,6 +2441,8 @@ void sde_encoder_virt_restore(struct drm_encoder *drm_enc) if ((phys != sde_enc->cur_master) && phys->ops.restore) if ((phys != sde_enc->cur_master) && phys->ops.restore) phys->ops.restore(phys); phys->ops.restore(phys); _sde_encoder_setup_dither(phys); } } if (sde_enc->cur_master->ops.restore) if (sde_enc->cur_master->ops.restore) Loading Loading @@ -3452,55 +3509,6 @@ void sde_encoder_trigger_kickoff_pending(struct drm_encoder *drm_enc) sde_enc->idle_pc_restore = false; sde_enc->idle_pc_restore = false; } } static void _sde_encoder_setup_dither(struct sde_encoder_phys *phys) { void *dither_cfg; int ret = 0, i = 0; size_t len = 0; enum sde_rm_topology_name topology; struct drm_encoder *drm_enc; struct msm_display_dsc_info *dsc = NULL; struct sde_encoder_virt *sde_enc; struct sde_hw_pingpong *hw_pp; u16 bpp; if (!phys || !phys->connector || !phys->hw_pp || !phys->hw_pp->ops.setup_dither || !phys->parent) return; topology = sde_connector_get_topology_name(phys->connector); if ((topology == SDE_RM_TOPOLOGY_PPSPLIT) && (phys->split_role == ENC_ROLE_SLAVE)) return; drm_enc = phys->parent; sde_enc = to_sde_encoder_virt(drm_enc); dsc = &sde_enc->mode_info.comp_info.dsc_info; /* disable dither for 10 bpp or 10bpc dsc config */ bpp = DSC_BPP(dsc->config); if (bpp == 10 || dsc->config.bits_per_component == 10) { phys->hw_pp->ops.setup_dither(phys->hw_pp, NULL, 0); return; } ret = sde_connector_get_dither_cfg(phys->connector, phys->connector->state, &dither_cfg, &len); if (ret) return; if (TOPOLOGY_DUALPIPE_MERGE_MODE(topology)) { for (i = 0; i < MAX_CHANNELS_PER_ENC; i++) { hw_pp = sde_enc->hw_pp[i]; if (hw_pp) { phys->hw_pp->ops.setup_dither(hw_pp, dither_cfg, len); } } } else { phys->hw_pp->ops.setup_dither(phys->hw_pp, dither_cfg, len); } } static u32 _sde_encoder_calculate_linetime(struct sde_encoder_virt *sde_enc, static u32 _sde_encoder_calculate_linetime(struct sde_encoder_virt *sde_enc, struct drm_display_mode *mode) struct drm_display_mode *mode) { { Loading
msm/sde/sde_hw_catalog.c +4 −0 Original line number Original line Diff line number Diff line Loading @@ -3344,6 +3344,9 @@ static int sde_pp_parse_dt(struct device_node *np, struct sde_mdss_cfg *sde_cfg) sblk->dither.version = PROP_VALUE_ACCESS(prop_value, DITHER_VER, sblk->dither.version = PROP_VALUE_ACCESS(prop_value, DITHER_VER, 0); 0); if (sde_cfg->dither_luma_mode_support) set_bit(SDE_PINGPONG_DITHER_LUMA, &pp->features); if (prop_exists[PP_MERGE_3D_ID]) { if (prop_exists[PP_MERGE_3D_ID]) { set_bit(SDE_PINGPONG_MERGE_3D, &pp->features); set_bit(SDE_PINGPONG_MERGE_3D, &pp->features); pp->merge_3d_id = PROP_VALUE_ACCESS(prop_value, pp->merge_3d_id = PROP_VALUE_ACCESS(prop_value, Loading Loading @@ -4561,6 +4564,7 @@ static int _sde_hardware_pre_caps(struct sde_mdss_cfg *sde_cfg, uint32_t hw_rev) sde_cfg->true_inline_rot_rev = SDE_INLINE_ROT_VERSION_2_0_0; sde_cfg->true_inline_rot_rev = SDE_INLINE_ROT_VERSION_2_0_0; sde_cfg->uidle_cfg.uidle_rev = SDE_UIDLE_VERSION_1_0_1; sde_cfg->uidle_cfg.uidle_rev = SDE_UIDLE_VERSION_1_0_1; sde_cfg->vbif_disable_inner_outer_shareable = true; sde_cfg->vbif_disable_inner_outer_shareable = true; sde_cfg->dither_luma_mode_support = true; } else { } else { SDE_ERROR("unsupported chipset id:%X\n", hw_rev); SDE_ERROR("unsupported chipset id:%X\n", hw_rev); sde_cfg->perf.min_prefill_lines = 0xffff; sde_cfg->perf.min_prefill_lines = 0xffff; Loading