Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit e75ba571 authored by Abhijit Kulkarni's avatar Abhijit Kulkarni Committed by Gerrit - the friendly Code Review server
Browse files

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



Add support for secure display and camera in driver. The physical address
of the secure buffers is programmed into driver and hence there is no
need of stage 1 translation. These changes handle the detach/attach of
smmu contexts while going into and coming out of secure use case.
For secure display both the secure and unsecure contexts are detached,
while for secure camera only the secure context is detached.

CRs-Fixed: 1085143
Change-Id: Iadab43e9655a9e97cdc6661c17a73891cbc2a17f
Signed-off-by: default avatarAbhijit Kulkarni <kabhijit@codeaurora.org>
Signed-off-by: default avatarNirmal Abraham <nabrah@codeaurora.org>
parent 6f434a70
Loading
Loading
Loading
Loading
+13 −0
Original line number Diff line number Diff line
@@ -178,6 +178,7 @@ enum mdss_hw_capabilities {
	MDSS_CAPS_QSEED3,
	MDSS_CAPS_DEST_SCALER,
	MDSS_CAPS_10_BIT_SUPPORTED,
	MDSS_CAPS_SEC_DETACH_SMMU,
	MDSS_CAPS_MAX,
};

@@ -219,6 +220,7 @@ struct mdss_smmu_client {
	bool domain_attached;
	bool handoff_pending;
	char __iomem *mmu_base;
	int domain;
};

struct mdss_mdp_qseed3_lut_tbl {
@@ -334,6 +336,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;
@@ -529,6 +532,8 @@ struct mdss_data_type {
	u32 splash_intf_sel;
	u32 splash_split_disp;
	struct mult_factor bus_throughput_factor;
	u32 sec_disp_en;
	u32 sec_cam_en;
};

extern struct mdss_data_type *mdss_res;
@@ -592,6 +597,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)
{
+97 −15
Original line number Diff line number Diff line
@@ -48,6 +48,8 @@
#include <linux/msm-bus-board.h>
#include <soc/qcom/scm.h>
#include <linux/soc/qcom/smd-rpm.h>
#include "soc/qcom/secure_buffer.h"
#include <asm/cacheflush.h>

#include "mdss.h"
#include "mdss_fb.h"
@@ -65,6 +67,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;

@@ -88,6 +92,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);
@@ -2050,6 +2055,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_TS_PREFILL, mdata->mdss_qos_map);
		set_bit(MDSS_QOS_OVERHEAD_FACTOR, mdata->mdss_qos_map);
@@ -2115,7 +2121,8 @@ static void mdss_mdp_hw_rev_caps_init(struct mdss_data_type *mdata)
		mdss_set_quirk(mdata, MDSS_QUIRK_MDP_CLK_SET_RATE);
		mdata->has_wb_ubwc = true;
		set_bit(MDSS_CAPS_10_BIT_SUPPORTED, mdata->mdss_caps_map);
		//set_bit(MDSS_CAPS_SEC_DETACH_SMMU, 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 */
@@ -5009,32 +5016,107 @@ static void mdss_mdp_footswitch_ctrl(struct mdss_data_type *mdata, int on)
	}
}

int mdss_mdp_secure_display_ctrl(struct mdss_data_type *mdata,
	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;

	if ((enable && (mdss_get_sd_client_cnt() > 0)) ||
		(!enable && (mdss_get_sd_client_cnt() > 1))) {
		mdss_update_sd_client(mdata, enable);
		return ret;
	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);


		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);
			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\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);

	/* Fix this as per latest scm calls */
		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",
		pr_debug("scm_call MEM_PROTECT_SD_CTRL(%u): ret=%d, resp=%x\n",
				enable, ret, resp);
	}
	if (ret)
		return ret;

+22 −6
Original line number Diff line number Diff line
@@ -88,6 +88,8 @@

#define MAX_LAYER_COUNT		0xC

/* Pipe flag to indicate this pipe contains secure camera buffer */
#define MDP_SECURE_CAMERA_OVERLAY_SESSION 0x100000000
/* hw cursor can only be setup in highest mixer stage */
#define HW_CURSOR_STAGE(mdata) \
	(((mdata)->max_target_zorder + MDSS_MDP_STAGE_0) - 1)
@@ -757,7 +759,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;
@@ -938,7 +940,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 */
@@ -1043,6 +1045,7 @@ struct mdss_overlay_private {
	u32 splash_mem_addr;
	u32 splash_mem_size;
	u32 sd_enabled;
	u32 sc_enabled;

	struct mdss_mdp_vsync_handler vsync_retire_handler;
	int retire_cnt;
@@ -1371,6 +1374,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)
{
@@ -1603,6 +1615,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.
@@ -1610,6 +1623,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;
}

@@ -1666,8 +1683,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(struct mdss_data_type *mdata,
	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,
@@ -1701,7 +1717,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,
@@ -1921,7 +1937,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);
+1 −1
Original line number Diff line number Diff line
@@ -1070,7 +1070,7 @@ static void __dump_pipe(struct seq_file *s, struct mdss_mdp_pipe *pipe,
	int i;
	struct mdss_overlay_private *mdp5_data = mfd_to_mdp5_data(mfd);

	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",
+34 −33
Original line number Diff line number Diff line
@@ -472,7 +472,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;
	bool is_right_blend = false;

	struct mdss_mdp_mixer *mixer = NULL;
@@ -512,6 +512,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->is_fg = layer->flags & MDP_LAYER_FORGROUND;
	pipe->img_width = layer->buffer.width & 0x3fff;
@@ -884,7 +886,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++) {
@@ -910,7 +912,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");
@@ -1155,59 +1158,57 @@ static inline bool __is_sd_state_valid(uint32_t sd_pipes, uint32_t nonsd_pipes,
}

/*
 * __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;
	int panel_type = mdp5_data->ctl->panel_data->panel_info.type;
	int ret = 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 (mdss_get_sd_client_cnt() && !mdp5_data->sd_enabled) {
		pr_err("Secure session already enabled for other client\n");
		return -EINVAL;
	}

	mdp5_data->sd_transition_state = SD_TRANSITION_NONE;
	if (!__is_sd_state_valid(sd_pipes, nonsd_pipes, panel_type,
		mdp5_data->sd_enabled)) {
	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);
		ret = -EINVAL;
	} else if (!mdp5_data->sd_enabled && sd_pipes) {
		mdp5_data->sd_transition_state =
			SD_TRANSITION_NON_SECURE_TO_SECURE;
	} else if (mdp5_data->sd_enabled && !sd_pipes) {
		mdp5_data->sd_transition_state =
			SD_TRANSITION_SECURE_TO_NON_SECURE;
	} else if (mdp5_data->ctl->is_video_mode &&
		((sd_pipes && !mdp5_data->sd_enabled) ||
		(!sd_pipes && mdp5_data->sd_enabled)) &&
		!mdp5_data->cache_null_commit) {
		pr_err("NULL commit missing before display secure session entry/exit\n");
		ret = -EINVAL;
		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;
	}

	return ret;
}

/*
@@ -1947,7 +1948,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",
@@ -2073,7 +2074,7 @@ int mdss_mdp_layer_pre_commit(struct msm_fb_data_type *mfd,
	if (!layer_count) {
		__handle_free_list(mdp5_data, NULL, layer_count);
		/* Check for secure state transition. */
		return __validate_secure_display(mdp5_data);
		return __validate_secure_session(mdp5_data);
	}

	validate_info_list = kcalloc(layer_count, sizeof(*validate_info_list),
Loading