diff --git a/drivers/video/fbdev/msm/mdss.h b/drivers/video/fbdev/msm/mdss.h index 1e93a5b2e9ba..5a24a1995af9 100644 --- a/drivers/video/fbdev/msm/mdss.h +++ b/drivers/video/fbdev/msm/mdss.h @@ -178,6 +178,7 @@ enum mdss_hw_capabilities { MDSS_CAPS_CWB_SUPPORTED, MDSS_CAPS_MDP_VOTE_CLK_NOT_SUPPORTED, MDSS_CAPS_AVR_SUPPORTED, + MDSS_CAPS_SEC_DETACH_SMMU, MDSS_CAPS_MAX, }; @@ -221,6 +222,7 @@ struct mdss_smmu_client { bool domain_attached; bool handoff_pending; void __iomem *mmu_base; + int domain; }; struct mdss_mdp_qseed3_lut_tbl { @@ -327,6 +329,7 @@ struct mdss_data_type { u32 wfd_mode; u32 has_no_lut_read; atomic_t sd_client_count; + atomic_t sc_client_count; u8 has_wb_ad; u8 has_non_scalar_rgb; bool has_src_split; @@ -519,6 +522,8 @@ struct mdss_data_type { u32 max_dest_scaler_input_width; u32 max_dest_scaler_output_width; struct mdss_mdp_destination_scaler *ds; + u32 sec_disp_en; + u32 sec_cam_en; }; extern struct mdss_data_type *mdss_res; @@ -579,6 +584,14 @@ static inline int mdss_get_sd_client_cnt(void) return atomic_read(&mdss_res->sd_client_count); } +static inline int mdss_get_sc_client_cnt(void) +{ + if (!mdss_res) + return 0; + else + return atomic_read(&mdss_res->sc_client_count); +} + static inline void mdss_set_quirk(struct mdss_data_type *mdata, enum mdss_hw_quirk bit) { diff --git a/drivers/video/fbdev/msm/mdss_mdp.c b/drivers/video/fbdev/msm/mdss_mdp.c index 04e8fa4ba576..1dae41391795 100644 --- a/drivers/video/fbdev/msm/mdss_mdp.c +++ b/drivers/video/fbdev/msm/mdss_mdp.c @@ -47,6 +47,8 @@ #include #include #include +#include "soc/qcom/secure_buffer.h" +#include #include "mdss.h" #include "mdss_fb.h" @@ -64,6 +66,8 @@ #define RES_1080p (1088*1920) #define RES_UHD (3840*2160) +#define MDP_DEVICE_ID 0x1A + struct mdss_data_type *mdss_res; static u32 mem_protect_sd_ctrl_id; @@ -87,6 +91,7 @@ struct msm_mdp_interface mdp5 = { #define MEM_PROTECT_SD_CTRL 0xF #define MEM_PROTECT_SD_CTRL_FLAT 0x14 +#define MEM_PROTECT_SD_CTRL_SWITCH 0x18 static DEFINE_SPINLOCK(mdp_lock); static DEFINE_SPINLOCK(mdss_mdp_intr_lock); @@ -1329,7 +1334,9 @@ int mdss_iommu_ctrl(int enable) if (mdata->iommu_ref_cnt == 0) { rc = mdss_smmu_detach(mdata); if (mdss_has_quirk(mdata, - MDSS_QUIRK_MIN_BUS_VOTE)) + MDSS_QUIRK_MIN_BUS_VOTE) && + (!mdata->sec_disp_en || + !mdata->sec_cam_en)) mdss_bus_scale_set_quota(MDSS_HW_RT, 0, 0); } @@ -1985,6 +1992,7 @@ static void mdss_mdp_hw_rev_caps_init(struct mdss_data_type *mdata) mdata->pixel_ram_size = 50 * 1024; mdata->rects_per_sspp[MDSS_MDP_PIPE_TYPE_DMA] = 2; + mem_protect_sd_ctrl_id = MEM_PROTECT_SD_CTRL_SWITCH; set_bit(MDSS_QOS_PER_PIPE_IB, mdata->mdss_qos_map); set_bit(MDSS_QOS_REMAPPER, mdata->mdss_qos_map); set_bit(MDSS_QOS_TS_PREFILL, mdata->mdss_qos_map); @@ -2015,6 +2023,7 @@ static void mdss_mdp_hw_rev_caps_init(struct mdss_data_type *mdata) mdata->has_wb_ubwc = true; set_bit(MDSS_CAPS_10_BIT_SUPPORTED, mdata->mdss_caps_map); set_bit(MDSS_CAPS_AVR_SUPPORTED, mdata->mdss_caps_map); + set_bit(MDSS_CAPS_SEC_DETACH_SMMU, mdata->mdss_caps_map); break; default: mdata->max_target_zorder = 4; /* excluding base layer */ @@ -4939,29 +4948,115 @@ static void mdss_mdp_footswitch_ctrl(struct mdss_data_type *mdata, int on) } } -int mdss_mdp_secure_display_ctrl(unsigned int enable) +int mdss_mdp_secure_session_ctrl(unsigned int enable, u64 flags) { + struct mdss_data_type *mdata = mdss_mdp_get_mdata(); struct sd_ctrl_req { unsigned int enable; } __attribute__ ((__packed__)) request; unsigned int resp = -1; int ret = 0; + uint32_t sid_info; struct scm_desc desc; - desc.args[0] = request.enable = enable; - desc.arginfo = SCM_ARGS(1); + if (test_bit(MDSS_CAPS_SEC_DETACH_SMMU, mdata->mdss_caps_map)) { + /* + * Prepare syscall to hypervisor to switch the secure_vmid + * between secure and non-secure contexts + */ + /* MDP secure SID */ + sid_info = 0x1; + desc.arginfo = SCM_ARGS(4, SCM_VAL, SCM_RW, SCM_VAL, SCM_VAL); + desc.args[0] = MDP_DEVICE_ID; + desc.args[1] = SCM_BUFFER_PHYS(&sid_info); + desc.args[2] = sizeof(uint32_t); - if (!is_scm_armv8()) { - ret = scm_call(SCM_SVC_MP, MEM_PROTECT_SD_CTRL, - &request, sizeof(request), &resp, sizeof(resp)); - } else { - ret = scm_call2(SCM_SIP_FNID(SCM_SVC_MP, + + pr_debug("Enable/Disable: %d, Flags %llx\n", enable, flags); + if (enable) { + if (flags & MDP_SECURE_DISPLAY_OVERLAY_SESSION) { + desc.args[3] = VMID_CP_SEC_DISPLAY; + mdata->sec_disp_en = 1; + } else if (flags & MDP_SECURE_CAMERA_OVERLAY_SESSION) { + desc.args[3] = VMID_CP_CAMERA_PREVIEW; + mdata->sec_cam_en = 1; + } else { + return 0; + } + + /* detach smmu contexts */ + ret = mdss_smmu_detach(mdata); + if (ret) { + pr_err("Error while detaching smmu contexts ret = %d\n", + ret); + return -EINVAL; + } + + /* let the driver think smmu is still attached */ + mdata->iommu_attached = true; + + dmac_flush_range(&sid_info, &sid_info + 1); + ret = scm_call2(SCM_SIP_FNID(SCM_SVC_MP, mem_protect_sd_ctrl_id), &desc); - resp = desc.ret[0]; - } + if (ret) { + pr_err("Error scm_call MEM_PROTECT_SD_CTRL(%u) ret=%dm resp=%x\n", + enable, ret, resp); + return -EINVAL; + } + resp = desc.ret[0]; - pr_debug("scm_call MEM_PROTECT_SD_CTRL(%u): ret=%d, resp=%x", + pr_debug("scm_call MEM_PROTECT_SD_CTRL(%u): ret=%d, resp=%x\n", + enable, ret, resp); + } else { + desc.args[3] = VMID_CP_PIXEL; + if (flags & MDP_SECURE_DISPLAY_OVERLAY_SESSION) + mdata->sec_disp_en = 0; + else if (flags & MDP_SECURE_CAMERA_OVERLAY_SESSION) + mdata->sec_cam_en = 0; + + dmac_flush_range(&sid_info, &sid_info + 1); + ret = scm_call2(SCM_SIP_FNID(SCM_SVC_MP, + mem_protect_sd_ctrl_id), &desc); + if (ret) + MDSS_XLOG_TOUT_HANDLER("mdp", "dsi0_ctrl", + "dsi0_phy", "dsi1_ctrl", + "dsi1_phy", "vbif", "vbif_nrt", + "dbg_bus", "vbif_dbg_bus", + "panic"); + resp = desc.ret[0]; + + pr_debug("scm_call MEM_PROTECT_SD_CTRL(%u): ret=%d, resp=%x\n", + enable, ret, resp); + + /* re-attach smmu contexts */ + mdata->iommu_attached = false; + ret = mdss_smmu_attach(mdata); + if (ret) { + pr_err("Error while attaching smmu contexts ret = %d\n", + ret); + return -EINVAL; + } + } + MDSS_XLOG(enable); + } else { + desc.args[0] = request.enable = enable; + desc.arginfo = SCM_ARGS(1); + + if (!is_scm_armv8()) { + ret = scm_call(SCM_SVC_MP, MEM_PROTECT_SD_CTRL, + &request, + sizeof(request), + &resp, + sizeof(resp)); + } else { + ret = scm_call2(SCM_SIP_FNID(SCM_SVC_MP, + mem_protect_sd_ctrl_id), &desc); + resp = desc.ret[0]; + } + + pr_debug("scm_call MEM_PROTECT_SD_CTRL(%u): ret=%d, resp=%x\n", enable, ret, resp); + } if (ret) return ret; diff --git a/drivers/video/fbdev/msm/mdss_mdp.h b/drivers/video/fbdev/msm/mdss_mdp.h index dc07fa8bf82e..e1c3841c82de 100644 --- a/drivers/video/fbdev/msm/mdss_mdp.h +++ b/drivers/video/fbdev/msm/mdss_mdp.h @@ -92,6 +92,8 @@ */ #define ENABLE_PIXEL_EXT_ONLY 0x80000000 +/* Pipe flag to indicate this pipe contains secure camera buffer */ +#define MDP_SECURE_CAMERA_OVERLAY_SESSION 0x100000000 /** * Destination Scaler control flags setting * @@ -629,7 +631,7 @@ struct mdss_mdp_img_data { dma_addr_t addr; unsigned long len; u32 offset; - u32 flags; + u64 flags; u32 dir; u32 domain; bool mapped; @@ -813,7 +815,7 @@ struct mdss_mdp_pipe { struct file *file; bool is_handed_off; - u32 flags; + u64 flags; u32 bwc_mode; /* valid only when pipe's output is crossing both layer mixers */ @@ -921,6 +923,7 @@ struct mdss_overlay_private { u32 splash_mem_addr; u32 splash_mem_size; u32 sd_enabled; + u32 sc_enabled; struct sw_sync_timeline *vsync_timeline; struct mdss_mdp_vsync_handler vsync_retire_handler; @@ -1294,6 +1297,15 @@ static inline void mdss_update_sd_client(struct mdss_data_type *mdata, atomic_add_unless(&mdss_res->sd_client_count, -1, 0); } +static inline void mdss_update_sc_client(struct mdss_data_type *mdata, + bool status) +{ + if (status) + atomic_inc(&mdata->sc_client_count); + else + atomic_add_unless(&mdss_res->sc_client_count, -1, 0); +} + static inline int mdss_mdp_get_wb_ctl_support(struct mdss_data_type *mdata, bool rotator_session) { @@ -1511,6 +1523,7 @@ static inline bool mdss_mdp_is_map_needed(struct mdss_data_type *mdata, struct mdss_mdp_img_data *data) { u32 is_secure_ui = data->flags & MDP_SECURE_DISPLAY_OVERLAY_SESSION; + u64 is_secure_camera = data->flags & MDP_SECURE_CAMERA_OVERLAY_SESSION; /* * For ULT Targets we need SMMU Map, to issue map call for secure Display. @@ -1518,6 +1531,10 @@ static inline bool mdss_mdp_is_map_needed(struct mdss_data_type *mdata, if (is_secure_ui && !mdss_has_quirk(mdata, MDSS_QUIRK_NEED_SECURE_MAP)) return false; + if (is_secure_camera && test_bit(MDSS_CAPS_SEC_DETACH_SMMU, + mdata->mdss_caps_map)) + return false; + return true; } @@ -1574,7 +1591,7 @@ unsigned long mdss_mdp_get_clk_rate(u32 clk_idx, bool locked); int mdss_mdp_vsync_clk_enable(int enable, bool locked); void mdss_mdp_clk_ctrl(int enable); struct mdss_data_type *mdss_mdp_get_mdata(void); -int mdss_mdp_secure_display_ctrl(unsigned int enable); +int mdss_mdp_secure_session_ctrl(unsigned int enable, u64 flags); int mdss_mdp_overlay_init(struct msm_fb_data_type *mfd); int mdss_mdp_dfps_update_params(struct msm_fb_data_type *mfd, @@ -1608,7 +1625,7 @@ int mdss_mdp_overlay_start(struct msm_fb_data_type *mfd); void mdss_mdp_overlay_set_chroma_sample( struct mdss_mdp_pipe *pipe); int mdp_pipe_tune_perf(struct mdss_mdp_pipe *pipe, - u32 flags); + u64 flags); int mdss_mdp_overlay_setup_scaling(struct mdss_mdp_pipe *pipe); struct mdss_mdp_pipe *mdss_mdp_pipe_assign(struct mdss_data_type *mdata, struct mdss_mdp_mixer *mixer, u32 ndx, @@ -1841,7 +1858,7 @@ struct mult_factor *mdss_mdp_get_comp_factor(u32 format, int mdss_mdp_data_map(struct mdss_mdp_data *data, bool rotator, int dir); void mdss_mdp_data_free(struct mdss_mdp_data *data, bool rotator, int dir); int mdss_mdp_data_get_and_validate_size(struct mdss_mdp_data *data, - struct msmfb_data *planes, int num_planes, u32 flags, + struct msmfb_data *planes, int num_planes, u64 flags, struct device *dev, bool rotator, int dir, struct mdp_layer_buffer *buffer); u32 mdss_get_panel_framerate(struct msm_fb_data_type *mfd); diff --git a/drivers/video/fbdev/msm/mdss_mdp_debug.c b/drivers/video/fbdev/msm/mdss_mdp_debug.c index 4c4fa9ea98d0..711d2d222c7d 100644 --- a/drivers/video/fbdev/msm/mdss_mdp_debug.c +++ b/drivers/video/fbdev/msm/mdss_mdp_debug.c @@ -1868,7 +1868,7 @@ static void __dump_pipe(struct seq_file *s, struct mdss_mdp_pipe *pipe) int smps[4]; int i; - seq_printf(s, "\nSSPP #%d type=%s ndx=%x flags=0x%08x play_cnt=%u xin_id=%d\n", + seq_printf(s, "\nSSPP #%d type=%s ndx=%x flags=0x%16llx play_cnt=%u xin_id=%d\n", pipe->num, mdss_mdp_pipetype2str(pipe->type), pipe->ndx, pipe->flags, pipe->play_cnt, pipe->xin_id); seq_printf(s, "\tstage=%d alpha=0x%x transp=0x%x blend_op=%d\n", diff --git a/drivers/video/fbdev/msm/mdss_mdp_layer.c b/drivers/video/fbdev/msm/mdss_mdp_layer.c index 1ff5d5e68575..20fcc26bb4bf 100644 --- a/drivers/video/fbdev/msm/mdss_mdp_layer.c +++ b/drivers/video/fbdev/msm/mdss_mdp_layer.c @@ -986,7 +986,7 @@ static int __configure_pipe_params(struct msm_fb_data_type *mfd, { int ret = 0; u32 left_lm_w = left_lm_w_from_mfd(mfd); - u32 flags; + u64 flags; struct mdss_mdp_mixer *mixer = NULL; struct mdss_overlay_private *mdp5_data = mfd_to_mdp5_data(mfd); @@ -1028,6 +1028,8 @@ static int __configure_pipe_params(struct msm_fb_data_type *mfd, pipe->flags |= MDP_BWC_EN; if (layer->flags & MDP_LAYER_PP) pipe->flags |= MDP_OVERLAY_PP_CFG_EN; + if (layer->flags & MDP_LAYER_SECURE_CAMERA_SESSION) + pipe->flags |= MDP_SECURE_CAMERA_OVERLAY_SESSION; pipe->scaler.enable = (layer->flags & SCALER_ENABLED); pipe->is_fg = layer->flags & MDP_LAYER_FORGROUND; @@ -1399,7 +1401,7 @@ static struct mdss_mdp_data *__map_layer_buffer(struct msm_fb_data_type *mfd, struct mdp_layer_buffer *buffer; struct msmfb_data image; int i, ret; - u32 flags; + u64 flags; struct mdss_mdp_validate_info_t *vitem; for (i = 0; i < layer_count; i++) { @@ -1425,7 +1427,8 @@ static struct mdss_mdp_data *__map_layer_buffer(struct msm_fb_data_type *mfd, } flags = (pipe->flags & (MDP_SECURE_OVERLAY_SESSION | - MDP_SECURE_DISPLAY_OVERLAY_SESSION)); + MDP_SECURE_DISPLAY_OVERLAY_SESSION | + MDP_SECURE_CAMERA_OVERLAY_SESSION)); if (buffer->planes[0].fd < 0) { pr_err("invalid file descriptor for layer buffer\n"); @@ -1636,34 +1639,48 @@ end: } /* - * __validate_secure_display() - validate secure display + * __validate_secure_session() - validate various secure sessions * * This function travers through used pipe list and checks if any pipe - * is with secure display enabled flag. It fails if client tries to stage - * unsecure content with secure display session. + * is with secure display, secure video and secure camera enabled flag. + * It fails if client tries to stage unsecure content with + * secure display session and secure camera with secure video sessions. * */ -static int __validate_secure_display(struct mdss_overlay_private *mdp5_data) +static int __validate_secure_session(struct mdss_overlay_private *mdp5_data) { struct mdss_mdp_pipe *pipe, *tmp; uint32_t sd_pipes = 0, nonsd_pipes = 0; + uint32_t secure_vid_pipes = 0, secure_cam_pipes = 0; mutex_lock(&mdp5_data->list_lock); list_for_each_entry_safe(pipe, tmp, &mdp5_data->pipes_used, list) { if (pipe->flags & MDP_SECURE_DISPLAY_OVERLAY_SESSION) sd_pipes++; + else if (pipe->flags & MDP_SECURE_OVERLAY_SESSION) + secure_vid_pipes++; + else if (pipe->flags & MDP_SECURE_CAMERA_OVERLAY_SESSION) + secure_cam_pipes++; else nonsd_pipes++; } mutex_unlock(&mdp5_data->list_lock); - pr_debug("pipe count:: secure display:%d non-secure:%d\n", - sd_pipes, nonsd_pipes); + pr_debug("pipe count:: secure display:%d non-secure:%d secure-vid:%d,secure-cam:%d\n", + sd_pipes, nonsd_pipes, secure_vid_pipes, secure_cam_pipes); - if ((sd_pipes || mdss_get_sd_client_cnt()) && nonsd_pipes) { + if ((sd_pipes || mdss_get_sd_client_cnt()) && + (nonsd_pipes || secure_vid_pipes || + secure_cam_pipes)) { pr_err("non-secure layer validation request during secure display session\n"); - pr_err(" secure client cnt:%d secure pipe cnt:%d non-secure pipe cnt:%d\n", - mdss_get_sd_client_cnt(), sd_pipes, nonsd_pipes); + pr_err(" secure client cnt:%d secure pipe:%d non-secure pipe:%d, secure-vid:%d, secure-cam:%d\n", + mdss_get_sd_client_cnt(), sd_pipes, nonsd_pipes, + secure_vid_pipes, secure_cam_pipes); + return -EINVAL; + } else if (secure_cam_pipes && (secure_vid_pipes || sd_pipes)) { + pr_err(" incompatible layers during secure camera session\n"); + pr_err("secure-camera cnt:%d secure video:%d secure display:%d\n", + secure_cam_pipes, secure_vid_pipes, sd_pipes); return -EINVAL; } else { return 0; @@ -2439,7 +2456,7 @@ static int __validate_layers(struct msm_fb_data_type *mfd, validate_skip: __handle_free_list(mdp5_data, validate_info_list, layer_count); - ret = __validate_secure_display(mdp5_data); + ret = __validate_secure_session(mdp5_data); validate_exit: pr_debug("err=%d total_layer:%d left:%d right:%d rec0_rel_ndx=0x%x rec1_rel_ndx=0x%x rec0_destroy_ndx=0x%x rec1_destroy_ndx=0x%x processed=%d\n", diff --git a/drivers/video/fbdev/msm/mdss_mdp_overlay.c b/drivers/video/fbdev/msm/mdss_mdp_overlay.c index 8c64dcd0655c..664850a1a617 100644 --- a/drivers/video/fbdev/msm/mdss_mdp_overlay.c +++ b/drivers/video/fbdev/msm/mdss_mdp_overlay.c @@ -396,7 +396,7 @@ int mdss_mdp_overlay_req_check(struct msm_fb_data_type *mfd, } int mdp_pipe_tune_perf(struct mdss_mdp_pipe *pipe, - u32 flags) + u64 flags) { struct mdss_data_type *mdata = pipe->mixer_left->ctl->mdata; struct mdss_mdp_perf_params perf; @@ -1188,11 +1188,10 @@ static void __overlay_pipe_cleanup(struct msm_fb_data_type *mfd, list_move(&buf->buf_list, &mdp5_data->bufs_freelist); /* - * in case of secure UI, the buffer needs to be released as - * soon as session is closed. + * free the buffers on the same cycle instead of waiting for + * next kickoff */ - if (pipe->flags & MDP_SECURE_DISPLAY_OVERLAY_SESSION) - mdss_mdp_overlay_buf_free(mfd, buf); + mdss_mdp_overlay_buf_free(mfd, buf); } mdss_mdp_pipe_destroy(pipe); @@ -1477,7 +1476,7 @@ static int __overlay_queue_pipes(struct msm_fb_data_type *mfd) */ if (mdss_get_sd_client_cnt() && !(pipe->flags & MDP_SECURE_DISPLAY_OVERLAY_SESSION)) { - pr_warn("Non secure pipe during secure display: %u: %08X, skip\n", + pr_warn("Non secure pipe during secure display: %u: %16llx, skip\n", pipe->num, pipe->flags); continue; } @@ -2110,6 +2109,92 @@ set_roi: mdss_mdp_set_roi(ctl, &l_roi, &r_roi); } +/* + * Enables/disable secure (display or camera) sessions + */ +static int __overlay_secure_ctrl(struct msm_fb_data_type *mfd) +{ + struct mdss_overlay_private *mdp5_data = mfd_to_mdp5_data(mfd); + struct mdss_mdp_ctl *ctl = mfd_to_ctl(mfd); + struct mdss_mdp_pipe *pipe; + int ret = 0; + int sd_in_pipe = 0; + int sc_in_pipe = 0; + + list_for_each_entry(pipe, &mdp5_data->pipes_used, list) { + if (pipe->flags & MDP_SECURE_DISPLAY_OVERLAY_SESSION) { + sd_in_pipe = 1; + pr_debug("Secure pipe: %u : %16llx\n", + pipe->num, pipe->flags); + } else if (pipe->flags & MDP_SECURE_CAMERA_OVERLAY_SESSION) { + sc_in_pipe = 1; + pr_debug("Secure camera: %u: %16llx\n", + pipe->num, pipe->flags); + } + } + + if ((!sd_in_pipe && !mdp5_data->sd_enabled) || + (sd_in_pipe && mdp5_data->sd_enabled) || + (!sc_in_pipe && !mdp5_data->sc_enabled) || + (sc_in_pipe && mdp5_data->sc_enabled)) + return ret; + + /* Secure Display */ + if (!mdp5_data->sd_enabled && sd_in_pipe) { + if (!mdss_get_sd_client_cnt()) { + /*wait for ping pong done */ + if (ctl->ops.wait_pingpong) + mdss_mdp_display_wait4pingpong(ctl, true); + ret = mdss_mdp_secure_session_ctrl(1, + MDP_SECURE_DISPLAY_OVERLAY_SESSION); + if (ret) + return ret; + } + mdp5_data->sd_enabled = 1; + mdss_update_sd_client(mdp5_data->mdata, true); + } else if (mdp5_data->sd_enabled && !sd_in_pipe) { + /* disable the secure display on last client */ + if (mdss_get_sd_client_cnt() == 1) { + if (ctl->ops.wait_pingpong) + mdss_mdp_display_wait4pingpong(ctl, true); + ret = mdss_mdp_secure_session_ctrl(0, + MDP_SECURE_DISPLAY_OVERLAY_SESSION); + if (ret) + return ret; + } + mdss_update_sd_client(mdp5_data->mdata, false); + mdp5_data->sd_enabled = 0; + } + + /* Secure Camera */ + if (!mdp5_data->sc_enabled && sc_in_pipe) { + if (!mdss_get_sc_client_cnt()) { + if (ctl->ops.wait_pingpong) + mdss_mdp_display_wait4pingpong(ctl, true); + ret = mdss_mdp_secure_session_ctrl(1, + MDP_SECURE_CAMERA_OVERLAY_SESSION); + if (ret) + return ret; + } + mdp5_data->sc_enabled = 1; + mdss_update_sc_client(mdp5_data->mdata, true); + } else if (mdp5_data->sc_enabled && !sc_in_pipe) { + /* disable the secure camera on last client */ + if (mdss_get_sc_client_cnt() == 1) { + if (ctl->ops.wait_pingpong) + mdss_mdp_display_wait4pingpong(ctl, true); + ret = mdss_mdp_secure_session_ctrl(0, + MDP_SECURE_CAMERA_OVERLAY_SESSION); + if (ret) + return ret; + } + mdss_update_sc_client(mdp5_data->mdata, false); + mdp5_data->sc_enabled = 0; + } + + return ret; +} + int mdss_mdp_overlay_kickoff(struct msm_fb_data_type *mfd, struct mdp_display_commit *data) { @@ -2117,7 +2202,6 @@ int mdss_mdp_overlay_kickoff(struct msm_fb_data_type *mfd, struct mdss_mdp_pipe *pipe, *tmp; struct mdss_mdp_ctl *ctl = mfd_to_ctl(mfd); int ret = 0; - int sd_in_pipe = 0; struct mdss_mdp_commit_cb commit_cb; if (!ctl) @@ -2148,30 +2232,12 @@ int mdss_mdp_overlay_kickoff(struct msm_fb_data_type *mfd, mutex_unlock(ctl->shared_lock); return ret; } + mutex_lock(&mdp5_data->list_lock); - - /* - * check if there is a secure display session - */ - list_for_each_entry(pipe, &mdp5_data->pipes_used, list) { - if (pipe->flags & MDP_SECURE_DISPLAY_OVERLAY_SESSION) { - sd_in_pipe = 1; - pr_debug("Secure pipe: %u : %08X\n", - pipe->num, pipe->flags); - } - } - - /* - * start secure display session if there is secure display session and - * sd_enabled is not true. - */ - if (!mdp5_data->sd_enabled && sd_in_pipe) { - if (!mdss_get_sd_client_cnt()) - ret = mdss_mdp_secure_display_ctrl(1); - if (!ret) { - mdp5_data->sd_enabled = 1; - mdss_update_sd_client(mdp5_data->mdata, true); - } + ret = __overlay_secure_ctrl(mfd); + if (IS_ERR_VALUE(ret)) { + pr_err("secure operation failed %d\n", ret); + goto commit_fail; } if (!ctl->shared_lock) @@ -2261,19 +2327,6 @@ int mdss_mdp_overlay_kickoff(struct msm_fb_data_type *mfd, } mutex_lock(&mdp5_data->ov_lock); - /* - * If there is no secure display session and sd_enabled, disable the - * secure display session - */ - if (mdp5_data->sd_enabled && !sd_in_pipe && !ret) { - /* disable the secure display on last client */ - if (mdss_get_sd_client_cnt() == 1) - ret = mdss_mdp_secure_display_ctrl(0); - if (!ret) { - mdss_update_sd_client(mdp5_data->mdata, false); - mdp5_data->sd_enabled = 0; - } - } mdss_fb_update_notify_update(mfd); commit_fail: @@ -2425,7 +2478,7 @@ static int mdss_mdp_overlay_queue(struct msm_fb_data_type *mfd, struct mdss_mdp_data *src_data; struct mdp_layer_buffer buffer; int ret; - u32 flags; + u64 flags; pipe = __overlay_find_pipe(mfd, req->id); if (!pipe) { @@ -2451,7 +2504,8 @@ static int mdss_mdp_overlay_queue(struct msm_fb_data_type *mfd, pr_warn("Unexpected buffer queue to a solid fill pipe\n"); flags = (pipe->flags & (MDP_SECURE_OVERLAY_SESSION | - MDP_SECURE_DISPLAY_OVERLAY_SESSION)); + MDP_SECURE_DISPLAY_OVERLAY_SESSION | + MDP_SECURE_CAMERA_OVERLAY_SESSION)); mutex_lock(&mdp5_data->list_lock); src_data = mdss_mdp_overlay_buf_alloc(mfd, pipe); diff --git a/drivers/video/fbdev/msm/mdss_mdp_pipe.c b/drivers/video/fbdev/msm/mdss_mdp_pipe.c index 7591ebc3e2ee..e370a80ad998 100644 --- a/drivers/video/fbdev/msm/mdss_mdp_pipe.c +++ b/drivers/video/fbdev/msm/mdss_mdp_pipe.c @@ -1878,7 +1878,8 @@ static void mdss_mdp_pipe_stride_update(struct mdss_mdp_pipe *pipe) if (pipe->multirect.mode == MDSS_MDP_PIPE_MULTIRECT_NONE) { memcpy(&ystride, &pipe->src_planes.ystride, sizeof(u32) * MAX_PLANES); - if (pipe->flags & MDP_SECURE_OVERLAY_SESSION) + if (pipe->flags & (MDP_SECURE_OVERLAY_SESSION | + MDP_SECURE_CAMERA_OVERLAY_SESSION)) secure = 0xF; } else { if (pipe->multirect.num == MDSS_MDP_PIPE_RECT0) { @@ -1891,12 +1892,14 @@ static void mdss_mdp_pipe_stride_update(struct mdss_mdp_pipe *pipe) ystride[0] = rec0_pipe->src_planes.ystride[0]; ystride[2] = rec0_pipe->src_planes.ystride[2]; - if (rec0_pipe->flags & MDP_SECURE_OVERLAY_SESSION) + if (rec0_pipe->flags & (MDP_SECURE_OVERLAY_SESSION | + MDP_SECURE_CAMERA_OVERLAY_SESSION)) secure |= 0x5; ystride[1] = rec1_pipe->src_planes.ystride[0]; ystride[3] = rec1_pipe->src_planes.ystride[2]; - if (rec1_pipe->flags & MDP_SECURE_OVERLAY_SESSION) + if (rec1_pipe->flags & (MDP_SECURE_OVERLAY_SESSION | + MDP_SECURE_CAMERA_OVERLAY_SESSION)) secure |= 0xA; } @@ -2320,7 +2323,9 @@ static int mdss_mdp_pipe_solidfill_setup(struct mdss_mdp_pipe *pipe) } format = MDSS_MDP_FMT_SOLID_FILL; - secure = (pipe->flags & MDP_SECURE_OVERLAY_SESSION ? 0xF : 0x0); + secure = (pipe->flags & (MDP_SECURE_OVERLAY_SESSION | + MDP_SECURE_CAMERA_OVERLAY_SESSION) + ? 0xF : 0x0); /* support ARGB color format only */ unpack = (C3_ALPHA << 24) | (C2_R_Cr << 16) | diff --git a/drivers/video/fbdev/msm/mdss_mdp_util.c b/drivers/video/fbdev/msm/mdss_mdp_util.c index bc1ecf1dbc29..199c2b66d90e 100644 --- a/drivers/video/fbdev/msm/mdss_mdp_util.c +++ b/drivers/video/fbdev/msm/mdss_mdp_util.c @@ -971,16 +971,17 @@ static int mdss_mdp_put_img(struct mdss_mdp_img_data *data, bool rotator, data->srcp_dma_buf = NULL; } } - } else if (data->flags & MDP_SECURE_DISPLAY_OVERLAY_SESSION) { + } else if ((data->flags & MDP_SECURE_DISPLAY_OVERLAY_SESSION) || + (data->flags & MDP_SECURE_CAMERA_OVERLAY_SESSION)) { /* - * skip memory unmapping - secure display uses physical - * address which does not require buffer unmapping + * skip memory unmapping - secure display and camera uses + * physical address which does not require buffer unmapping * * For LT targets in secure display usecase, srcp_dma_buf will * be filled due to map call which will be unmapped above. * */ - pr_debug("skip memory unmapping for secure display content\n"); + pr_debug("skip memory unmapping for secure display/camera content\n"); } else { return -ENOMEM; } @@ -1196,7 +1197,7 @@ err_unmap: } static int mdss_mdp_data_get(struct mdss_mdp_data *data, - struct msmfb_data *planes, int num_planes, u32 flags, + struct msmfb_data *planes, int num_planes, u64 flags, struct device *dev, bool rotator, int dir) { int i, rc = 0; @@ -1209,7 +1210,7 @@ static int mdss_mdp_data_get(struct mdss_mdp_data *data, rc = mdss_mdp_get_img(&planes[i], &data->p[i], dev, rotator, dir); if (rc) { - pr_err("failed to get buf p=%d flags=%x\n", i, flags); + pr_err("failed to get buf p=%d flags=%llx\n", i, flags); while (i > 0) { i--; mdss_mdp_put_img(&data->p[i], rotator, dir); @@ -1259,7 +1260,7 @@ void mdss_mdp_data_free(struct mdss_mdp_data *data, bool rotator, int dir) } int mdss_mdp_data_get_and_validate_size(struct mdss_mdp_data *data, - struct msmfb_data *planes, int num_planes, u32 flags, + struct msmfb_data *planes, int num_planes, u64 flags, struct device *dev, bool rotator, int dir, struct mdp_layer_buffer *buffer) { diff --git a/drivers/video/fbdev/msm/mdss_smmu.c b/drivers/video/fbdev/msm/mdss_smmu.c index eab7bcaaa156..2239791fdad0 100644 --- a/drivers/video/fbdev/msm/mdss_smmu.c +++ b/drivers/video/fbdev/msm/mdss_smmu.c @@ -162,12 +162,15 @@ end: } /* - * mdss_smmu_v2_attach() + * mdss_smmu_attach_v2() * * Associates each configured VA range with the corresponding smmu context * bank device. Enables the clks as smmu_v2 requires voting it before the usage. * And iommu attach is done only once during the initial attach and it is never * detached as smmu v2 uses a feature called 'retention'. + * Only detach the secure and non-secure contexts in case of secure display + * case and secure contexts for secure camera use cases for the platforms + * which have caps MDSS_CAPS_SEC_DETACH_SMMU enabled */ static int mdss_smmu_attach_v2(struct mdss_data_type *mdata) { @@ -191,7 +194,9 @@ static int mdss_smmu_attach_v2(struct mdss_data_type *mdata) } mdss_smmu->handoff_pending = false; - if (!mdss_smmu->domain_attached) { + if (!mdss_smmu->domain_attached && + mdss_smmu_is_valid_domain_condition(mdata, + i, true)) { rc = arm_iommu_attach_device(mdss_smmu->dev, mdss_smmu->mmu_mapping); if (rc) { @@ -229,10 +234,11 @@ err: } /* - * mdss_smmu_v2_detach() + * mdss_smmu_detach_v2() * - * Only disables the clks as it is not required to detach the iommu mapped - * VA range from the device in smmu_v2 as explained in the mdss_smmu_v2_attach + * Disables the clks only when it is not required to detach the iommu mapped + * VA range (as long as not in secure display use case) + * from the device in smmu_v2 as explained in the mdss_smmu_v2_attach */ static int mdss_smmu_detach_v2(struct mdss_data_type *mdata) { @@ -245,8 +251,24 @@ static int mdss_smmu_detach_v2(struct mdss_data_type *mdata) continue; mdss_smmu = mdss_smmu_get_cb(i); - if (mdss_smmu && mdss_smmu->dev && !mdss_smmu->handoff_pending) - mdss_smmu_enable_power(mdss_smmu, false); + if (mdss_smmu && mdss_smmu->dev) { + if (!mdss_smmu->handoff_pending && + mdss_smmu->domain_attached && + mdss_smmu_is_valid_domain_condition(mdata, + i, false)) { + /* + * if entering in secure display or + * secure camera use case(for secured contexts + * leave the smmu clocks on and only detach the + * smmu contexts + */ + arm_iommu_detach_device(mdss_smmu->dev); + mdss_smmu->domain_attached = false; + pr_debug("iommu v2 domain[%i] detached\n", i); + } else { + mdss_smmu_enable_power(mdss_smmu, false); + } + } } mutex_unlock(&mdp_iommu_lock); @@ -609,6 +631,7 @@ int mdss_smmu_probe(struct platform_device *pdev) } mdss_smmu = &mdata->mdss_smmu[smmu_domain.domain]; + mdss_smmu->domain = smmu_domain.domain; mp = &mdss_smmu->mp; memset(mp, 0, sizeof(struct dss_module_power)); diff --git a/drivers/video/fbdev/msm/mdss_smmu.h b/drivers/video/fbdev/msm/mdss_smmu.h index a987066cc773..f7e6e275c16a 100644 --- a/drivers/video/fbdev/msm/mdss_smmu.h +++ b/drivers/video/fbdev/msm/mdss_smmu.h @@ -73,6 +73,38 @@ static inline bool mdss_smmu_is_valid_domain_type(struct mdss_data_type *mdata, return true; } +static inline bool mdss_smmu_is_valid_domain_condition( + struct mdss_data_type *mdata, + int domain_type, + bool is_attach) +{ + if (is_attach) { + if (test_bit(MDSS_CAPS_SEC_DETACH_SMMU, + mdata->mdss_caps_map) && + (mdata->sec_disp_en || + (mdata->sec_cam_en && + domain_type == MDSS_IOMMU_DOMAIN_SECURE))) { + pr_debug("SMMU attach not attempted, sd:%d, sc:%d\n", + mdata->sec_disp_en, mdata->sec_cam_en); + return false; + } else { + return true; + } + } else { + if (test_bit(MDSS_CAPS_SEC_DETACH_SMMU, + mdata->mdss_caps_map) && + (mdata->sec_disp_en || + (mdata->sec_cam_en && + domain_type == MDSS_IOMMU_DOMAIN_SECURE))) { + pr_debug("SMMU detach attempted, sd:%d, sc:%d\n", + mdata->sec_disp_en, mdata->sec_cam_en); + return true; + } else { + return false; + } + } +} + static inline struct mdss_smmu_client *mdss_smmu_get_cb(u32 domain) { struct mdss_data_type *mdata = mdss_mdp_get_mdata(); @@ -96,7 +128,7 @@ static inline int is_mdss_iommu_attached(void) return mdata ? mdata->iommu_attached : false; } -static inline int mdss_smmu_get_domain_type(u32 flags, bool rotator) +static inline int mdss_smmu_get_domain_type(u64 flags, bool rotator) { struct mdss_data_type *mdata = mdss_mdp_get_mdata(); int type;