Merge branch 'mdss-final-replay' into msm-4.4

This merge brings all display changes from msm-3.18 kernel.

* (58 commits)
  msm: mdss: add support for additional DMA pipes
  msm: mdss: refactor device tree pipe parsing logic
  msm: mdss: refactor mixer configuration code
  msm: mdss: add support for secure display on msm8953.
  msm: mdss: disable ECG feature on 28nm PHY platform
  msm: mdss: send DSI command using TPG when in secure session
  msm: mdss: Update histogram and PA LUT in mdss V3
  msm: mdss: validate layer count before copying userdata
  msm: mdss: Fix potential NULL pointer dereferences
  Revert "msm: mdss: Remove redundant handoff pending check"
  msm: mdss: hdmi: Do not treat intermediate ddc error as failure
  msm: mdss: revisit igc pipe enumeration logic
  msm: mdss: Add PA support for mdss V3
  msm: mdss: Add support for mdss v3 ops
  msm: mdss: Update the postprocessing ops using mdss revision
  msm: mdss: update the caching payload based on mdss version
  msm: clk: hdmi: add support for atomic update
  msm: sde: Add v4l2 rotator driver to enable multi-context usecase
  msm: mdss: refactor pipe type checks
  msm: mdss: add proper layer zorder validation
  msm: mdss: stub bus scaling functions if driver is disabled
  msm: mdss: avoid failure if primary panel pref is not enabled
  msm: adv7533: add support for clients to read audio block
  msm: mdss: add lineptr interrupt support for command mode panels
  msm: mdss: update rotator frame rate in the pipe configuration
  mdss: msm: Avoid excessive failure logs in igc config
  msm: mdss: delay dma commands for split-dsi cmd mode panels
  msm: mdss: enable GDSC before enabling clocks in MDP3 probe
  mdss: dsi: turn off phy power supply during static screen
  mdss: dsi: read dsi and phy revision during dsi ctrl probe
  msm: mdss: Fix memory leak in MDP3 driver
  msm: mdss: delay overlay start until first update for external
  msm: mdss: free splash memory for MSM8909w after splash done
  msm: mdss: hdmi: separate audio from transmitter core
  msm: mdss: disable dsi burst mode when idle is enabled
  msm: mdss: remove invalid csc initialization during hw init
  msm: mdss: dsi: increase dsi error count only for valid errors
  msm: mdss: remove HIST LUT programming in mdss_hw_init
  msm: mdss: dsi: ignore error interrupt when mask not set
  msm: mdss: add support to configure bus scale vectors from dt
  msm: mdss: unstage the pipe if there is z_order mismatch
  msm: mdss: squash MDP3 driver changes and SMMU change
  msm: mdss: Read the bridge chip name and instance id from DTSI
  msm: mdss: Enable continuous splash on bridge chip
  msm: mdss: Fix multiple bridge chip usecase
  msm: mdss: Enable export of mdss interrupt to external driver
  msm: mdss: rotator: turn off rotator clock in wq release
  msm: mdss: fix ulps during suspend feature logic
  clk: msm: mdss: program correct divider for PLL configuration
  msm: mdss: fix DSI PHY timing configuration logic
  msm: mdss: hdmi: add support for hdmi simulation
  msm: mdss: handle race condition in pingpong done counter
  clk: qcom: mdss: calculate pixel clock for HDMI during handoff
  msm: mdss: ensure proper dynamic refresh programming for dual DSI
  msm: mdss: Add fps flag and update blit request version
  msm: mdss: initialize fb split values during fb probe
  mdss: mdp: fix rotator compat layer copy
  msm: mdss: handle DSI ctrl/PHY regulator control properly

