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

Commit fe515de8 authored by Linux Build Service Account's avatar Linux Build Service Account Committed by Gerrit - the friendly Code Review server
Browse files

Merge "msm: mdss: Add support for handling secure buffer use-cases in MDP3"

parents ccbe5ca5 42fc6090
Loading
Loading
Loading
Loading
+6 −1
Original line number Diff line number Diff line
@@ -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>

@@ -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,
@@ -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__);

+7 −0
Original line number Diff line number Diff line
@@ -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
@@ -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;
+157 −8
Original line number Diff line number Diff line
@@ -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"
@@ -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);
@@ -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;
@@ -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));
@@ -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;
@@ -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
@@ -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;
@@ -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 &&
@@ -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) {
@@ -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,
@@ -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,
@@ -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;
@@ -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;
+5 −1
Original line number Diff line number Diff line
@@ -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);
@@ -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 */
+110 −25
Original line number Diff line number Diff line
@@ -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
@@ -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;
@@ -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);
@@ -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;
@@ -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) {
@@ -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) {
@@ -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__);
@@ -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;
@@ -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;
@@ -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