Loading drivers/video/msm/mdss/mdp3.c +6 −1 Original line number Diff line number Diff line Loading @@ -47,6 +47,7 @@ #include <linux/qcom_iommu.h> #include <linux/msm_iommu_domains.h> #include <linux/vmalloc.h> #include <soc/qcom/scm.h> #include <linux/msm_dma_iommu_mapping.h> Loading Loading @@ -2956,7 +2957,7 @@ int mdp3_panel_get_intf_status(u32 disp_num, u32 intf_type) static int mdp3_probe(struct platform_device *pdev) { int rc; int rc, scm_ret = 0; static struct msm_mdp_interface mdp3_interface = { .init_fnc = mdp3_init, .fb_mem_get_iommu_domain = mdp3_fb_mem_get_iommu_domain, Loading Loading @@ -3083,6 +3084,10 @@ static int mdp3_probe(struct platform_device *pdev) __mdp3_set_supported_formats(); rc = scm_restore_sec_cfg(SEC_DEVICE_MDP3, 0, &scm_ret); if (rc) pr_err("Restore secure cfg failed\n"); mdp3_res->mdss_util->mdp_probe_done = true; pr_debug("%s: END\n", __func__); Loading drivers/video/msm/mdss/mdp3.h +7 −0 Original line number Diff line number Diff line Loading @@ -31,6 +31,7 @@ #define MDP_CORE_CLK_RATE_SVS 160000000 #define MDP_CORE_CLK_RATE_SUPER_SVS 200000000 #define MDP_CORE_CLK_RATE_MAX 307200000 #define SEC_DEVICE_MDP3 1 #define CLK_FUDGE_NUM 12 #define CLK_FUDGE_DEN 10 Loading Loading @@ -96,6 +97,12 @@ enum { DI_MAX, }; enum mdp3_sd_transition { NO_TRANSITION, NONSECURE_TO_SECURE, SECURE_TO_NONSECURE, }; struct mdp3_bus_handle_map { struct msm_bus_vectors *bus_vector; struct msm_bus_paths *usecases; Loading drivers/video/msm/mdss/mdp3_ctrl.c +157 −8 Original line number Diff line number Diff line Loading @@ -25,6 +25,7 @@ #include <linux/sw_sync.h> #include <linux/iommu.h> #include <linux/msm_ion.h> #include <soc/qcom/scm.h> #include "mdp3_ctrl.h" #include "mdp3.h" Loading @@ -33,6 +34,7 @@ #include "mdss_spi_panel.h" #define VSYNC_EXPIRE_TICK 4 #define MEM_PROTECT_SD_CTRL 0xF static void mdp3_ctrl_pan_display(struct msm_fb_data_type *mfd); static int mdp3_overlay_unset(struct msm_fb_data_type *mfd, int ndx); Loading Loading @@ -397,12 +399,46 @@ void mdp3_vsync_timer_func(unsigned long arg) } } int config_secure_display(struct mdp3_session_data *mdp3_session) { struct sd_ctrl_req { unsigned int enable; } __attribute__ ((__packed__)) request; unsigned int resp = -1; int ret = 0; struct scm_desc desc; if (mdp3_session->transition_state == NONSECURE_TO_SECURE) atomic_inc(&mdp3_session->secure_display); else if (mdp3_session->transition_state == SECURE_TO_NONSECURE) atomic_dec(&mdp3_session->secure_display); request.enable = atomic_read(&mdp3_session->secure_display); desc.args[0] = request.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), &desc); resp = desc.ret[0]; } pr_debug("scm_call MEM_PROTECT_SD_CTRL(%u): ret=%di resp =%d\n", request.enable, ret, resp); return resp; } static int mdp3_ctrl_async_blit_req(struct msm_fb_data_type *mfd, void __user *p) { struct mdp_async_blit_req_list req_list_header; int rc, count; void __user *p_req; struct mdp3_session_data *session; if (copy_from_user(&req_list_header, p, sizeof(req_list_header))) return -EFAULT; Loading @@ -410,6 +446,23 @@ static int mdp3_ctrl_async_blit_req(struct msm_fb_data_type *mfd, count = req_list_header.count; if (count < 0 || count > MAX_BLIT_REQ) return -EINVAL; if (!mfd || !mfd->mdp.private1) return -EINVAL; session = (struct mdp3_session_data *)mfd->mdp.private1; if (atomic_read(&session->secure_display) && (mdp3_ctrl_get_intf_type(mfd) == MDP3_DMA_OUTPUT_SEL_DSI_VIDEO)) { rc = wait_for_completion_timeout(&session->secure_completion, msecs_to_jiffies(84)); if (rc) { pr_err("Timed out waiting for completion of secure display\n"); return rc; } } rc = mdp3_ppp_parse_req(p_req, &req_list_header, 1); if (!rc) rc = copy_to_user(p, &req_list_header, sizeof(req_list_header)); Loading Loading @@ -895,6 +948,7 @@ static int mdp3_ctrl_on(struct msm_fb_data_type *mfd) int rc = 0; struct mdp3_session_data *mdp3_session; struct mdss_panel_data *panel; int scm_ret = 0; pr_debug("mdp3_ctrl_on\n"); mdp3_session = (struct mdp3_session_data *)mfd->mdp.private1; Loading Loading @@ -940,6 +994,10 @@ static int mdp3_ctrl_on(struct msm_fb_data_type *mfd) goto end; } rc = scm_restore_sec_cfg(SEC_DEVICE_MDP3, 0, &scm_ret); if (rc) pr_err("Restoring secure cfg failed\n"); /* * Get a reference to the runtime pm device. * If idle pc feature is enabled, it will be released Loading Loading @@ -1505,7 +1563,8 @@ static int mdp3_ctrl_display_commit_kickoff(struct msm_fb_data_type *mfd, struct mdss_panel_data *panel; int frame_rate = DEFAULT_FRAME_RATE; int stride; bool null_commit = false; bool is_panel_type_cmd = false; if (!mfd || !mfd->mdp.private1) return -EINVAL; Loading @@ -1520,7 +1579,34 @@ static int mdp3_ctrl_display_commit_kickoff(struct msm_fb_data_type *mfd, if (mdp3_bufq_count(&mdp3_session->bufq_in) == 0) { pr_debug("no buffer in queue yet\n"); return -EPERM; null_commit = true; } if (null_commit && mdp3_ctrl_get_intf_type(mfd) == MDP3_DMA_OUTPUT_SEL_DSI_VIDEO) { mutex_lock(&mdp3_session->lock); reinit_completion(&mdp3_session->secure_completion); mdp3_ctrl_reset_countdown(mdp3_session, mfd); mdp3_ctrl_clk_enable(mfd, 1); rc = mdp3_session->dma->handle_null_commit(mdp3_session->dma, mdp3_session->intf); if (atomic_read(&mdp3_session->secure_display)) { mdp3_session->transition_state = SECURE_TO_NONSECURE; rc = config_secure_display(mdp3_session); if (rc) pr_err("Configuring secure display failed\n"); } complete_all(&mdp3_session->secure_completion); mdp3_ctrl_notify(mdp3_session, MDP_NOTIFY_FRAME_DONE); if (mdp3_bufq_count(&mdp3_session->bufq_out) > 0) { data = mdp3_bufq_pop(&mdp3_session->bufq_out); if (data) mdp3_put_img(data, MDP3_CLIENT_DMA_P); } mdp3_session->vsync_before_commit = 0; mutex_unlock(&mdp3_session->lock); return 0; } if (panel_info->partial_update_enabled && Loading Loading @@ -1562,6 +1648,10 @@ static int mdp3_ctrl_display_commit_kickoff(struct msm_fb_data_type *mfd, return -EPERM; } MDSS_XLOG(0x111); if (mfd->panel.type == MIPI_CMD_PANEL || client == MDP3_CLIENT_SPI) is_panel_type_cmd = true; mdp3_ctrl_notify(mdp3_session, MDP_NOTIFY_FRAME_BEGIN); data = mdp3_bufq_pop(&mdp3_session->bufq_in); if (data) { Loading @@ -1577,20 +1667,76 @@ static int mdp3_ctrl_display_commit_kickoff(struct msm_fb_data_type *mfd, rc = mdss_spi_panel_kickoff(mdp3_session->panel, (void *)(int)data->addr, (int)data->len, stride); } else if (mdp3_session->dma->update_src_cfg && goto frame_done; } else if (mdp3_session->dma->output_config.out_sel == MDP3_DMA_OUTPUT_SEL_DSI_CMD) { rc = mdp3_session->dma->wait_for_dma(mdp3_session->dma, mdp3_session->intf); if (!rc && !mdp3_session->first_commit) { pr_err("dma done timedout\n"); mutex_unlock(&mdp3_session->lock); return -ETIMEDOUT; } } /* For command mode panels, the secure display should be enabled * only after the previous dma done is completed */ if (mdp3_session->transition_state != NO_TRANSITION) { rc = config_secure_display(mdp3_session); if (rc) { pr_err("Configuring secure display failed\n"); mutex_unlock(&mdp3_session->lock); return -EINVAL; } } if (is_panel_type_cmd) { rc = mdp3_iommu_enable(client); if (rc) { pr_err("failed to enable iommu\n"); mdp3_put_img(data, client); mutex_unlock(&mdp3_session->lock); return rc; } } rc = mdp3_map_layer(data, MDP3_CLIENT_DMA_P); if (data->len < mdp3_session->dma->source_config.stride * mdp3_session->dma->source_config.height) { pr_err("buf size(0x%lx) is smaller than dma config(0x%x)\n", data->len, (mdp3_session->dma->source_config.stride * mdp3_session->dma->source_config.height)); mdp3_put_img(data, client); if (is_panel_type_cmd) mdp3_iommu_disable(client); mutex_unlock(&mdp3_session->lock); return -EINVAL; } if (is_panel_type_cmd) mdp3_iommu_disable(client); if (mdp3_session->dma->update_src_cfg && panel_info->partial_update_enabled) { panel->panel_info.roi.x = mdp3_session->dma->roi.x; panel->panel_info.roi.y = mdp3_session->dma->roi.y; panel->panel_info.roi.w = mdp3_session->dma->roi.w; panel->panel_info.roi.h = mdp3_session->dma->roi.h; rc = mdp3_session->dma->update(mdp3_session->dma, (void *)(int)data->addr, mdp3_session->intf, (void *)panel); (void *)(int)data->addr, mdp3_session->intf, (void *)panel, atomic_read(&mdp3_session->secure_display)); } else { rc = mdp3_session->dma->update(mdp3_session->dma, (void *)(int)data->addr, mdp3_session->intf, NULL); (void *)(int)data->addr, mdp3_session->intf, NULL, atomic_read(&mdp3_session->secure_display)); } frame_done: /* This is for the previous frame */ if (rc < 0) { mdp3_ctrl_notify(mdp3_session, Loading Loading @@ -1746,7 +1892,8 @@ static void mdp3_ctrl_pan_display(struct msm_fb_data_type *mfd) } rc = mdp3_session->dma->update(mdp3_session->dma, (void *)(int)(mfd->iova + offset), mdp3_session->intf, NULL); mdp3_session->intf, NULL, atomic_read(&mdp3_session->secure_display)); /* This is for the previous frame */ if (rc < 0) { mdp3_ctrl_notify(mdp3_session, Loading Loading @@ -3058,6 +3205,7 @@ int mdp3_ctrl_init(struct msm_fb_data_type *mfd) mdp3_session->histo_status = 0; mdp3_session->lut_sel = 0; BLOCKING_INIT_NOTIFIER_HEAD(&mdp3_session->notifier_head); atomic_set(&mdp3_session->secure_display, 0); init_timer(&mdp3_session->vsync_timer); mdp3_session->vsync_timer.function = mdp3_vsync_timer_func; Loading @@ -3065,6 +3213,7 @@ int mdp3_ctrl_init(struct msm_fb_data_type *mfd) mdp3_session->vsync_period = 1000 / frame_rate; mfd->mdp.private1 = mdp3_session; init_completion(&mdp3_session->dma_completion); init_completion(&mdp3_session->secure_completion); if (intf_type != MDP3_DMA_OUTPUT_SEL_DSI_VIDEO || intf_type != MDP3_DMA_OUTPUT_SEL_SPI_CMD) mdp3_session->wait_for_dma_done = mdp3_wait_for_dma_done; Loading drivers/video/msm/mdss/mdp3_ctrl.h +5 −1 Original line number Diff line number Diff line Loading @@ -76,12 +76,16 @@ struct mdp3_session_data { bool dma_active; struct completion dma_completion; struct completion secure_completion; int (*wait_for_dma_done)(struct mdp3_session_data *session); /* For retire fence */ struct sw_sync_timeline *vsync_timeline; int retire_cnt; struct work_struct retire_work; atomic_t secure_display; int transition_state; }; void mdp3_bufq_deinit(struct mdp3_buffer_queue *bufq, int client); Loading @@ -92,6 +96,6 @@ int mdp3_ctrl_get_source_format(u32 imgType); int mdp3_ctrl_get_pack_pattern(u32 imgType); int mdp3_ctrl_reset(struct msm_fb_data_type *mfd); int mdp3_get_ion_client(struct msm_fb_data_type *mfd); int config_secure_display(struct mdp3_session_data *mdp3_session); #endif /* MDP3_CTRL_H */ drivers/video/msm/mdss/mdp3_dma.c +110 −25 Original line number Diff line number Diff line Loading @@ -17,6 +17,7 @@ #include "mdp3_dma.h" #include "mdp3_hwio.h" #include "mdss_debug.h" #include "mdp3_ctrl.h" #define DMA_STOP_POLL_SLEEP_US 1000 #define DMA_STOP_POLL_TIMEOUT_US 200000 Loading Loading @@ -351,7 +352,7 @@ static int mdp3_dmap_config(struct mdp3_dma *dma, return 0; } static void mdp3_dmap_config_source(struct mdp3_dma *dma) static void mdp3_dmap_config_source(struct mdp3_dma *dma, bool enable_secure) { struct mdp3_dma_source *source_config = &dma->source_config; u32 dma_p_cfg_reg, dma_p_size; Loading @@ -364,6 +365,11 @@ static void mdp3_dmap_config_source(struct mdp3_dma *dma) dma_p_size = dma->roi.w | (dma->roi.h << 16); if (enable_secure) dma_p_cfg_reg |= BIT(21); else dma_p_cfg_reg &= ~BIT(21); MDP3_REG_WRITE(MDP3_REG_DMA_P_CONFIG, dma_p_cfg_reg); MDP3_REG_WRITE(MDP3_REG_DMA_P_SIZE, dma_p_size); MDP3_REG_WRITE(MDP3_REG_DMA_P_IBUF_Y_STRIDE, source_config->stride); Loading Loading @@ -406,7 +412,7 @@ static int mdp3_dmas_config(struct mdp3_dma *dma, return 0; } static void mdp3_dmas_config_source(struct mdp3_dma *dma) static void mdp3_dmas_config_source(struct mdp3_dma *dma, bool enable_secure) { struct mdp3_dma_source *source_config = &dma->source_config; u32 dma_s_cfg_reg, dma_s_size; Loading Loading @@ -654,46 +660,119 @@ int dma_bpp(int format) return bpp; } static int mdp3_dmap_update(struct mdp3_dma *dma, void *buf, struct mdp3_intf *intf, void *data) static int mdp3_handle_null_commit(struct mdp3_dma *dma, struct mdp3_intf *intf) { int rc = 0; int retry_count = 2; unsigned long flag; int cb_type = MDP3_DMA_CALLBACK_TYPE_VSYNC; struct mdss_panel_data *panel; if (!dma->source_config.format && !dma->source_config.stride) { pr_debug("Null commit already handled\n"); return 0; } /* * Size and stride are set to 0 to ensure that DMA pipe does not * fetch anything whenever we get a null commit. The values will be * reconfigured to the correct values in the next commit. */ MDP3_REG_WRITE(MDP3_REG_DMA_P_SIZE, 0); MDP3_REG_WRITE(MDP3_REG_DMA_P_IBUF_Y_STRIDE, 0); spin_lock_irqsave(&dma->dma_lock, flag); dma->source_config.format = 0; dma->source_config.stride = 0; mdp3_irq_disable(MDP3_INTR_LCDC_UNDERFLOW); MDP3_REG_WRITE(MDP3_REG_DSI_VIDEO_UNDERFLOW_CTL, 0x80000000); if (!intf->active) { pr_debug("%s start interface\n", __func__); intf->start(intf); } /* * Make sure that all the configurations required for * null commit is done before waiting for the vsync. */ mb(); dma->vsync_status = MDP3_REG_READ(MDP3_REG_INTR_STATUS) & (1 << MDP3_INTR_LCDC_START_OF_FRAME); init_completion(&dma->vsync_comp); spin_unlock_irqrestore(&dma->dma_lock, flag); mdp3_dma_callback_enable(dma, cb_type); retry_vsync: pr_debug("wait for vsync_comp started\n"); rc = wait_for_completion_timeout(&dma->vsync_comp, KOFF_TIMEOUT); if (rc <= 0 && --retry_count) { int vsync = MDP3_REG_READ(MDP3_REG_INTR_STATUS) & (1 << MDP3_INTR_LCDC_START_OF_FRAME); if (!vsync) { pr_err("%s trying again count = %d\n", __func__, retry_count); goto retry_vsync; } rc = -1; } pr_debug("wait for vsync_comp done\n"); return rc; } static int mdp3_wait_for_dma_comp(struct mdp3_dma *dma, struct mdp3_intf *intf) { int vsync_status; int rc = 0; int retry_count = 2; ATRACE_BEGIN(__func__); pr_debug("mdp3_dmap_update\n"); MDSS_XLOG(XLOG_FUNC_ENTRY, __LINE__); if (dma->output_config.out_sel == MDP3_DMA_OUTPUT_SEL_DSI_CMD) { cb_type = MDP3_DMA_CALLBACK_TYPE_DMA_DONE; if (intf->active) { ATRACE_BEGIN("mdp3_wait_for_dma_comp"); retry_dma_done: rc = wait_for_completion_timeout(&dma->dma_comp, KOFF_TIMEOUT); if (rc <= 0 && --retry_count) { int vsync_status; vsync_status = (1 << MDP3_INTR_DMA_P_DONE) & MDP3_REG_READ(MDP3_REG_INTR_STATUS); if (!vsync_status) { pr_err("%s: cmd timeout retry cnt %d\n", __func__, retry_count); goto retry_dma_done; } else { rc = 1; } rc = -1; } ATRACE_END("mdp3_wait_for_dma_comp"); } return rc; } static int mdp3_dmap_update(struct mdp3_dma *dma, void *buf, struct mdp3_intf *intf, void *data, bool secure) { unsigned long flag; int cb_type = MDP3_DMA_CALLBACK_TYPE_VSYNC; struct mdss_panel_data *panel; int rc = 0; int retry_count = 2; int vsync = 0; ATRACE_BEGIN(__func__); pr_debug("mdp3_dmap_update\n"); MDSS_XLOG(XLOG_FUNC_ENTRY, __LINE__); if (dma->output_config.out_sel == MDP3_DMA_OUTPUT_SEL_DSI_CMD) { cb_type = MDP3_DMA_CALLBACK_TYPE_DMA_DONE; } if (dma->update_src_cfg) { if (dma->output_config.out_sel == MDP3_DMA_OUTPUT_SEL_DSI_VIDEO && intf->active) pr_err("configuring dma source while it is active\n"); dma->dma_config_source(dma); dma->dma_config_source(dma, secure); if (data) { panel = (struct mdss_panel_data *)data; if (panel->event_handler) { Loading Loading @@ -737,7 +816,7 @@ retry_vsync: rc = wait_for_completion_timeout(&dma->vsync_comp, KOFF_TIMEOUT); if (rc <= 0 && --retry_count) { int vsync = MDP3_REG_READ(MDP3_REG_INTR_STATUS) & vsync = MDP3_REG_READ(MDP3_REG_INTR_STATUS) & (1 << MDP3_INTR_LCDC_START_OF_FRAME); if (!vsync) { Loading @@ -748,6 +827,9 @@ retry_vsync: rc = -1; } ATRACE_END("mdp3_wait_for_vsync_comp"); if (!mdp3_res->irq_ref_count[MDP3_INTR_LCDC_UNDERFLOW]) mdp3_irq_enable(MDP3_INTR_LCDC_UNDERFLOW); } pr_debug("$%s wait for vsync_comp out\n", __func__); ATRACE_END(__func__); Loading @@ -755,7 +837,7 @@ retry_vsync: } static int mdp3_dmas_update(struct mdp3_dma *dma, void *buf, struct mdp3_intf *intf, void *data) struct mdp3_intf *intf, void *data, bool secure) { unsigned long flag; int cb_type = MDP3_DMA_CALLBACK_TYPE_VSYNC; Loading Loading @@ -1082,6 +1164,8 @@ int mdp3_dma_init(struct mdp3_dma *dma) dma->config_histo = mdp3_dmap_histo_config; dma->config_lut = mdp3_dmap_lut_config; dma->update = mdp3_dmap_update; dma->handle_null_commit = mdp3_handle_null_commit; dma->wait_for_dma = mdp3_wait_for_dma_comp; dma->update_cursor = mdp3_dmap_cursor_update; dma->get_histo = mdp3_dmap_histo_get; dma->histo_op = mdp3_dmap_histo_op; Loading @@ -1100,6 +1184,7 @@ int mdp3_dma_init(struct mdp3_dma *dma) dma->config_ccs = NULL; dma->config_histo = NULL; dma->config_lut = NULL; dma->handle_null_commit = NULL; dma->update = mdp3_dmas_update; dma->update_cursor = NULL; dma->get_histo = NULL; Loading Loading
drivers/video/msm/mdss/mdp3.c +6 −1 Original line number Diff line number Diff line Loading @@ -47,6 +47,7 @@ #include <linux/qcom_iommu.h> #include <linux/msm_iommu_domains.h> #include <linux/vmalloc.h> #include <soc/qcom/scm.h> #include <linux/msm_dma_iommu_mapping.h> Loading Loading @@ -2956,7 +2957,7 @@ int mdp3_panel_get_intf_status(u32 disp_num, u32 intf_type) static int mdp3_probe(struct platform_device *pdev) { int rc; int rc, scm_ret = 0; static struct msm_mdp_interface mdp3_interface = { .init_fnc = mdp3_init, .fb_mem_get_iommu_domain = mdp3_fb_mem_get_iommu_domain, Loading Loading @@ -3083,6 +3084,10 @@ static int mdp3_probe(struct platform_device *pdev) __mdp3_set_supported_formats(); rc = scm_restore_sec_cfg(SEC_DEVICE_MDP3, 0, &scm_ret); if (rc) pr_err("Restore secure cfg failed\n"); mdp3_res->mdss_util->mdp_probe_done = true; pr_debug("%s: END\n", __func__); Loading
drivers/video/msm/mdss/mdp3.h +7 −0 Original line number Diff line number Diff line Loading @@ -31,6 +31,7 @@ #define MDP_CORE_CLK_RATE_SVS 160000000 #define MDP_CORE_CLK_RATE_SUPER_SVS 200000000 #define MDP_CORE_CLK_RATE_MAX 307200000 #define SEC_DEVICE_MDP3 1 #define CLK_FUDGE_NUM 12 #define CLK_FUDGE_DEN 10 Loading Loading @@ -96,6 +97,12 @@ enum { DI_MAX, }; enum mdp3_sd_transition { NO_TRANSITION, NONSECURE_TO_SECURE, SECURE_TO_NONSECURE, }; struct mdp3_bus_handle_map { struct msm_bus_vectors *bus_vector; struct msm_bus_paths *usecases; Loading
drivers/video/msm/mdss/mdp3_ctrl.c +157 −8 Original line number Diff line number Diff line Loading @@ -25,6 +25,7 @@ #include <linux/sw_sync.h> #include <linux/iommu.h> #include <linux/msm_ion.h> #include <soc/qcom/scm.h> #include "mdp3_ctrl.h" #include "mdp3.h" Loading @@ -33,6 +34,7 @@ #include "mdss_spi_panel.h" #define VSYNC_EXPIRE_TICK 4 #define MEM_PROTECT_SD_CTRL 0xF static void mdp3_ctrl_pan_display(struct msm_fb_data_type *mfd); static int mdp3_overlay_unset(struct msm_fb_data_type *mfd, int ndx); Loading Loading @@ -397,12 +399,46 @@ void mdp3_vsync_timer_func(unsigned long arg) } } int config_secure_display(struct mdp3_session_data *mdp3_session) { struct sd_ctrl_req { unsigned int enable; } __attribute__ ((__packed__)) request; unsigned int resp = -1; int ret = 0; struct scm_desc desc; if (mdp3_session->transition_state == NONSECURE_TO_SECURE) atomic_inc(&mdp3_session->secure_display); else if (mdp3_session->transition_state == SECURE_TO_NONSECURE) atomic_dec(&mdp3_session->secure_display); request.enable = atomic_read(&mdp3_session->secure_display); desc.args[0] = request.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), &desc); resp = desc.ret[0]; } pr_debug("scm_call MEM_PROTECT_SD_CTRL(%u): ret=%di resp =%d\n", request.enable, ret, resp); return resp; } static int mdp3_ctrl_async_blit_req(struct msm_fb_data_type *mfd, void __user *p) { struct mdp_async_blit_req_list req_list_header; int rc, count; void __user *p_req; struct mdp3_session_data *session; if (copy_from_user(&req_list_header, p, sizeof(req_list_header))) return -EFAULT; Loading @@ -410,6 +446,23 @@ static int mdp3_ctrl_async_blit_req(struct msm_fb_data_type *mfd, count = req_list_header.count; if (count < 0 || count > MAX_BLIT_REQ) return -EINVAL; if (!mfd || !mfd->mdp.private1) return -EINVAL; session = (struct mdp3_session_data *)mfd->mdp.private1; if (atomic_read(&session->secure_display) && (mdp3_ctrl_get_intf_type(mfd) == MDP3_DMA_OUTPUT_SEL_DSI_VIDEO)) { rc = wait_for_completion_timeout(&session->secure_completion, msecs_to_jiffies(84)); if (rc) { pr_err("Timed out waiting for completion of secure display\n"); return rc; } } rc = mdp3_ppp_parse_req(p_req, &req_list_header, 1); if (!rc) rc = copy_to_user(p, &req_list_header, sizeof(req_list_header)); Loading Loading @@ -895,6 +948,7 @@ static int mdp3_ctrl_on(struct msm_fb_data_type *mfd) int rc = 0; struct mdp3_session_data *mdp3_session; struct mdss_panel_data *panel; int scm_ret = 0; pr_debug("mdp3_ctrl_on\n"); mdp3_session = (struct mdp3_session_data *)mfd->mdp.private1; Loading Loading @@ -940,6 +994,10 @@ static int mdp3_ctrl_on(struct msm_fb_data_type *mfd) goto end; } rc = scm_restore_sec_cfg(SEC_DEVICE_MDP3, 0, &scm_ret); if (rc) pr_err("Restoring secure cfg failed\n"); /* * Get a reference to the runtime pm device. * If idle pc feature is enabled, it will be released Loading Loading @@ -1505,7 +1563,8 @@ static int mdp3_ctrl_display_commit_kickoff(struct msm_fb_data_type *mfd, struct mdss_panel_data *panel; int frame_rate = DEFAULT_FRAME_RATE; int stride; bool null_commit = false; bool is_panel_type_cmd = false; if (!mfd || !mfd->mdp.private1) return -EINVAL; Loading @@ -1520,7 +1579,34 @@ static int mdp3_ctrl_display_commit_kickoff(struct msm_fb_data_type *mfd, if (mdp3_bufq_count(&mdp3_session->bufq_in) == 0) { pr_debug("no buffer in queue yet\n"); return -EPERM; null_commit = true; } if (null_commit && mdp3_ctrl_get_intf_type(mfd) == MDP3_DMA_OUTPUT_SEL_DSI_VIDEO) { mutex_lock(&mdp3_session->lock); reinit_completion(&mdp3_session->secure_completion); mdp3_ctrl_reset_countdown(mdp3_session, mfd); mdp3_ctrl_clk_enable(mfd, 1); rc = mdp3_session->dma->handle_null_commit(mdp3_session->dma, mdp3_session->intf); if (atomic_read(&mdp3_session->secure_display)) { mdp3_session->transition_state = SECURE_TO_NONSECURE; rc = config_secure_display(mdp3_session); if (rc) pr_err("Configuring secure display failed\n"); } complete_all(&mdp3_session->secure_completion); mdp3_ctrl_notify(mdp3_session, MDP_NOTIFY_FRAME_DONE); if (mdp3_bufq_count(&mdp3_session->bufq_out) > 0) { data = mdp3_bufq_pop(&mdp3_session->bufq_out); if (data) mdp3_put_img(data, MDP3_CLIENT_DMA_P); } mdp3_session->vsync_before_commit = 0; mutex_unlock(&mdp3_session->lock); return 0; } if (panel_info->partial_update_enabled && Loading Loading @@ -1562,6 +1648,10 @@ static int mdp3_ctrl_display_commit_kickoff(struct msm_fb_data_type *mfd, return -EPERM; } MDSS_XLOG(0x111); if (mfd->panel.type == MIPI_CMD_PANEL || client == MDP3_CLIENT_SPI) is_panel_type_cmd = true; mdp3_ctrl_notify(mdp3_session, MDP_NOTIFY_FRAME_BEGIN); data = mdp3_bufq_pop(&mdp3_session->bufq_in); if (data) { Loading @@ -1577,20 +1667,76 @@ static int mdp3_ctrl_display_commit_kickoff(struct msm_fb_data_type *mfd, rc = mdss_spi_panel_kickoff(mdp3_session->panel, (void *)(int)data->addr, (int)data->len, stride); } else if (mdp3_session->dma->update_src_cfg && goto frame_done; } else if (mdp3_session->dma->output_config.out_sel == MDP3_DMA_OUTPUT_SEL_DSI_CMD) { rc = mdp3_session->dma->wait_for_dma(mdp3_session->dma, mdp3_session->intf); if (!rc && !mdp3_session->first_commit) { pr_err("dma done timedout\n"); mutex_unlock(&mdp3_session->lock); return -ETIMEDOUT; } } /* For command mode panels, the secure display should be enabled * only after the previous dma done is completed */ if (mdp3_session->transition_state != NO_TRANSITION) { rc = config_secure_display(mdp3_session); if (rc) { pr_err("Configuring secure display failed\n"); mutex_unlock(&mdp3_session->lock); return -EINVAL; } } if (is_panel_type_cmd) { rc = mdp3_iommu_enable(client); if (rc) { pr_err("failed to enable iommu\n"); mdp3_put_img(data, client); mutex_unlock(&mdp3_session->lock); return rc; } } rc = mdp3_map_layer(data, MDP3_CLIENT_DMA_P); if (data->len < mdp3_session->dma->source_config.stride * mdp3_session->dma->source_config.height) { pr_err("buf size(0x%lx) is smaller than dma config(0x%x)\n", data->len, (mdp3_session->dma->source_config.stride * mdp3_session->dma->source_config.height)); mdp3_put_img(data, client); if (is_panel_type_cmd) mdp3_iommu_disable(client); mutex_unlock(&mdp3_session->lock); return -EINVAL; } if (is_panel_type_cmd) mdp3_iommu_disable(client); if (mdp3_session->dma->update_src_cfg && panel_info->partial_update_enabled) { panel->panel_info.roi.x = mdp3_session->dma->roi.x; panel->panel_info.roi.y = mdp3_session->dma->roi.y; panel->panel_info.roi.w = mdp3_session->dma->roi.w; panel->panel_info.roi.h = mdp3_session->dma->roi.h; rc = mdp3_session->dma->update(mdp3_session->dma, (void *)(int)data->addr, mdp3_session->intf, (void *)panel); (void *)(int)data->addr, mdp3_session->intf, (void *)panel, atomic_read(&mdp3_session->secure_display)); } else { rc = mdp3_session->dma->update(mdp3_session->dma, (void *)(int)data->addr, mdp3_session->intf, NULL); (void *)(int)data->addr, mdp3_session->intf, NULL, atomic_read(&mdp3_session->secure_display)); } frame_done: /* This is for the previous frame */ if (rc < 0) { mdp3_ctrl_notify(mdp3_session, Loading Loading @@ -1746,7 +1892,8 @@ static void mdp3_ctrl_pan_display(struct msm_fb_data_type *mfd) } rc = mdp3_session->dma->update(mdp3_session->dma, (void *)(int)(mfd->iova + offset), mdp3_session->intf, NULL); mdp3_session->intf, NULL, atomic_read(&mdp3_session->secure_display)); /* This is for the previous frame */ if (rc < 0) { mdp3_ctrl_notify(mdp3_session, Loading Loading @@ -3058,6 +3205,7 @@ int mdp3_ctrl_init(struct msm_fb_data_type *mfd) mdp3_session->histo_status = 0; mdp3_session->lut_sel = 0; BLOCKING_INIT_NOTIFIER_HEAD(&mdp3_session->notifier_head); atomic_set(&mdp3_session->secure_display, 0); init_timer(&mdp3_session->vsync_timer); mdp3_session->vsync_timer.function = mdp3_vsync_timer_func; Loading @@ -3065,6 +3213,7 @@ int mdp3_ctrl_init(struct msm_fb_data_type *mfd) mdp3_session->vsync_period = 1000 / frame_rate; mfd->mdp.private1 = mdp3_session; init_completion(&mdp3_session->dma_completion); init_completion(&mdp3_session->secure_completion); if (intf_type != MDP3_DMA_OUTPUT_SEL_DSI_VIDEO || intf_type != MDP3_DMA_OUTPUT_SEL_SPI_CMD) mdp3_session->wait_for_dma_done = mdp3_wait_for_dma_done; Loading
drivers/video/msm/mdss/mdp3_ctrl.h +5 −1 Original line number Diff line number Diff line Loading @@ -76,12 +76,16 @@ struct mdp3_session_data { bool dma_active; struct completion dma_completion; struct completion secure_completion; int (*wait_for_dma_done)(struct mdp3_session_data *session); /* For retire fence */ struct sw_sync_timeline *vsync_timeline; int retire_cnt; struct work_struct retire_work; atomic_t secure_display; int transition_state; }; void mdp3_bufq_deinit(struct mdp3_buffer_queue *bufq, int client); Loading @@ -92,6 +96,6 @@ int mdp3_ctrl_get_source_format(u32 imgType); int mdp3_ctrl_get_pack_pattern(u32 imgType); int mdp3_ctrl_reset(struct msm_fb_data_type *mfd); int mdp3_get_ion_client(struct msm_fb_data_type *mfd); int config_secure_display(struct mdp3_session_data *mdp3_session); #endif /* MDP3_CTRL_H */
drivers/video/msm/mdss/mdp3_dma.c +110 −25 Original line number Diff line number Diff line Loading @@ -17,6 +17,7 @@ #include "mdp3_dma.h" #include "mdp3_hwio.h" #include "mdss_debug.h" #include "mdp3_ctrl.h" #define DMA_STOP_POLL_SLEEP_US 1000 #define DMA_STOP_POLL_TIMEOUT_US 200000 Loading Loading @@ -351,7 +352,7 @@ static int mdp3_dmap_config(struct mdp3_dma *dma, return 0; } static void mdp3_dmap_config_source(struct mdp3_dma *dma) static void mdp3_dmap_config_source(struct mdp3_dma *dma, bool enable_secure) { struct mdp3_dma_source *source_config = &dma->source_config; u32 dma_p_cfg_reg, dma_p_size; Loading @@ -364,6 +365,11 @@ static void mdp3_dmap_config_source(struct mdp3_dma *dma) dma_p_size = dma->roi.w | (dma->roi.h << 16); if (enable_secure) dma_p_cfg_reg |= BIT(21); else dma_p_cfg_reg &= ~BIT(21); MDP3_REG_WRITE(MDP3_REG_DMA_P_CONFIG, dma_p_cfg_reg); MDP3_REG_WRITE(MDP3_REG_DMA_P_SIZE, dma_p_size); MDP3_REG_WRITE(MDP3_REG_DMA_P_IBUF_Y_STRIDE, source_config->stride); Loading Loading @@ -406,7 +412,7 @@ static int mdp3_dmas_config(struct mdp3_dma *dma, return 0; } static void mdp3_dmas_config_source(struct mdp3_dma *dma) static void mdp3_dmas_config_source(struct mdp3_dma *dma, bool enable_secure) { struct mdp3_dma_source *source_config = &dma->source_config; u32 dma_s_cfg_reg, dma_s_size; Loading Loading @@ -654,46 +660,119 @@ int dma_bpp(int format) return bpp; } static int mdp3_dmap_update(struct mdp3_dma *dma, void *buf, struct mdp3_intf *intf, void *data) static int mdp3_handle_null_commit(struct mdp3_dma *dma, struct mdp3_intf *intf) { int rc = 0; int retry_count = 2; unsigned long flag; int cb_type = MDP3_DMA_CALLBACK_TYPE_VSYNC; struct mdss_panel_data *panel; if (!dma->source_config.format && !dma->source_config.stride) { pr_debug("Null commit already handled\n"); return 0; } /* * Size and stride are set to 0 to ensure that DMA pipe does not * fetch anything whenever we get a null commit. The values will be * reconfigured to the correct values in the next commit. */ MDP3_REG_WRITE(MDP3_REG_DMA_P_SIZE, 0); MDP3_REG_WRITE(MDP3_REG_DMA_P_IBUF_Y_STRIDE, 0); spin_lock_irqsave(&dma->dma_lock, flag); dma->source_config.format = 0; dma->source_config.stride = 0; mdp3_irq_disable(MDP3_INTR_LCDC_UNDERFLOW); MDP3_REG_WRITE(MDP3_REG_DSI_VIDEO_UNDERFLOW_CTL, 0x80000000); if (!intf->active) { pr_debug("%s start interface\n", __func__); intf->start(intf); } /* * Make sure that all the configurations required for * null commit is done before waiting for the vsync. */ mb(); dma->vsync_status = MDP3_REG_READ(MDP3_REG_INTR_STATUS) & (1 << MDP3_INTR_LCDC_START_OF_FRAME); init_completion(&dma->vsync_comp); spin_unlock_irqrestore(&dma->dma_lock, flag); mdp3_dma_callback_enable(dma, cb_type); retry_vsync: pr_debug("wait for vsync_comp started\n"); rc = wait_for_completion_timeout(&dma->vsync_comp, KOFF_TIMEOUT); if (rc <= 0 && --retry_count) { int vsync = MDP3_REG_READ(MDP3_REG_INTR_STATUS) & (1 << MDP3_INTR_LCDC_START_OF_FRAME); if (!vsync) { pr_err("%s trying again count = %d\n", __func__, retry_count); goto retry_vsync; } rc = -1; } pr_debug("wait for vsync_comp done\n"); return rc; } static int mdp3_wait_for_dma_comp(struct mdp3_dma *dma, struct mdp3_intf *intf) { int vsync_status; int rc = 0; int retry_count = 2; ATRACE_BEGIN(__func__); pr_debug("mdp3_dmap_update\n"); MDSS_XLOG(XLOG_FUNC_ENTRY, __LINE__); if (dma->output_config.out_sel == MDP3_DMA_OUTPUT_SEL_DSI_CMD) { cb_type = MDP3_DMA_CALLBACK_TYPE_DMA_DONE; if (intf->active) { ATRACE_BEGIN("mdp3_wait_for_dma_comp"); retry_dma_done: rc = wait_for_completion_timeout(&dma->dma_comp, KOFF_TIMEOUT); if (rc <= 0 && --retry_count) { int vsync_status; vsync_status = (1 << MDP3_INTR_DMA_P_DONE) & MDP3_REG_READ(MDP3_REG_INTR_STATUS); if (!vsync_status) { pr_err("%s: cmd timeout retry cnt %d\n", __func__, retry_count); goto retry_dma_done; } else { rc = 1; } rc = -1; } ATRACE_END("mdp3_wait_for_dma_comp"); } return rc; } static int mdp3_dmap_update(struct mdp3_dma *dma, void *buf, struct mdp3_intf *intf, void *data, bool secure) { unsigned long flag; int cb_type = MDP3_DMA_CALLBACK_TYPE_VSYNC; struct mdss_panel_data *panel; int rc = 0; int retry_count = 2; int vsync = 0; ATRACE_BEGIN(__func__); pr_debug("mdp3_dmap_update\n"); MDSS_XLOG(XLOG_FUNC_ENTRY, __LINE__); if (dma->output_config.out_sel == MDP3_DMA_OUTPUT_SEL_DSI_CMD) { cb_type = MDP3_DMA_CALLBACK_TYPE_DMA_DONE; } if (dma->update_src_cfg) { if (dma->output_config.out_sel == MDP3_DMA_OUTPUT_SEL_DSI_VIDEO && intf->active) pr_err("configuring dma source while it is active\n"); dma->dma_config_source(dma); dma->dma_config_source(dma, secure); if (data) { panel = (struct mdss_panel_data *)data; if (panel->event_handler) { Loading Loading @@ -737,7 +816,7 @@ retry_vsync: rc = wait_for_completion_timeout(&dma->vsync_comp, KOFF_TIMEOUT); if (rc <= 0 && --retry_count) { int vsync = MDP3_REG_READ(MDP3_REG_INTR_STATUS) & vsync = MDP3_REG_READ(MDP3_REG_INTR_STATUS) & (1 << MDP3_INTR_LCDC_START_OF_FRAME); if (!vsync) { Loading @@ -748,6 +827,9 @@ retry_vsync: rc = -1; } ATRACE_END("mdp3_wait_for_vsync_comp"); if (!mdp3_res->irq_ref_count[MDP3_INTR_LCDC_UNDERFLOW]) mdp3_irq_enable(MDP3_INTR_LCDC_UNDERFLOW); } pr_debug("$%s wait for vsync_comp out\n", __func__); ATRACE_END(__func__); Loading @@ -755,7 +837,7 @@ retry_vsync: } static int mdp3_dmas_update(struct mdp3_dma *dma, void *buf, struct mdp3_intf *intf, void *data) struct mdp3_intf *intf, void *data, bool secure) { unsigned long flag; int cb_type = MDP3_DMA_CALLBACK_TYPE_VSYNC; Loading Loading @@ -1082,6 +1164,8 @@ int mdp3_dma_init(struct mdp3_dma *dma) dma->config_histo = mdp3_dmap_histo_config; dma->config_lut = mdp3_dmap_lut_config; dma->update = mdp3_dmap_update; dma->handle_null_commit = mdp3_handle_null_commit; dma->wait_for_dma = mdp3_wait_for_dma_comp; dma->update_cursor = mdp3_dmap_cursor_update; dma->get_histo = mdp3_dmap_histo_get; dma->histo_op = mdp3_dmap_histo_op; Loading @@ -1100,6 +1184,7 @@ int mdp3_dma_init(struct mdp3_dma *dma) dma->config_ccs = NULL; dma->config_histo = NULL; dma->config_lut = NULL; dma->handle_null_commit = NULL; dma->update = mdp3_dmas_update; dma->update_cursor = NULL; dma->get_histo = NULL; Loading