Conflicts:
	Documentation/devicetree/bindings/fb/mdss-dsi-panel.txt
	Documentation/devicetree/bindings/fb/mdss-dsi.txt
	Documentation/devicetree/bindings/fb/mdss-mdp.txt
	arch/arm/boot/dts/qcom/dsi-adv7533-1080p.dtsi
	arch/arm/boot/dts/qcom/dsi-adv7533-720p.dtsi
	arch/arm/boot/dts/qcom/msm8996-agave-adp.dtsi
	drivers/media/platform/msm/Kconfig
	drivers/media/platform/msm/Makefile
	drivers/misc/hdcp.c
	drivers/video/fbdev/msm/Makefile
	drivers/video/fbdev/msm/mdp3.c
	drivers/video/fbdev/msm/mdp3.h
	drivers/video/fbdev/msm/mdp3_ctrl.c
	drivers/video/fbdev/msm/mdp3_ctrl.h
	drivers/video/fbdev/msm/mdp3_dma.c
	drivers/video/fbdev/msm/mdp3_dma.h
	drivers/video/fbdev/msm/mdp3_hwio.h
	drivers/video/fbdev/msm/mdp3_ppp.c
	drivers/video/fbdev/msm/mdp3_ppp.h
	drivers/video/fbdev/msm/mdp3_ppp_hwio.c
	drivers/video/fbdev/msm/mdss.h
	drivers/video/fbdev/msm/mdss_compat_utils.c
	drivers/video/fbdev/msm/mdss_dba_utils.c
	drivers/video/fbdev/msm/mdss_dba_utils.h
	drivers/video/fbdev/msm/mdss_debug.c
	drivers/video/fbdev/msm/mdss_dsi.c
	drivers/video/fbdev/msm/mdss_dsi.h
	drivers/video/fbdev/msm/mdss_dsi_clk.c
	drivers/video/fbdev/msm/mdss_dsi_host.c
	drivers/video/fbdev/msm/mdss_dsi_panel.c
	drivers/video/fbdev/msm/mdss_fb.c
	drivers/video/fbdev/msm/mdss_fb.h
	drivers/video/fbdev/msm/mdss_hdmi_edid.c
	drivers/video/fbdev/msm/mdss_hdmi_hdcp2p2.c
	drivers/video/fbdev/msm/mdss_hdmi_tx.c
	drivers/video/fbdev/msm/mdss_hdmi_tx.h
	drivers/video/fbdev/msm/mdss_hdmi_util.c
	drivers/video/fbdev/msm/mdss_mdp.c
	drivers/video/fbdev/msm/mdss_mdp.h
	drivers/video/fbdev/msm/mdss_mdp_ctl.c
	drivers/video/fbdev/msm/mdss_mdp_hwio.h
	drivers/video/fbdev/msm/mdss_mdp_intf_cmd.c
	drivers/video/fbdev/msm/mdss_mdp_intf_writeback.c
	drivers/video/fbdev/msm/mdss_mdp_layer.c
	drivers/video/fbdev/msm/mdss_mdp_overlay.c
	drivers/video/fbdev/msm/mdss_mdp_pipe.c
	drivers/video/fbdev/msm/mdss_mdp_pp.c
	drivers/video/fbdev/msm/mdss_mdp_pp.h
	drivers/video/fbdev/msm/mdss_mdp_pp_cache_config.c
	drivers/video/fbdev/msm/mdss_mdp_pp_v1_7.c
	drivers/video/fbdev/msm/mdss_mdp_util.c
	drivers/video/fbdev/msm/mdss_panel.h
	drivers/video/fbdev/msm/mdss_rotator.c
	drivers/video/fbdev/msm/mdss_rotator_internal.h
	drivers/video/fbdev/msm/mdss_smmu.c
	drivers/video/fbdev/msm/msm_dba/adv7533.c
	drivers/video/fbdev/msm/msm_mdss_io_8974.c
	include/uapi/linux/msm_mdp.h
	include/video/msm_dba.h

