summaryrefslogtreecommitdiff
path: root/drivers/video/fbdev
diff options
context:
space:
mode:
authorLinux Build Service Account <lnxbuild@localhost>2016-11-08 11:18:41 -0800
committerGerrit - the friendly Code Review server <code-review@localhost>2016-11-08 11:18:40 -0800
commit82933a003b9efa487b0cd507fd0fa70977606c9c (patch)
tree3279d414ba03db1ff3a875a759262133605190f7 /drivers/video/fbdev
parenta273d731aff32612c67fbbf22238f62e5237dfbc (diff)
parent7c9a3efa79d1b4b3576291f78e5551b16fc43032 (diff)
Merge "msm: mdss: Enable secure display and camera feature for msmcobalt"
Diffstat (limited to 'drivers/video/fbdev')
-rw-r--r--drivers/video/fbdev/msm/mdss.h13
-rw-r--r--drivers/video/fbdev/msm/mdss_mdp.c119
-rw-r--r--drivers/video/fbdev/msm/mdss_mdp.h27
-rw-r--r--drivers/video/fbdev/msm/mdss_mdp_debug.c2
-rw-r--r--drivers/video/fbdev/msm/mdss_mdp_layer.c43
-rw-r--r--drivers/video/fbdev/msm/mdss_mdp_overlay.c144
-rw-r--r--drivers/video/fbdev/msm/mdss_mdp_pipe.c13
-rw-r--r--drivers/video/fbdev/msm/mdss_mdp_util.c15
-rw-r--r--drivers/video/fbdev/msm/mdss_smmu.c37
-rw-r--r--drivers/video/fbdev/msm/mdss_smmu.h34
10 files changed, 352 insertions, 95 deletions
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 <linux/msm-bus-board.h>
#include <soc/qcom/scm.h>
#include <soc/qcom/rpm-smd.h>
+#include "soc/qcom/secure_buffer.h"
+#include <asm/cacheflush.h>
#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);
- }
+ mutex_lock(&mdp5_data->list_lock);
+ 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;