diff --git a/msm/dsi/dsi_clk_manager.c b/msm/dsi/dsi_clk_manager.c index b8b5bec682c4..a213c6959b38 100644 --- a/msm/dsi/dsi_clk_manager.c +++ b/msm/dsi/dsi_clk_manager.c @@ -1,5 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* + * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved. * Copyright (c) 2016-2020, The Linux Foundation. All rights reserved. */ @@ -172,6 +173,16 @@ int dsi_clk_update_parent(struct dsi_clk_link_set *parent, { int rc = 0; + if (!parent->byte_clk || !parent->pixel_clk) { + DSI_ERR("Invalid parent\n"); + return -EINVAL; + } + + if (!child->byte_clk || !child->pixel_clk) { + DSI_ERR("Invalid child\n"); + return -EINVAL; + } + rc = clk_set_parent(child->byte_clk, parent->byte_clk); if (rc) { DSI_ERR("failed to set byte clk parent\n"); diff --git a/msm/dsi/dsi_display.c b/msm/dsi/dsi_display.c index 2330d73f5c0f..e6c03fc7f6c0 100644 --- a/msm/dsi/dsi_display.c +++ b/msm/dsi/dsi_display.c @@ -1,5 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* + * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved. * Copyright (c) 2016-2021, The Linux Foundation. All rights reserved. */ @@ -2657,6 +2658,38 @@ error: return rc; } +#ifdef CONFIG_DEEPSLEEP +static int dsi_display_unset_clk_src(struct dsi_display *display) +{ + int rc = 0; + int i; + struct dsi_display_ctrl *ctrl; + + DSI_DEBUG("[%s] unset source clocks\n", display->name); + + display_for_each_ctrl(i, display) { + ctrl = &display->ctrl[i]; + if (!ctrl->ctrl) + continue; + + /* set ctrl clocks to xo source */ + rc = dsi_ctrl_set_clock_source(ctrl->ctrl, + &display->clock_info.xo_clks); + if (rc) { + DSI_ERR("[%s] failed to set source clocks, rc=%d\n", + display->name, rc); + return rc; + } + } + return 0; +} +#else +static inline int dsi_display_unset_clk_src(struct dsi_display *display) +{ + return 0; +} +#endif + static int dsi_display_set_clk_src(struct dsi_display *display) { int rc = 0; @@ -3442,6 +3475,7 @@ static int dsi_display_clocks_init(struct dsi_display *display) { int i, rc = 0, num_clk = 0; const char *clk_name; + const char *xo_byte = "xo_byte", *xo_pixel = "xo_pixel"; const char *src_byte = "src_byte", *src_pixel = "src_pixel"; const char *mux_byte = "mux_byte", *mux_pixel = "mux_pixel"; const char *cphy_byte = "cphy_byte", *cphy_pixel = "cphy_pixel"; @@ -3449,6 +3483,7 @@ static int dsi_display_clocks_init(struct dsi_display *display) const char *shadow_cphybyte = "shadow_cphybyte", *shadow_cphypixel = "shadow_cphypixel"; struct clk *dsi_clk; + struct dsi_clk_link_set *xo = &display->clock_info.xo_clks; struct dsi_clk_link_set *src = &display->clock_info.src_clks; struct dsi_clk_link_set *mux = &display->clock_info.mux_clks; struct dsi_clk_link_set *cphy = &display->clock_info.cphy_clks; @@ -3479,6 +3514,15 @@ static int dsi_display_clocks_init(struct dsi_display *display) DSI_ERR("failed to get %s, rc=%d\n", clk_name, rc); + if (dsi_display_check_prefix(xo_byte, clk_name)) { + xo->byte_clk = NULL; + goto error; + } + if (dsi_display_check_prefix(xo_pixel, clk_name)) { + xo->pixel_clk = NULL; + goto error; + } + if (dsi_display_check_prefix(mux_byte, clk_name)) { mux->byte_clk = NULL; goto error; @@ -3524,6 +3568,16 @@ static int dsi_display_clocks_init(struct dsi_display *display) } } + if (dsi_display_check_prefix(xo_byte, clk_name)) { + xo->byte_clk = dsi_clk; + continue; + } + + if (dsi_display_check_prefix(xo_pixel, clk_name)) { + xo->pixel_clk = dsi_clk; + continue; + } + if (dsi_display_check_prefix(src_byte, clk_name)) { src->byte_clk = dsi_clk; continue; @@ -6918,6 +6972,20 @@ int dsi_display_get_modes(struct dsi_display *display, goto error; } + /* + * Update the host_config.dst_format for compressed RGB101010 + * pixel format. + */ + if (display->panel->host_config.dst_format == + DSI_PIXEL_FORMAT_RGB101010 && + display_mode.timing.dsc_enabled) { + display->panel->host_config.dst_format = + DSI_PIXEL_FORMAT_RGB888; + DSI_DEBUG("updated dst_format from %d to %d\n", + DSI_PIXEL_FORMAT_RGB101010, + display->panel->host_config.dst_format); + } + is_cmd_mode = (display_mode.panel_mode == DSI_OP_CMD_MODE); /* Setup widebus support */ @@ -8586,6 +8654,12 @@ int dsi_display_unprepare(struct dsi_display *display) DSI_ERR("[%s] failed to disable Link clocks, rc=%d\n", display->name, rc); + /* set to dsi clocks to xo clocks */ + rc = dsi_display_unset_clk_src(display); + if (rc) + DSI_ERR("[%s] failed to unset clocks, rc=%d\n", + display->name, rc); + rc = dsi_display_ctrl_deinit(display); if (rc) DSI_ERR("[%s] failed to deinit controller, rc=%d\n", diff --git a/msm/dsi/dsi_display.h b/msm/dsi/dsi_display.h index 2dc7bc7dd137..e2932a0d530d 100644 --- a/msm/dsi/dsi_display.h +++ b/msm/dsi/dsi_display.h @@ -1,5 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* + * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved. * Copyright (c) 2015-2021, The Linux Foundation. All rights reserved. */ @@ -110,6 +111,7 @@ struct dsi_display_boot_param { * @shadow_cphy_clks: Used for C-phy clock switch. */ struct dsi_display_clk_info { + struct dsi_clk_link_set xo_clks; struct dsi_clk_link_set src_clks; struct dsi_clk_link_set mux_clks; struct dsi_clk_link_set cphy_clks; diff --git a/msm/dsi/dsi_panel.c b/msm/dsi/dsi_panel.c index 687d1036628d..cdfeb88e6873 100644 --- a/msm/dsi/dsi_panel.c +++ b/msm/dsi/dsi_panel.c @@ -1,5 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* + * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved. * Copyright (c) 2016-2021, The Linux Foundation. All rights reserved. */ @@ -934,6 +935,15 @@ static int dsi_panel_parse_pixel_format(struct dsi_host_common_cfg *host, fmt = DSI_PIXEL_FORMAT_RGB666; break; case 30: + /* + * The destination pixel format (host->dst_format) depends + * upon the compression, and should be RGB888 if the DSC is + * enable. + * The DSC status information is inside the timing modes, that + * is parsed during first dsi_display_get_modes() call. + * The dst_format will be updated there depending upon the + * DSC status. + */ fmt = DSI_PIXEL_FORMAT_RGB101010; break; case 24: diff --git a/msm/msm_drv.h b/msm/msm_drv.h index 2c417ed21ad4..438c9abbec32 100644 --- a/msm/msm_drv.h +++ b/msm/msm_drv.h @@ -1,4 +1,5 @@ /* + * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved. * Copyright (c) 2016-2020, The Linux Foundation. All rights reserved. * Copyright (C) 2013 Red Hat * Author: Rob Clark @@ -1128,6 +1129,8 @@ struct drm_framebuffer *msm_framebuffer_create(struct drm_device *dev, struct drm_file *file, const struct drm_mode_fb_cmd2 *mode_cmd); struct drm_framebuffer * msm_alloc_stolen_fb(struct drm_device *dev, int w, int h, int p, uint32_t format); +int msm_fb_obj_get_attrs(struct drm_gem_object *obj, int *fb_ns, + int *fb_sec, int *fb_sec_dir, unsigned long *flags); struct drm_fb_helper *msm_fbdev_init(struct drm_device *dev); void msm_fbdev_free(struct drm_device *dev); diff --git a/msm/msm_fb.c b/msm/msm_fb.c index 5c59ac17f38a..2de3d8fd7177 100644 --- a/msm/msm_fb.c +++ b/msm/msm_fb.c @@ -1,4 +1,5 @@ /* + * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved. * Copyright (c) 2018-2020, The Linux Foundation. All rights reserved. * Copyright (C) 2013 Red Hat * Author: Rob Clark @@ -16,6 +17,8 @@ * this program. If not, see . */ +#include +#include #include #include #include @@ -378,3 +381,32 @@ msm_alloc_stolen_fb(struct drm_device *dev, int w, int h, int p, uint32_t format return fb; } + +int msm_fb_obj_get_attrs(struct drm_gem_object *obj, int *fb_ns, + int *fb_sec, int *fb_sec_dir, unsigned long *flags) +{ + + struct msm_gem_object *msm_obj = to_msm_bo(obj); + int ret = 0; + + if (!obj->import_attach) { + DRM_DEBUG("NULL attachment in drm gem object flags:0x%x\n", msm_obj->flags); + return -EINVAL; + } + + ret = dma_buf_get_flags(obj->import_attach->dmabuf, flags); + if (ret) { + DRM_ERROR("dma_buf_get_flags failure, err=%d\n", ret); + return ret; + } + + if (!(*flags & ION_FLAG_SECURE)) + *fb_ns = 1; + else if (*flags & ION_FLAG_CP_PIXEL) + *fb_sec = 1; + else if (*flags & (ION_FLAG_CP_SEC_DISPLAY | + ION_FLAG_CP_CAMERA_PREVIEW)) + *fb_sec_dir = 1; + + return ret; +} diff --git a/msm/sde/sde_plane.c b/msm/sde/sde_plane.c index 4afaf8abffb3..c8b1c78eb785 100644 --- a/msm/sde/sde_plane.c +++ b/msm/sde/sde_plane.c @@ -1,4 +1,5 @@ /* + * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved. * Copyright (C) 2014-2021 The Linux Foundation. All rights reserved. * Copyright (C) 2013 Red Hat * Author: Rob Clark @@ -1962,6 +1963,39 @@ static void sde_plane_cleanup_fb(struct drm_plane *plane, } +static int _sde_plane_validate_fb(struct sde_plane *psde, + struct drm_plane_state *state) +{ + struct sde_plane_state *pstate; + struct drm_framebuffer *fb; + uint32_t fb_ns = 0, fb_sec = 0, fb_sec_dir = 0; + unsigned long flags = 0; + int mode, ret = 0, n, i; + + pstate = to_sde_plane_state(state); + mode = sde_plane_get_property(pstate, + PLANE_PROP_FB_TRANSLATION_MODE); + + fb = state->fb; + n = fb->format->num_planes; + for (i = 0; i < n; i++) { + ret = msm_fb_obj_get_attrs(fb->obj[i], &fb_ns, &fb_sec, + &fb_sec_dir, &flags); + + if (!ret && ((fb_ns && (mode != SDE_DRM_FB_NON_SEC)) || + (fb_sec && (mode != SDE_DRM_FB_SEC)) || + (fb_sec_dir && (mode != SDE_DRM_FB_SEC_DIR_TRANS)))) { + SDE_ERROR_PLANE(psde, "mode:%d fb:%d dma_buf flags:0x%x rc:%d\n", + mode, fb->base.id, flags, ret); + SDE_EVT32(psde->base.base.id, fb->base.id, flags, + fb_ns, fb_sec, fb_sec_dir, ret, SDE_EVTLOG_ERROR); + return -EINVAL; + } + } + + return 0; +} + static void _sde_plane_sspp_atomic_check_mode_changed(struct sde_plane *psde, struct drm_plane_state *state, struct drm_plane_state *old_state) @@ -2631,6 +2665,11 @@ static int sde_plane_sspp_atomic_check(struct drm_plane *plane, return ret; ret = _sde_plane_validate_shared_crtc(psde, state); + if (ret) + return ret; + + ret = _sde_plane_validate_fb(psde, state); + if (ret) return ret;