CRs-Fixed: 1000197
Change-Id: I521519c8abe8eed6924e2fbe3e1a026126582b77
Signed-off-by: Adrian Salido-Moreno <adrianm@codeaurora.org>
Signed-off-by: Narendra Muppalla <narendram@codeaurora.org>
diff --git a/drivers/media/platform/msm/sde/rotator/sde_rotator_base.c b/drivers/media/platform/msm/sde/rotator/sde_rotator_base.c
new file mode 100644
index 0000000..0665f46
--- /dev/null
+++ b/drivers/media/platform/msm/sde/rotator/sde_rotator_base.c
@@ -0,0 +1,569 @@
+/* Copyright (c) 2012, 2015-2016, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+#define pr_fmt(fmt)	"%s: " fmt, __func__
+
+#include <linux/errno.h>
+#include <linux/file.h>
+#include <linux/spinlock.h>
+#include <linux/types.h>
+#include <linux/major.h>
+#include <linux/debugfs.h>
+#include <linux/clk.h>
+#include <linux/slab.h>
+#include <linux/io.h>
+#include <linux/iopoll.h>
+#include <linux/msm-bus.h>
+#include <linux/msm-bus-board.h>
+#include <linux/regulator/consumer.h>
+
+#define CREATE_TRACE_POINTS
+#include "sde_rotator_base.h"
+#include "sde_rotator_util.h"
+#include "sde_rotator_trace.h"
+
+static inline u64 fudge_factor(u64 val, u32 numer, u32 denom)
+{
+	u64 result = (val * (u64)numer);
+
+	do_div(result, denom);
+	return result;
+}
+
+static inline u64 apply_fudge_factor(u64 val,
+	struct sde_mult_factor *factor)
+{
+	return fudge_factor(val, factor->numer, factor->denom);
+}
+
+static inline u64 apply_inverse_fudge_factor(u64 val,
+	struct sde_mult_factor *factor)
+{
+	return fudge_factor(val, factor->denom, factor->numer);
+}
+
+static inline bool validate_comp_ratio(struct sde_mult_factor *factor)
+{
+	return factor->numer && factor->denom;
+}
+
+u32 sde_apply_comp_ratio_factor(u32 quota,
+	struct sde_mdp_format_params *fmt,
+	struct sde_mult_factor *factor)
+{
+	struct sde_rot_data_type *mdata = sde_rot_get_mdata();
+
+	if (!mdata || !test_bit(SDE_QOS_OVERHEAD_FACTOR,
+		      mdata->sde_qos_map))
+		return quota;
+
+	/* apply compression ratio, only for compressed formats */
+	if (sde_mdp_is_ubwc_format(fmt) &&
+	    validate_comp_ratio(factor))
+		quota = apply_inverse_fudge_factor(quota, factor);
+
+	return quota;
+}
+
+#define RES_1080p		(1088*1920)
+#define RES_UHD		(3840*2160)
+#define XIN_HALT_TIMEOUT_US	0x4000
+
+static int sde_mdp_wait_for_xin_halt(u32 xin_id)
+{
+	void __iomem *vbif_base;
+	u32 status;
+	struct sde_rot_data_type *mdata = sde_rot_get_mdata();
+	u32 idle_mask = BIT(xin_id);
+	int rc;
+
+	vbif_base = mdata->vbif_nrt_io.base;
+
+	rc = readl_poll_timeout(vbif_base + MMSS_VBIF_XIN_HALT_CTRL1,
+		status, (status & idle_mask),
+		1000, XIN_HALT_TIMEOUT_US);
+	if (rc == -ETIMEDOUT) {
+		SDEROT_ERR("VBIF client %d not halting. TIMEDOUT.\n",
+			xin_id);
+	} else {
+		SDEROT_DBG("VBIF client %d is halted\n", xin_id);
+	}
+
+	return rc;
+}
+
+/**
+ * force_on_xin_clk() - enable/disable the force-on for the pipe clock
+ * @bit_off: offset of the bit to enable/disable the force-on.
+ * @reg_off: register offset for the clock control.
+ * @enable: boolean to indicate if the force-on of the clock needs to be
+ * enabled or disabled.
+ *
+ * This function returns:
+ * true - if the clock is forced-on by this function
+ * false - if the clock was already forced on
+ * It is the caller responsibility to check if this function is forcing
+ * the clock on; if so, it will need to remove the force of the clock,
+ * otherwise it should avoid to remove the force-on.
+ * Clocks must be on when calling this function.
+ */
+static bool force_on_xin_clk(u32 bit_off, u32 clk_ctl_reg_off, bool enable)
+{
+	u32 val;
+	u32 force_on_mask;
+	struct sde_rot_data_type *mdata = sde_rot_get_mdata();
+	bool clk_forced_on = false;
+
+	force_on_mask = BIT(bit_off);
+	val = readl_relaxed(mdata->mdp_base + clk_ctl_reg_off);
+
+	clk_forced_on = !(force_on_mask & val);
+
+	if (true == enable)
+		val |= force_on_mask;
+	else
+		val &= ~force_on_mask;
+
+	writel_relaxed(val, mdata->mdp_base + clk_ctl_reg_off);
+
+	return clk_forced_on;
+}
+
+static void apply_dynamic_ot_limit(u32 *ot_lim,
+	struct sde_mdp_set_ot_params *params)
+{
+	struct sde_rot_data_type *mdata = sde_rot_get_mdata();
+	u32 res;
+
+	if (false == test_bit(SDE_QOS_OTLIM, mdata->sde_qos_map))
+		return;
+
+	res = params->width * params->height;
+
+	SDEROT_DBG("w:%d h:%d rot:%d yuv:%d wb:%d res:%d\n",
+		params->width, params->height, params->is_rot,
+		params->is_yuv, params->is_wb, res);
+
+	if ((params->is_rot && params->is_yuv) ||
+		params->is_wb) {
+		if (res <= RES_1080p) {
+			*ot_lim = 2;
+		} else if (res <= RES_UHD) {
+			if (params->is_rot && params->is_yuv)
+				*ot_lim = 8;
+			else
+				*ot_lim = 16;
+		}
+	}
+}
+
+static u32 get_ot_limit(u32 reg_off, u32 bit_off,
+	struct sde_mdp_set_ot_params *params)
+{
+	struct sde_rot_data_type *mdata = sde_rot_get_mdata();
+	u32 ot_lim = 0;
+	u32 val;
+
+	if (mdata->default_ot_wr_limit &&
+		(params->reg_off_vbif_lim_conf == MMSS_VBIF_WR_LIM_CONF))
+		ot_lim = mdata->default_ot_wr_limit;
+	else if (mdata->default_ot_rd_limit &&
+		(params->reg_off_vbif_lim_conf == MMSS_VBIF_RD_LIM_CONF))
+		ot_lim = mdata->default_ot_rd_limit;
+
+	/*
+	 * If default ot is not set from dt,
+	 * then do not configure it.
+	 */
+	if (ot_lim == 0)
+		goto exit;
+
+	/* Modify the limits if the target and the use case requires it */
+	apply_dynamic_ot_limit(&ot_lim, params);
+
+	val = SDE_VBIF_READ(mdata, reg_off);
+	val &= (0xFF << bit_off);
+	val = val >> bit_off;
+
+	if (val == ot_lim)
+		ot_lim = 0;
+
+exit:
+	SDEROT_DBG("ot_lim=%d\n", ot_lim);
+	return ot_lim;
+}
+
+void sde_mdp_set_ot_limit(struct sde_mdp_set_ot_params *params)
+{
+	struct sde_rot_data_type *mdata = sde_rot_get_mdata();
+	u32 ot_lim;
+	u32 reg_off_vbif_lim_conf = (params->xin_id / 4) * 4 +
+		params->reg_off_vbif_lim_conf;
+	u32 bit_off_vbif_lim_conf = (params->xin_id % 4) * 8;
+	u32 reg_val;
+	bool forced_on;
+
+	ot_lim = get_ot_limit(
+		reg_off_vbif_lim_conf,
+		bit_off_vbif_lim_conf,
+		params) & 0xFF;
+
+	if (ot_lim == 0)
+		goto exit;
+
+	trace_rot_perf_set_ot(params->num, params->xin_id, ot_lim);
+
+	forced_on = force_on_xin_clk(params->bit_off_mdp_clk_ctrl,
+		params->reg_off_mdp_clk_ctrl, true);
+
+	reg_val = SDE_VBIF_READ(mdata, reg_off_vbif_lim_conf);
+	reg_val &= ~(0xFF << bit_off_vbif_lim_conf);
+	reg_val |= (ot_lim) << bit_off_vbif_lim_conf;
+	SDE_VBIF_WRITE(mdata, reg_off_vbif_lim_conf, reg_val);
+
+	reg_val = SDE_VBIF_READ(mdata, MMSS_VBIF_XIN_HALT_CTRL0);
+	SDE_VBIF_WRITE(mdata, MMSS_VBIF_XIN_HALT_CTRL0,
+		reg_val | BIT(params->xin_id));
+
+	/* this is a polling operation */
+	sde_mdp_wait_for_xin_halt(params->xin_id);
+
+	reg_val = SDE_VBIF_READ(mdata, MMSS_VBIF_XIN_HALT_CTRL0);
+	SDE_VBIF_WRITE(mdata, MMSS_VBIF_XIN_HALT_CTRL0,
+		reg_val & ~BIT(params->xin_id));
+
+	if (forced_on)
+		force_on_xin_clk(params->bit_off_mdp_clk_ctrl,
+			params->reg_off_mdp_clk_ctrl, false);
+
+exit:
+	return;
+}
+
+struct reg_bus_client *sde_reg_bus_vote_client_create(char *client_name)
+{
+	struct reg_bus_client *client;
+	struct sde_rot_data_type *sde_res = sde_rot_get_mdata();
+	static u32 id;
+
+	if (client_name == NULL) {
+		SDEROT_ERR("client name is null\n");
+		return ERR_PTR(-EINVAL);
+	}
+
+	client = kzalloc(sizeof(struct reg_bus_client), GFP_KERNEL);
+	if (!client)
+		return ERR_PTR(-ENOMEM);
+
+	mutex_lock(&sde_res->reg_bus_lock);
+	strlcpy(client->name, client_name, MAX_CLIENT_NAME_LEN);
+	client->usecase_ndx = VOTE_INDEX_DISABLE;
+	client->id = id;
+	SDEROT_DBG("bus vote client %s created:%p id :%d\n", client_name,
+		client, id);
+	id++;
+	list_add(&client->list, &sde_res->reg_bus_clist);
+	mutex_unlock(&sde_res->reg_bus_lock);
+
+	return client;
+}
+
+void sde_reg_bus_vote_client_destroy(struct reg_bus_client *client)
+{
+	struct sde_rot_data_type *sde_res = sde_rot_get_mdata();
+
+	if (!client) {
+		SDEROT_ERR("reg bus vote: invalid client handle\n");
+	} else {
+		SDEROT_DBG("bus vote client %s destroyed:%p id:%u\n",
+			client->name, client, client->id);
+		mutex_lock(&sde_res->reg_bus_lock);
+		list_del_init(&client->list);
+		mutex_unlock(&sde_res->reg_bus_lock);
+		kfree(client);
+	}
+}
+
+int sde_update_reg_bus_vote(struct reg_bus_client *bus_client, u32 usecase_ndx)
+{
+	int ret = 0;
+	bool changed = false;
+	u32 max_usecase_ndx = VOTE_INDEX_DISABLE;
+	struct reg_bus_client *client, *temp_client;
+	struct sde_rot_data_type *sde_res = sde_rot_get_mdata();
+
+	if (!sde_res || !sde_res->reg_bus_hdl || !bus_client)
+		return 0;
+
+	mutex_lock(&sde_res->reg_bus_lock);
+	bus_client->usecase_ndx = usecase_ndx;
+	list_for_each_entry_safe(client, temp_client, &sde_res->reg_bus_clist,
+		list) {
+
+		if (client->usecase_ndx < VOTE_INDEX_MAX &&
+		    client->usecase_ndx > max_usecase_ndx)
+			max_usecase_ndx = client->usecase_ndx;
+	}
+
+	if (sde_res->reg_bus_usecase_ndx != max_usecase_ndx) {
+		changed = true;
+		sde_res->reg_bus_usecase_ndx = max_usecase_ndx;
+	}
+
+	SDEROT_DBG(
+		"%pS: changed=%d current idx=%d request client %s id:%u idx:%d\n",
+		__builtin_return_address(0), changed, max_usecase_ndx,
+		bus_client->name, bus_client->id, usecase_ndx);
+	if (changed)
+		ret = msm_bus_scale_client_update_request(sde_res->reg_bus_hdl,
+			max_usecase_ndx);
+
+	mutex_unlock(&sde_res->reg_bus_lock);
+	return ret;
+}
+
+static int sde_mdp_parse_dt_handler(struct platform_device *pdev,
+		char *prop_name, u32 *offsets, int len)
+{
+	int rc;
+
+	rc = of_property_read_u32_array(pdev->dev.of_node, prop_name,
+					offsets, len);
+	if (rc) {
+		SDEROT_ERR("Error from prop %s : u32 array read\n", prop_name);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int sde_mdp_parse_dt_prop_len(struct platform_device *pdev,
+				      char *prop_name)
+{
+	int len = 0;
+
+	of_find_property(pdev->dev.of_node, prop_name, &len);
+
+	if (len < 1) {
+		SDEROT_INFO("prop %s : doesn't exist in device tree\n",
+			prop_name);
+		return 0;
+	}
+
+	len = len/sizeof(u32);
+
+	return len;
+}
+
+static void sde_mdp_parse_vbif_qos(struct platform_device *pdev,
+		struct sde_rot_data_type *mdata)
+{
+	int rc;
+
+	mdata->vbif_rt_qos = NULL;
+
+	mdata->npriority_lvl = sde_mdp_parse_dt_prop_len(pdev,
+			"qcom,mdss-rot-vbif-qos-setting");
+	mdata->vbif_nrt_qos = kzalloc(sizeof(u32) *
+			mdata->npriority_lvl, GFP_KERNEL);
+	if (!mdata->vbif_nrt_qos)
+		return;
+
+	rc = sde_mdp_parse_dt_handler(pdev,
+		"qcom,mdss-rot-vbif-qos-setting", mdata->vbif_nrt_qos,
+			mdata->npriority_lvl);
+	if (rc) {
+		SDEROT_DBG("vbif setting not found\n");
+		return;
+	}
+}
+
+static int sde_mdp_parse_dt_misc(struct platform_device *pdev,
+		struct sde_rot_data_type *mdata)
+{
+	int rc;
+	u32 data;
+
+	rc = of_property_read_u32(pdev->dev.of_node, "qcom,mdss-rot-block-size",
+		&data);
+	mdata->rot_block_size = (!rc ? data : 128);
+
+	rc = of_property_read_u32(pdev->dev.of_node,
+		"qcom,mdss-default-ot-rd-limit", &data);
+	mdata->default_ot_rd_limit = (!rc ? data : 0);
+
+	rc = of_property_read_u32(pdev->dev.of_node,
+		"qcom,mdss-default-ot-wr-limit", &data);
+	mdata->default_ot_wr_limit = (!rc ? data : 0);
+
+	rc = of_property_read_u32(pdev->dev.of_node,
+		 "qcom,mdss-highest-bank-bit", &(mdata->highest_bank_bit));
+	if (rc)
+		SDEROT_DBG(
+			"Could not read optional property: highest bank bit\n");
+
+	sde_mdp_parse_vbif_qos(pdev, mdata);
+
+	mdata->mdp_base = mdata->sde_io.base + SDE_MDP_OFFSET;
+
+	return 0;
+}
+
+#define MDP_REG_BUS_VECTOR_ENTRY(ab_val, ib_val)	\
+	{						\
+		.src = MSM_BUS_MASTER_AMPSS_M0,		\
+		.dst = MSM_BUS_SLAVE_DISPLAY_CFG,	\
+		.ab = (ab_val),				\
+		.ib = (ib_val),				\
+	}
+
+#define BUS_VOTE_19_MHZ 153600000
+#define BUS_VOTE_40_MHZ 320000000
+#define BUS_VOTE_80_MHZ 640000000
+
+static struct msm_bus_vectors mdp_reg_bus_vectors[] = {
+	MDP_REG_BUS_VECTOR_ENTRY(0, 0),
+	MDP_REG_BUS_VECTOR_ENTRY(0, BUS_VOTE_19_MHZ),
+	MDP_REG_BUS_VECTOR_ENTRY(0, BUS_VOTE_40_MHZ),
+	MDP_REG_BUS_VECTOR_ENTRY(0, BUS_VOTE_80_MHZ),
+};
+static struct msm_bus_paths mdp_reg_bus_usecases[ARRAY_SIZE(
+		mdp_reg_bus_vectors)];
+static struct msm_bus_scale_pdata mdp_reg_bus_scale_table = {
+	.usecase = mdp_reg_bus_usecases,
+	.num_usecases = ARRAY_SIZE(mdp_reg_bus_usecases),
+	.name = "sde_reg",
+	.active_only = true,
+};
+
+static int sde_mdp_bus_scale_register(struct sde_rot_data_type *mdata)
+{
+	struct msm_bus_scale_pdata *reg_bus_pdata;
+	int i;
+
+	if (!mdata->reg_bus_hdl) {
+		reg_bus_pdata = &mdp_reg_bus_scale_table;
+		for (i = 0; i < reg_bus_pdata->num_usecases; i++) {
+			mdp_reg_bus_usecases[i].num_paths = 1;
+			mdp_reg_bus_usecases[i].vectors =
+				&mdp_reg_bus_vectors[i];
+		}
+
+		mdata->reg_bus_hdl =
+			msm_bus_scale_register_client(reg_bus_pdata);
+		if (!mdata->reg_bus_hdl) {
+			/* Continue without reg_bus scaling */
+			SDEROT_WARN("reg_bus_client register failed\n");
+		} else
+			SDEROT_DBG("register reg_bus_hdl=%x\n",
+					mdata->reg_bus_hdl);
+	}
+
+	return 0;
+}
+
+static void sde_mdp_bus_scale_unregister(struct sde_rot_data_type *mdata)
+{
+	SDEROT_DBG("unregister reg_bus_hdl=%x\n", mdata->reg_bus_hdl);
+
+	if (mdata->reg_bus_hdl) {
+		msm_bus_scale_unregister_client(mdata->reg_bus_hdl);
+		mdata->reg_bus_hdl = 0;
+	}
+}
+
+static struct sde_rot_data_type *sde_rot_res;
+
+struct sde_rot_data_type *sde_rot_get_mdata(void)
+{
+	return sde_rot_res;
+}
+
+/*
+ * sde_rotator_base_init - initialize base rotator data/resource
+ */
+int sde_rotator_base_init(struct sde_rot_data_type **pmdata,
+		struct platform_device *pdev,
+		const void *drvdata)
+{
+	int rc;
+	struct sde_rot_data_type *mdata;
+
+	mdata = devm_kzalloc(&pdev->dev, sizeof(*mdata), GFP_KERNEL);
+	if (mdata == NULL)
+		return -ENOMEM;
+
+	mdata->pdev = pdev;
+	sde_rot_res = mdata;
+	mutex_init(&mdata->reg_bus_lock);
+	INIT_LIST_HEAD(&mdata->reg_bus_clist);
+
+	rc = sde_rot_ioremap_byname(pdev, &mdata->sde_io, "mdp_phys");
+	if (rc) {
+		SDEROT_ERR("unable to map SDE base\n");
+		goto probe_done;
+	}
+	SDEROT_DBG("SDE ROT HW Base addr=0x%x len=0x%x\n",
+		(int) (unsigned long) mdata->sde_io.base,
+		mdata->sde_io.len);
+
+	rc = sde_rot_ioremap_byname(pdev, &mdata->vbif_nrt_io, "rot_vbif_phys");
+	if (rc) {
+		SDEROT_ERR("unable to map SDE ROT VBIF base\n");
+		goto probe_done;
+	}
+	SDEROT_DBG("SDE ROT VBIF HW Base addr=%p len=0x%x\n",
+			mdata->vbif_nrt_io.base, mdata->vbif_nrt_io.len);
+
+	rc = sde_mdp_parse_dt_misc(pdev, mdata);
+	if (rc) {
+		SDEROT_ERR("Error in device tree : misc\n");
+		goto probe_done;
+	}
+
+	rc = sde_mdp_bus_scale_register(mdata);
+	if (rc) {
+		SDEROT_ERR("unable to register bus scaling\n");
+		goto probe_done;
+	}
+
+	rc = sde_smmu_init(&pdev->dev);
+	if (rc) {
+		SDEROT_ERR("sde smmu init failed %d\n", rc);
+		goto probe_done;
+	}
+
+	*pmdata = mdata;
+
+	return 0;
+probe_done:
+	return rc;
+}
+
+/*
+ * sde_rotator_base_destroy - clean up base rotator data/resource
+ */
+void sde_rotator_base_destroy(struct sde_rot_data_type *mdata)
+{
+	struct platform_device *pdev;
+
+	if (!mdata || !mdata->pdev)
+		return;
+
+	pdev = mdata->pdev;
+
+	sde_rot_res = NULL;
+	sde_mdp_bus_scale_unregister(mdata);
+	sde_rot_iounmap(&mdata->vbif_nrt_io);
+	sde_rot_iounmap(&mdata->sde_io);
+	devm_kfree(&pdev->dev, mdata);
+}