Merge "msm: mdss: Enable secure display and camera feature for msmcobalt"

This commit is contained in:
Linux Build Service Account 2016-11-08 11:18:41 -08:00 committed by Gerrit - the friendly Code Review server
commit 82933a003b
10 changed files with 352 additions and 95 deletions

View file

@ -178,6 +178,7 @@ enum mdss_hw_capabilities {
MDSS_CAPS_CWB_SUPPORTED, MDSS_CAPS_CWB_SUPPORTED,
MDSS_CAPS_MDP_VOTE_CLK_NOT_SUPPORTED, MDSS_CAPS_MDP_VOTE_CLK_NOT_SUPPORTED,
MDSS_CAPS_AVR_SUPPORTED, MDSS_CAPS_AVR_SUPPORTED,
MDSS_CAPS_SEC_DETACH_SMMU,
MDSS_CAPS_MAX, MDSS_CAPS_MAX,
}; };
@ -221,6 +222,7 @@ struct mdss_smmu_client {
bool domain_attached; bool domain_attached;
bool handoff_pending; bool handoff_pending;
void __iomem *mmu_base; void __iomem *mmu_base;
int domain;
}; };
struct mdss_mdp_qseed3_lut_tbl { struct mdss_mdp_qseed3_lut_tbl {
@ -327,6 +329,7 @@ struct mdss_data_type {
u32 wfd_mode; u32 wfd_mode;
u32 has_no_lut_read; u32 has_no_lut_read;
atomic_t sd_client_count; atomic_t sd_client_count;
atomic_t sc_client_count;
u8 has_wb_ad; u8 has_wb_ad;
u8 has_non_scalar_rgb; u8 has_non_scalar_rgb;
bool has_src_split; bool has_src_split;
@ -519,6 +522,8 @@ struct mdss_data_type {
u32 max_dest_scaler_input_width; u32 max_dest_scaler_input_width;
u32 max_dest_scaler_output_width; u32 max_dest_scaler_output_width;
struct mdss_mdp_destination_scaler *ds; struct mdss_mdp_destination_scaler *ds;
u32 sec_disp_en;
u32 sec_cam_en;
}; };
extern struct mdss_data_type *mdss_res; 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); 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, static inline void mdss_set_quirk(struct mdss_data_type *mdata,
enum mdss_hw_quirk bit) enum mdss_hw_quirk bit)
{ {

View file

@ -47,6 +47,8 @@
#include <linux/msm-bus-board.h> #include <linux/msm-bus-board.h>
#include <soc/qcom/scm.h> #include <soc/qcom/scm.h>
#include <soc/qcom/rpm-smd.h> #include <soc/qcom/rpm-smd.h>
#include "soc/qcom/secure_buffer.h"
#include <asm/cacheflush.h>
#include "mdss.h" #include "mdss.h"
#include "mdss_fb.h" #include "mdss_fb.h"
@ -64,6 +66,8 @@
#define RES_1080p (1088*1920) #define RES_1080p (1088*1920)
#define RES_UHD (3840*2160) #define RES_UHD (3840*2160)
#define MDP_DEVICE_ID 0x1A
struct mdss_data_type *mdss_res; struct mdss_data_type *mdss_res;
static u32 mem_protect_sd_ctrl_id; 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 0xF
#define MEM_PROTECT_SD_CTRL_FLAT 0x14 #define MEM_PROTECT_SD_CTRL_FLAT 0x14
#define MEM_PROTECT_SD_CTRL_SWITCH 0x18
static DEFINE_SPINLOCK(mdp_lock); static DEFINE_SPINLOCK(mdp_lock);
static DEFINE_SPINLOCK(mdss_mdp_intr_lock); static DEFINE_SPINLOCK(mdss_mdp_intr_lock);
@ -1329,7 +1334,9 @@ int mdss_iommu_ctrl(int enable)
if (mdata->iommu_ref_cnt == 0) { if (mdata->iommu_ref_cnt == 0) {
rc = mdss_smmu_detach(mdata); rc = mdss_smmu_detach(mdata);
if (mdss_has_quirk(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, mdss_bus_scale_set_quota(MDSS_HW_RT,
0, 0); 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->pixel_ram_size = 50 * 1024;
mdata->rects_per_sspp[MDSS_MDP_PIPE_TYPE_DMA] = 2; 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_PER_PIPE_IB, mdata->mdss_qos_map);
set_bit(MDSS_QOS_REMAPPER, mdata->mdss_qos_map); set_bit(MDSS_QOS_REMAPPER, mdata->mdss_qos_map);
set_bit(MDSS_QOS_TS_PREFILL, 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; mdata->has_wb_ubwc = true;
set_bit(MDSS_CAPS_10_BIT_SUPPORTED, mdata->mdss_caps_map); 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_AVR_SUPPORTED, mdata->mdss_caps_map);
set_bit(MDSS_CAPS_SEC_DETACH_SMMU, mdata->mdss_caps_map);
break; break;
default: default:
mdata->max_target_zorder = 4; /* excluding base layer */ 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 { struct sd_ctrl_req {
unsigned int enable; unsigned int enable;
} __attribute__ ((__packed__)) request; } __attribute__ ((__packed__)) request;
unsigned int resp = -1; unsigned int resp = -1;
int ret = 0; int ret = 0;
uint32_t sid_info;
struct scm_desc desc; struct scm_desc desc;
desc.args[0] = request.enable = enable; if (test_bit(MDSS_CAPS_SEC_DETACH_SMMU, mdata->mdss_caps_map)) {
desc.arginfo = SCM_ARGS(1); /*
* 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, pr_debug("Enable/Disable: %d, Flags %llx\n", enable, flags);
&request, sizeof(request), &resp, sizeof(resp)); if (enable) {
} else { if (flags & MDP_SECURE_DISPLAY_OVERLAY_SESSION) {
ret = scm_call2(SCM_SIP_FNID(SCM_SVC_MP, 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); 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); enable, ret, resp);
}
if (ret) if (ret)
return ret; return ret;

View file

@ -92,6 +92,8 @@
*/ */
#define ENABLE_PIXEL_EXT_ONLY 0x80000000 #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 * Destination Scaler control flags setting
* *
@ -629,7 +631,7 @@ struct mdss_mdp_img_data {
dma_addr_t addr; dma_addr_t addr;
unsigned long len; unsigned long len;
u32 offset; u32 offset;
u32 flags; u64 flags;
u32 dir; u32 dir;
u32 domain; u32 domain;
bool mapped; bool mapped;
@ -813,7 +815,7 @@ struct mdss_mdp_pipe {
struct file *file; struct file *file;
bool is_handed_off; bool is_handed_off;
u32 flags; u64 flags;
u32 bwc_mode; u32 bwc_mode;
/* valid only when pipe's output is crossing both layer mixers */ /* 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_addr;
u32 splash_mem_size; u32 splash_mem_size;
u32 sd_enabled; u32 sd_enabled;
u32 sc_enabled;
struct sw_sync_timeline *vsync_timeline; struct sw_sync_timeline *vsync_timeline;
struct mdss_mdp_vsync_handler vsync_retire_handler; 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); 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, static inline int mdss_mdp_get_wb_ctl_support(struct mdss_data_type *mdata,
bool rotator_session) 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) struct mdss_mdp_img_data *data)
{ {
u32 is_secure_ui = data->flags & MDP_SECURE_DISPLAY_OVERLAY_SESSION; 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. * 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)) if (is_secure_ui && !mdss_has_quirk(mdata, MDSS_QUIRK_NEED_SECURE_MAP))
return false; return false;
if (is_secure_camera && test_bit(MDSS_CAPS_SEC_DETACH_SMMU,
mdata->mdss_caps_map))
return false;
return true; 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); int mdss_mdp_vsync_clk_enable(int enable, bool locked);
void mdss_mdp_clk_ctrl(int enable); void mdss_mdp_clk_ctrl(int enable);
struct mdss_data_type *mdss_mdp_get_mdata(void); 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_overlay_init(struct msm_fb_data_type *mfd);
int mdss_mdp_dfps_update_params(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( void mdss_mdp_overlay_set_chroma_sample(
struct mdss_mdp_pipe *pipe); struct mdss_mdp_pipe *pipe);
int mdp_pipe_tune_perf(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); 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_pipe *mdss_mdp_pipe_assign(struct mdss_data_type *mdata,
struct mdss_mdp_mixer *mixer, u32 ndx, 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); 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); 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, 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 device *dev, bool rotator, int dir,
struct mdp_layer_buffer *buffer); struct mdp_layer_buffer *buffer);
u32 mdss_get_panel_framerate(struct msm_fb_data_type *mfd); u32 mdss_get_panel_framerate(struct msm_fb_data_type *mfd);

View file

@ -1868,7 +1868,7 @@ static void __dump_pipe(struct seq_file *s, struct mdss_mdp_pipe *pipe)
int smps[4]; int smps[4];
int i; 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->num, mdss_mdp_pipetype2str(pipe->type),
pipe->ndx, pipe->flags, pipe->play_cnt, pipe->xin_id); 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", seq_printf(s, "\tstage=%d alpha=0x%x transp=0x%x blend_op=%d\n",

View file

@ -986,7 +986,7 @@ static int __configure_pipe_params(struct msm_fb_data_type *mfd,
{ {
int ret = 0; int ret = 0;
u32 left_lm_w = left_lm_w_from_mfd(mfd); u32 left_lm_w = left_lm_w_from_mfd(mfd);
u32 flags; u64 flags;
struct mdss_mdp_mixer *mixer = NULL; struct mdss_mdp_mixer *mixer = NULL;
struct mdss_overlay_private *mdp5_data = mfd_to_mdp5_data(mfd); 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; pipe->flags |= MDP_BWC_EN;
if (layer->flags & MDP_LAYER_PP) if (layer->flags & MDP_LAYER_PP)
pipe->flags |= MDP_OVERLAY_PP_CFG_EN; 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->scaler.enable = (layer->flags & SCALER_ENABLED);
pipe->is_fg = layer->flags & MDP_LAYER_FORGROUND; 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 mdp_layer_buffer *buffer;
struct msmfb_data image; struct msmfb_data image;
int i, ret; int i, ret;
u32 flags; u64 flags;
struct mdss_mdp_validate_info_t *vitem; struct mdss_mdp_validate_info_t *vitem;
for (i = 0; i < layer_count; i++) { 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 | 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) { if (buffer->planes[0].fd < 0) {
pr_err("invalid file descriptor for layer buffer\n"); 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 * 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 * is with secure display, secure video and secure camera enabled flag.
* unsecure content with secure display session. * 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; struct mdss_mdp_pipe *pipe, *tmp;
uint32_t sd_pipes = 0, nonsd_pipes = 0; uint32_t sd_pipes = 0, nonsd_pipes = 0;
uint32_t secure_vid_pipes = 0, secure_cam_pipes = 0;
mutex_lock(&mdp5_data->list_lock); mutex_lock(&mdp5_data->list_lock);
list_for_each_entry_safe(pipe, tmp, &mdp5_data->pipes_used, list) { list_for_each_entry_safe(pipe, tmp, &mdp5_data->pipes_used, list) {
if (pipe->flags & MDP_SECURE_DISPLAY_OVERLAY_SESSION) if (pipe->flags & MDP_SECURE_DISPLAY_OVERLAY_SESSION)
sd_pipes++; 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 else
nonsd_pipes++; nonsd_pipes++;
} }
mutex_unlock(&mdp5_data->list_lock); mutex_unlock(&mdp5_data->list_lock);
pr_debug("pipe count:: secure display:%d non-secure:%d\n", pr_debug("pipe count:: secure display:%d non-secure:%d secure-vid:%d,secure-cam:%d\n",
sd_pipes, nonsd_pipes); 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("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", 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); 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; return -EINVAL;
} else { } else {
return 0; return 0;
@ -2439,7 +2456,7 @@ static int __validate_layers(struct msm_fb_data_type *mfd,
validate_skip: validate_skip:
__handle_free_list(mdp5_data, validate_info_list, layer_count); __handle_free_list(mdp5_data, validate_info_list, layer_count);
ret = __validate_secure_display(mdp5_data); ret = __validate_secure_session(mdp5_data);
validate_exit: 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", 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",

View file

@ -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, 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_data_type *mdata = pipe->mixer_left->ctl->mdata;
struct mdss_mdp_perf_params perf; 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); list_move(&buf->buf_list, &mdp5_data->bufs_freelist);
/* /*
* in case of secure UI, the buffer needs to be released as * free the buffers on the same cycle instead of waiting for
* soon as session is closed. * 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); 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() && if (mdss_get_sd_client_cnt() &&
!(pipe->flags & MDP_SECURE_DISPLAY_OVERLAY_SESSION)) { !(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); pipe->num, pipe->flags);
continue; continue;
} }
@ -2110,6 +2109,92 @@ set_roi:
mdss_mdp_set_roi(ctl, &l_roi, &r_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, int mdss_mdp_overlay_kickoff(struct msm_fb_data_type *mfd,
struct mdp_display_commit *data) 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_pipe *pipe, *tmp;
struct mdss_mdp_ctl *ctl = mfd_to_ctl(mfd); struct mdss_mdp_ctl *ctl = mfd_to_ctl(mfd);
int ret = 0; int ret = 0;
int sd_in_pipe = 0;
struct mdss_mdp_commit_cb commit_cb; struct mdss_mdp_commit_cb commit_cb;
if (!ctl) if (!ctl)
@ -2148,30 +2232,12 @@ int mdss_mdp_overlay_kickoff(struct msm_fb_data_type *mfd,
mutex_unlock(ctl->shared_lock); mutex_unlock(ctl->shared_lock);
return ret; return ret;
} }
mutex_lock(&mdp5_data->list_lock); mutex_lock(&mdp5_data->list_lock);
ret = __overlay_secure_ctrl(mfd);
/* if (IS_ERR_VALUE(ret)) {
* check if there is a secure display session pr_err("secure operation failed %d\n", ret);
*/ goto commit_fail;
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);
}
} }
if (!ctl->shared_lock) 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); 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); mdss_fb_update_notify_update(mfd);
commit_fail: 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 mdss_mdp_data *src_data;
struct mdp_layer_buffer buffer; struct mdp_layer_buffer buffer;
int ret; int ret;
u32 flags; u64 flags;
pipe = __overlay_find_pipe(mfd, req->id); pipe = __overlay_find_pipe(mfd, req->id);
if (!pipe) { 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"); pr_warn("Unexpected buffer queue to a solid fill pipe\n");
flags = (pipe->flags & (MDP_SECURE_OVERLAY_SESSION | 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); mutex_lock(&mdp5_data->list_lock);
src_data = mdss_mdp_overlay_buf_alloc(mfd, pipe); src_data = mdss_mdp_overlay_buf_alloc(mfd, pipe);

View file

@ -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) { if (pipe->multirect.mode == MDSS_MDP_PIPE_MULTIRECT_NONE) {
memcpy(&ystride, &pipe->src_planes.ystride, memcpy(&ystride, &pipe->src_planes.ystride,
sizeof(u32) * MAX_PLANES); 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; secure = 0xF;
} else { } else {
if (pipe->multirect.num == MDSS_MDP_PIPE_RECT0) { 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[0] = rec0_pipe->src_planes.ystride[0];
ystride[2] = rec0_pipe->src_planes.ystride[2]; 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; secure |= 0x5;
ystride[1] = rec1_pipe->src_planes.ystride[0]; ystride[1] = rec1_pipe->src_planes.ystride[0];
ystride[3] = rec1_pipe->src_planes.ystride[2]; 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; secure |= 0xA;
} }
@ -2320,7 +2323,9 @@ static int mdss_mdp_pipe_solidfill_setup(struct mdss_mdp_pipe *pipe)
} }
format = MDSS_MDP_FMT_SOLID_FILL; 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 */ /* support ARGB color format only */
unpack = (C3_ALPHA << 24) | (C2_R_Cr << 16) | unpack = (C3_ALPHA << 24) | (C2_R_Cr << 16) |

View file

@ -971,16 +971,17 @@ static int mdss_mdp_put_img(struct mdss_mdp_img_data *data, bool rotator,
data->srcp_dma_buf = NULL; 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 * skip memory unmapping - secure display and camera uses
* address which does not require buffer unmapping * physical address which does not require buffer unmapping
* *
* For LT targets in secure display usecase, srcp_dma_buf will * For LT targets in secure display usecase, srcp_dma_buf will
* be filled due to map call which will be unmapped above. * 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 { } else {
return -ENOMEM; return -ENOMEM;
} }
@ -1196,7 +1197,7 @@ err_unmap:
} }
static int mdss_mdp_data_get(struct mdss_mdp_data *data, 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) struct device *dev, bool rotator, int dir)
{ {
int i, rc = 0; 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, rc = mdss_mdp_get_img(&planes[i], &data->p[i], dev, rotator,
dir); dir);
if (rc) { 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) { while (i > 0) {
i--; i--;
mdss_mdp_put_img(&data->p[i], rotator, dir); 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, 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 device *dev, bool rotator, int dir,
struct mdp_layer_buffer *buffer) struct mdp_layer_buffer *buffer)
{ {

View file

@ -162,12 +162,15 @@ end:
} }
/* /*
* mdss_smmu_v2_attach() * mdss_smmu_attach_v2()
* *
* Associates each configured VA range with the corresponding smmu context * Associates each configured VA range with the corresponding smmu context
* bank device. Enables the clks as smmu_v2 requires voting it before the usage. * 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 * And iommu attach is done only once during the initial attach and it is never
* detached as smmu v2 uses a feature called 'retention'. * 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) 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; 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, rc = arm_iommu_attach_device(mdss_smmu->dev,
mdss_smmu->mmu_mapping); mdss_smmu->mmu_mapping);
if (rc) { 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 * Disables the clks only when 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 * 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) 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; continue;
mdss_smmu = mdss_smmu_get_cb(i); mdss_smmu = mdss_smmu_get_cb(i);
if (mdss_smmu && mdss_smmu->dev && !mdss_smmu->handoff_pending) if (mdss_smmu && mdss_smmu->dev) {
mdss_smmu_enable_power(mdss_smmu, false); 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); 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 = &mdata->mdss_smmu[smmu_domain.domain];
mdss_smmu->domain = smmu_domain.domain;
mp = &mdss_smmu->mp; mp = &mdss_smmu->mp;
memset(mp, 0, sizeof(struct dss_module_power)); memset(mp, 0, sizeof(struct dss_module_power));

View file

@ -73,6 +73,38 @@ static inline bool mdss_smmu_is_valid_domain_type(struct mdss_data_type *mdata,
return true; 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) static inline struct mdss_smmu_client *mdss_smmu_get_cb(u32 domain)
{ {
struct mdss_data_type *mdata = mdss_mdp_get_mdata(); 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; 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(); struct mdss_data_type *mdata = mdss_mdp_get_mdata();
int type; int type;