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

Commit 480aa758 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 additional DMA pipes"

parents 31484448 7e03cc68
Loading
Loading
Loading
Loading
+90 −250
Original line number Diff line number Diff line
@@ -81,10 +81,6 @@ struct msm_mdp_interface mdp5 = {
	.get_format_params = mdss_mdp_get_format_params,
};

#define DEFAULT_TOTAL_RGB_PIPES 3
#define DEFAULT_TOTAL_VIG_PIPES 3
#define DEFAULT_TOTAL_DMA_PIPES 2

#define IB_QUOTA 2000000000
#define AB_QUOTA 2000000000

@@ -2394,7 +2390,7 @@ int mdss_mdp_parse_dt_hw_settings(struct platform_device *pdev)
	vbif_arr = of_get_property(pdev->dev.of_node, "qcom,vbif-settings",
			&vbif_len);
	if (!vbif_arr || (vbif_len & 1)) {
		pr_warn("MDSS VBIF settings not found\n");
		pr_debug("MDSS VBIF settings not found\n");
		vbif_len = 0;
	}
	vbif_len /= 2 * sizeof(u32);
@@ -2410,7 +2406,7 @@ int mdss_mdp_parse_dt_hw_settings(struct platform_device *pdev)
	mdp_arr = of_get_property(pdev->dev.of_node, "qcom,mdp-settings",
			&mdp_len);
	if (!mdp_arr || (mdp_len & 1)) {
		pr_warn("MDSS MDP settings not found\n");
		pr_debug("MDSS MDP settings not found\n");
		mdp_len = 0;
	}
	mdp_len /= 2 * sizeof(u32);
@@ -2638,267 +2634,86 @@ static void mdss_mdp_parse_dt_pipe_panic_ctrl(struct platform_device *pdev,
}

static int mdss_mdp_parse_dt_pipe_helper(struct platform_device *pdev,
		u32 npipes,
		u32 nfids)
		u32 ptype, char *ptypestr,
		struct mdss_mdp_pipe **out_plist,
		size_t len,
		u8 priority_base)
{
	u32 dma_off;
	u32 *offsets = NULL, *ftch_id = NULL, *xin_id = NULL;
	u32 len;
	uint32_t setup_cnt = 0;
	int rc = 0, i;
	struct mdss_data_type *mdata = platform_get_drvdata(pdev);
	u32 offsets[MDSS_MDP_MAX_SSPP];
	u32 ftch_id[MDSS_MDP_MAX_SSPP];
	u32 xin_id[MDSS_MDP_MAX_SSPP];
	u32 pnums[MDSS_MDP_MAX_SSPP];
	struct mdss_mdp_pipe *pipe_list;
	char prop_name[64];
	int i, cnt, rc;

	if (!out_plist)
		return -EINVAL;

	offsets = kcalloc(npipes, sizeof(u32), GFP_KERNEL);
	if (!offsets)
		return -ENOMEM;

	ftch_id = kcalloc(npipes, sizeof(u32), GFP_KERNEL);
	if (!ftch_id) {
		rc = -ENOMEM;
		goto ftch_alloc_fail;
	}

	xin_id = kcalloc(npipes, sizeof(u32), GFP_KERNEL);
	if (!xin_id) {
		rc = -ENOMEM;
		goto xin_alloc_fail;
	}

	if (mdata->nvig_pipes) {
		mdata->vig_pipes = devm_kzalloc(&mdata->pdev->dev,
				    (sizeof(struct mdss_mdp_pipe)
				     * mdata->nvig_pipes), GFP_KERNEL);
		if (!mdata->vig_pipes) {
			rc = -ENOMEM;
			goto vig_alloc_fail;
		}
		if (nfids) {
			rc = mdss_mdp_parse_dt_handler(pdev,
					"qcom,mdss-pipe-vig-fetch-id", ftch_id,
					mdata->nvig_pipes);
			if (rc)
				goto parse_fail;
		}

		rc = mdss_mdp_parse_dt_handler(pdev,
				"qcom,mdss-pipe-vig-xin-id", xin_id,
				mdata->nvig_pipes);
		if (rc)
			goto parse_fail;

		rc = mdss_mdp_parse_dt_handler(pdev, "qcom,mdss-pipe-vig-off",
				offsets, mdata->nvig_pipes);
		if (rc)
			goto parse_fail;

		len = min_t(int, DEFAULT_TOTAL_VIG_PIPES,
			    (int)mdata->nvig_pipes);
		rc = mdss_mdp_pipe_addr_setup(mdata, mdata->vig_pipes, offsets,
					ftch_id, xin_id, MDSS_MDP_PIPE_TYPE_VIG,
					MDSS_MDP_SSPP_VIG0, len, 0);
		if (rc)
			goto parse_fail;

		setup_cnt += len;
	}

	if (mdata->nrgb_pipes) {
		mdata->rgb_pipes = devm_kzalloc(&mdata->pdev->dev,
				(sizeof(struct mdss_mdp_pipe) *
				 mdata->nrgb_pipes), GFP_KERNEL);
		if (!mdata->rgb_pipes) {
			rc = -ENOMEM;
			goto rgb_alloc_fail;
		}

		if (nfids) {
			rc = mdss_mdp_parse_dt_handler(pdev,
					"qcom,mdss-pipe-rgb-fetch-id",
					ftch_id + mdata->nvig_pipes,
					mdata->nrgb_pipes);
			if (rc)
				goto parse_fail;
		}

		rc = mdss_mdp_parse_dt_handler(pdev,
				"qcom,mdss-pipe-rgb-xin-id",
				xin_id + mdata->nvig_pipes, mdata->nrgb_pipes);
		if (rc)
			goto parse_fail;

		rc = mdss_mdp_parse_dt_handler(pdev, "qcom,mdss-pipe-rgb-off",
				offsets + mdata->nvig_pipes, mdata->nrgb_pipes);
		if (rc)
			goto parse_fail;

		len = min_t(int, DEFAULT_TOTAL_RGB_PIPES,
			    (int)mdata->nrgb_pipes);
		rc = mdss_mdp_pipe_addr_setup(mdata, mdata->rgb_pipes,
				offsets + mdata->nvig_pipes,
				ftch_id + mdata->nvig_pipes,
				xin_id + mdata->nvig_pipes,
				MDSS_MDP_PIPE_TYPE_RGB,
				MDSS_MDP_SSPP_RGB0, len, mdata->nvig_pipes);
		if (rc)
			goto parse_fail;

		setup_cnt += len;
	}

	if (mdata->ndma_pipes) {
		mdata->dma_pipes = devm_kzalloc(&mdata->pdev->dev,
			sizeof(struct mdss_mdp_pipe) * mdata->ndma_pipes,
			GFP_KERNEL);
		if (!mdata->dma_pipes) {
			pr_err("no mem for dma_pipes: kzalloc fail\n");
			rc = -ENOMEM;
			goto dma_alloc_fail;
		}

		dma_off = mdata->nvig_pipes + mdata->nrgb_pipes;

		if (nfids) {
			rc = mdss_mdp_parse_dt_handler(pdev,
				"qcom,mdss-pipe-dma-fetch-id",
				ftch_id + dma_off, mdata->ndma_pipes);
			if (rc)
				goto parse_fail;
		}

		rc = mdss_mdp_parse_dt_handler(pdev,
			"qcom,mdss-pipe-dma-xin-id",
			xin_id + dma_off, mdata->ndma_pipes);
		if (rc)
			goto parse_fail;

		rc = mdss_mdp_parse_dt_handler(pdev, "qcom,mdss-pipe-dma-off",
			offsets + dma_off, mdata->ndma_pipes);
		if (rc)
			goto parse_fail;

		len = mdata->ndma_pipes;
		rc = mdss_mdp_pipe_addr_setup(mdata, mdata->dma_pipes,
			offsets + dma_off, ftch_id + dma_off, xin_id + dma_off,
			MDSS_MDP_PIPE_TYPE_DMA, MDSS_MDP_SSPP_DMA0, len,
			mdata->nvig_pipes + mdata->nrgb_pipes);
		if (rc)
			goto parse_fail;

		setup_cnt += len;
	for (i = 0, cnt = 0; i < MDSS_MDP_MAX_SSPP && cnt < len; i++) {
		if (ptype == get_pipe_type_from_num(i)) {
			pnums[cnt] = i;
			cnt++;
		}

	if (mdata->nvig_pipes > DEFAULT_TOTAL_VIG_PIPES) {
		rc = mdss_mdp_pipe_addr_setup(mdata,
			mdata->vig_pipes + DEFAULT_TOTAL_VIG_PIPES,
			offsets + DEFAULT_TOTAL_VIG_PIPES,
			ftch_id + DEFAULT_TOTAL_VIG_PIPES,
			xin_id + DEFAULT_TOTAL_VIG_PIPES,
			MDSS_MDP_PIPE_TYPE_VIG, setup_cnt,
			mdata->nvig_pipes - DEFAULT_TOTAL_VIG_PIPES,
			DEFAULT_TOTAL_VIG_PIPES);
		if (rc)
			goto parse_fail;

		setup_cnt += mdata->nvig_pipes - DEFAULT_TOTAL_VIG_PIPES;
	}

	if (mdata->nrgb_pipes > DEFAULT_TOTAL_RGB_PIPES) {
		rc = mdss_mdp_pipe_addr_setup(mdata,
			mdata->rgb_pipes + DEFAULT_TOTAL_RGB_PIPES,
			offsets + mdata->nvig_pipes + DEFAULT_TOTAL_RGB_PIPES,
			ftch_id + mdata->nvig_pipes + DEFAULT_TOTAL_RGB_PIPES,
			xin_id + mdata->nvig_pipes + DEFAULT_TOTAL_RGB_PIPES,
			MDSS_MDP_PIPE_TYPE_RGB, setup_cnt,
			mdata->nrgb_pipes - DEFAULT_TOTAL_RGB_PIPES,
			mdata->nvig_pipes + DEFAULT_TOTAL_RGB_PIPES);
		if (rc)
			goto parse_fail;
	if (cnt < len)
		pr_warn("Invalid %s pipe count: %zu, max supported: %d\n",
				ptypestr, len, cnt);
	if (cnt == 0) {
		*out_plist = NULL;

		setup_cnt += mdata->nrgb_pipes - DEFAULT_TOTAL_RGB_PIPES;
		return 0;
	}

	if (mdata->nvig_pipes) {
		rc = mdss_mdp_parse_dt_pipe_clk_ctrl(pdev,
				"qcom,mdss-pipe-vig-clk-ctrl-offsets",
				mdata->vig_pipes,
				mdata->nvig_pipes);
		if (rc)
			goto parse_fail;
	}
	pipe_list = devm_kzalloc(&pdev->dev,
			(sizeof(struct mdss_mdp_pipe) * cnt), GFP_KERNEL);
	if (!pipe_list)
		return -ENOMEM;

	if (mdata->nrgb_pipes) {
		rc = mdss_mdp_parse_dt_pipe_clk_ctrl(pdev,
				"qcom,mdss-pipe-rgb-clk-ctrl-offsets",
				mdata->rgb_pipes,
				mdata->nrgb_pipes);
	if (mdata->has_pixel_ram || (ptype == MDSS_MDP_PIPE_TYPE_CURSOR)) {
		for (i = 0; i < cnt; i++)
			ftch_id[i] = -1;
	} else {
		snprintf(prop_name, sizeof(prop_name),
				"qcom,mdss-pipe-%s-fetch-id", ptypestr);
		rc = mdss_mdp_parse_dt_handler(pdev, prop_name, ftch_id,
				cnt);
		if (rc)
			goto parse_fail;
	}

	if (mdata->ndma_pipes) {
		rc = mdss_mdp_parse_dt_pipe_clk_ctrl(pdev,
			"qcom,mdss-pipe-dma-clk-ctrl-offsets", mdata->dma_pipes,
			mdata->ndma_pipes);
	snprintf(prop_name, sizeof(prop_name),
			"qcom,mdss-pipe-%s-xin-id", ptypestr);
	rc = mdss_mdp_parse_dt_handler(pdev, prop_name, xin_id, cnt);
	if (rc)
		goto parse_fail;
	}

	if (mdata->ncursor_pipes) {
		mdata->cursor_pipes = devm_kzalloc(&mdata->pdev->dev,
			sizeof(struct mdss_mdp_pipe) * mdata->ncursor_pipes,
			GFP_KERNEL);

		if (!mdata->cursor_pipes) {
			pr_err("no mem for cursor_pipes: kzalloc fail\n");
			rc = -ENOMEM;
			goto cursor_alloc_fail;
		}
		rc = mdss_mdp_parse_dt_handler(pdev,
			"qcom,mdss-pipe-cursor-off", offsets,
			mdata->ncursor_pipes);
	snprintf(prop_name, sizeof(prop_name),
			"qcom,mdss-pipe-%s-off", ptypestr);
	rc = mdss_mdp_parse_dt_handler(pdev, prop_name, offsets, cnt);
	if (rc)
		goto parse_fail;

		rc = mdss_mdp_parse_dt_handler(pdev,
			"qcom,mdss-pipe-cursor-xin-id", xin_id,
			mdata->ncursor_pipes);
	rc = mdss_mdp_pipe_addr_setup(mdata, pipe_list, offsets, ftch_id,
			xin_id, ptype, pnums, cnt, priority_base);
	if (rc)
		goto parse_fail;

		rc = mdss_mdp_parse_dt_pipe_clk_ctrl(pdev,
			"qcom,mdss-pipe-cursor-clk-ctrl-offsets",
			mdata->cursor_pipes, mdata->ncursor_pipes);
	snprintf(prop_name, sizeof(prop_name),
			"qcom,mdss-pipe-%s-clk-ctrl-offsets", ptypestr);
	rc = mdss_mdp_parse_dt_pipe_clk_ctrl(pdev, prop_name,
			pipe_list, cnt);
	if (rc)
		goto parse_fail;

		/* set the fetch id to an invalid value */
		for (i = 0; i < mdata->ncursor_pipes; i++)
			ftch_id[i] = -1;
		rc = mdss_mdp_pipe_addr_setup(mdata, mdata->cursor_pipes,
			offsets, ftch_id, xin_id, MDSS_MDP_PIPE_TYPE_CURSOR,
			MDSS_MDP_SSPP_CURSOR0, mdata->ncursor_pipes, 0);
		if (rc)
			goto parse_fail;
		pr_info("dedicated vp cursors detected, num=%d\n",
			mdata->ncursor_pipes);
	}
	goto parse_done;
	*out_plist = pipe_list;

	return cnt;
parse_fail:
	kfree(mdata->cursor_pipes);
cursor_alloc_fail:
	kfree(mdata->cursor_pipes);
dma_alloc_fail:
	kfree(mdata->rgb_pipes);
rgb_alloc_fail:
	kfree(mdata->vig_pipes);
vig_alloc_fail:
	kfree(xin_id);
xin_alloc_fail:
	kfree(ftch_id);
ftch_alloc_fail:
	kfree(offsets);
parse_done:
	devm_kfree(&pdev->dev, pipe_list);

	return rc;
}

@@ -2952,9 +2767,34 @@ static int mdss_mdp_parse_dt_pipe(struct platform_device *pdev)
		return -EINVAL;
	}

	rc = mdss_mdp_parse_dt_pipe_helper(pdev, npipes, nfids);
	if (rc)
	rc = mdss_mdp_parse_dt_pipe_helper(pdev, MDSS_MDP_PIPE_TYPE_VIG, "vig",
			&mdata->vig_pipes, mdata->nvig_pipes, 0);
	if (IS_ERR_VALUE(rc))
		goto parse_fail;
	mdata->nvig_pipes = rc;

	rc = mdss_mdp_parse_dt_pipe_helper(pdev, MDSS_MDP_PIPE_TYPE_RGB, "rgb",
			&mdata->rgb_pipes, mdata->nrgb_pipes,
			mdata->nvig_pipes);
	if (IS_ERR_VALUE(rc))
		goto parse_fail;
	mdata->nrgb_pipes = rc;

	rc = mdss_mdp_parse_dt_pipe_helper(pdev, MDSS_MDP_PIPE_TYPE_DMA, "dma",
			&mdata->dma_pipes, mdata->ndma_pipes,
			mdata->nvig_pipes + mdata->nrgb_pipes);
	if (IS_ERR_VALUE(rc))
		goto parse_fail;
	mdata->ndma_pipes = rc;

	rc = mdss_mdp_parse_dt_pipe_helper(pdev, MDSS_MDP_PIPE_TYPE_CURSOR,
			"cursor", &mdata->cursor_pipes, mdata->ncursor_pipes,
			0);
	if (IS_ERR_VALUE(rc))
		goto parse_fail;
	mdata->ncursor_pipes = rc;

	rc = 0;

	mdss_mdp_parse_dt_handler(pdev, "qcom,mdss-pipe-sw-reset-off",
		&sw_reset_offset, 1);
@@ -4035,7 +3875,7 @@ static int mdss_mdp_parse_dt_prop_len(struct platform_device *pdev,
	of_find_property(pdev->dev.of_node, prop_name, &len);

	if (len < 1) {
		pr_info("prop %s : doesn't exist in device tree\n",
		pr_debug("prop %s : doesn't exist in device tree\n",
			prop_name);
		return 0;
	}
+6 −5
Original line number Diff line number Diff line
@@ -157,6 +157,8 @@ get_pipe_type_from_num(enum mdss_mdp_sspp_index pnum)
		break;
	case MDSS_MDP_SSPP_DMA0:
	case MDSS_MDP_SSPP_DMA1:
	case MDSS_MDP_SSPP_DMA2:
	case MDSS_MDP_SSPP_DMA3:
		ptype = MDSS_MDP_PIPE_TYPE_DMA;
		break;
	case MDSS_MDP_SSPP_CURSOR0:
@@ -1537,8 +1539,8 @@ void mdss_mdp_smp_unreserve(struct mdss_mdp_pipe *pipe);
void mdss_mdp_smp_release(struct mdss_mdp_pipe *pipe);

int mdss_mdp_pipe_addr_setup(struct mdss_data_type *mdata,
	struct mdss_mdp_pipe *head, u32 *offsets, u32 *ftch_y_id, u32 *xin_id,
	u32 type, u32 num_base, u32 len, u8 priority_base);
	struct mdss_mdp_pipe *head, u32 *offsets, u32 *ftch_id, u32 *xin_id,
	u32 type, const int *pnums, u32 len, u8 priority_base);
int mdss_mdp_mixer_addr_setup(struct mdss_data_type *mdata, u32 *mixer_offsets,
		u32 *dspp_offsets, u32 *pingpong_offsets, u32 type, u32 len);
int mdss_mdp_ctl_addr_setup(struct mdss_data_type *mdata, u32 *ctl_offsets,
@@ -1597,9 +1599,8 @@ int mdss_mdp_wb_kickoff(struct msm_fb_data_type *mfd,
int mdss_mdp_wb_ioctl_handler(struct msm_fb_data_type *mfd, u32 cmd, void *arg);

int mdss_mdp_get_ctl_mixers(u32 fb_num, u32 *mixer_id);
u32 mdss_mdp_get_mixer_mask(u32 pipe_num, u32 stage);
u32 mdss_mdp_get_mixer_extn_mask(u32 pipe_num, u32 stage);
u32 mdss_mdp_get_mixercfg(struct mdss_mdp_mixer *mixer, bool extn);
bool mdss_mdp_mixer_reg_has_pipe(struct mdss_mdp_mixer *mixer,
		struct mdss_mdp_pipe *pipe);
u32 mdss_mdp_fb_stride(u32 fb_index, u32 xres, int bpp);
void mdss_check_dsi_ctrl_status(struct work_struct *work, uint32_t interval);

+187 −162
Original line number Diff line number Diff line
@@ -27,7 +27,39 @@
#include "mdss_mdp_trace.h"
#include "mdss_debug.h"

#define NUM_MIXERCFG_REGS 3
#define MDSS_MDP_WB_OUTPUT_BPP	3
struct mdss_mdp_mixer_cfg {
	u32 config_masks[NUM_MIXERCFG_REGS];
	bool border_enabled;
	bool cursor_enabled;
};

static struct {
	u32 flush_bit;
	struct mdss_mdp_hwio_cfg base;
	struct mdss_mdp_hwio_cfg ext;
	struct mdss_mdp_hwio_cfg ext2;
} mdp_pipe_hwio[MDSS_MDP_MAX_SSPP] = {
	[MDSS_MDP_SSPP_VIG0]    = {  0, {  0, 3, 0 }, {  0, 1, 3 } },
	[MDSS_MDP_SSPP_VIG1]    = {  1, {  3, 3, 0 }, {  2, 1, 3 } },
	[MDSS_MDP_SSPP_VIG2]    = {  2, {  6, 3, 0 }, {  4, 1, 3 } },
	[MDSS_MDP_SSPP_VIG3]    = { 18, { 26, 3, 0 }, {  4, 1, 3 } },
	[MDSS_MDP_SSPP_RGB0]    = {  3, {  9, 3, 0 }, {  8, 1, 3 } },
	[MDSS_MDP_SSPP_RGB1]    = {  4, { 12, 3, 0 }, { 10, 1, 3 } },
	[MDSS_MDP_SSPP_RGB2]    = {  5, { 15, 3, 0 }, { 12, 1, 3 } },
	[MDSS_MDP_SSPP_RGB3]    = { 19, { 29, 3, 0 }, { 14, 1, 3 } },
	[MDSS_MDP_SSPP_DMA0]    = { 11, { 18, 3, 0 }, { 16, 1, 3 } },
	[MDSS_MDP_SSPP_DMA1]    = { 12, { 21, 3, 0 }, { 18, 1, 3 } },
	[MDSS_MDP_SSPP_DMA2]    = { 24, .ext2 = {  0, 4, 0 } },
	[MDSS_MDP_SSPP_DMA3]    = { 25, .ext2 = {  4, 4, 0 } },
	[MDSS_MDP_SSPP_CURSOR0] = { 22, .ext  = { 20, 4, 0 } },
	[MDSS_MDP_SSPP_CURSOR1] = { 23, .ext  = { 26, 4, 0 } },
};

static void __mdss_mdp_mixer_write_cfg(struct mdss_mdp_mixer *mixer,
		struct mdss_mdp_mixer_cfg *cfg);
static void __mdss_mdp_reset_mixercfg(struct mdss_mdp_ctl *ctl);

static inline u64 fudge_factor(u64 val, u32 numer, u32 denom)
{
@@ -52,82 +84,6 @@ static DEFINE_MUTEX(mdss_mdp_ctl_lock);

static u32 mdss_mdp_get_vbp_factor_max(struct mdss_mdp_ctl *ctl);

static inline u32 __mdss_mdp_get_wb_mixer(struct mdss_mdp_mixer *mixer)
{
	/* Return the dedicated WB mixer. */
	if (test_bit(MDSS_CAPS_MIXER_1_FOR_WB,
				mixer->ctl->mdata->mdss_caps_map))
		return MDSS_MDP_INTF_LAYERMIXER1;
	else
		return MDSS_MDP_INTF_LAYERMIXER3;
}

static void __mdss_mdp_reset_mixercfg(struct mdss_mdp_ctl *ctl)
{
	u32 off;
	int i, nmixers;
	struct mdss_data_type *mdata = mdss_mdp_get_mdata();

	if (!ctl || !mdata)
		return;

	nmixers = mdata->nmixers_intf + mdata->nmixers_wb;

	for (i = 0; i < nmixers; i++) {
		off = MDSS_MDP_REG_CTL_LAYER(i);
		mdss_mdp_ctl_write(ctl, off, 0);

		off += MDSS_MDP_REG_CTL_LAYER_EXTN(i);
		mdss_mdp_ctl_write(ctl, off, 0);
	}
}

static inline int __mdss_mdp_ctl_get_mixer_off(struct mdss_mdp_mixer *mixer)
{
	u32 wb_mixer_num = 0;

	if (mixer->type == MDSS_MDP_MIXER_TYPE_INTF) {
		if (mixer->num == MDSS_MDP_INTF_LAYERMIXER3)
			return MDSS_MDP_CTL_X_LAYER_5;
		else
			return MDSS_MDP_REG_CTL_LAYER(mixer->num);
	} else {
		wb_mixer_num = __mdss_mdp_get_wb_mixer(mixer);
		return MDSS_MDP_REG_CTL_LAYER(mixer->num + wb_mixer_num);
	}
}

static inline int __mdss_mdp_ctl_get_mixer_extn_off(
	struct mdss_mdp_mixer *mixer)
{
	u32 wb_mixer_num = 0;

	if (mixer->type == MDSS_MDP_MIXER_TYPE_INTF) {
		if (mixer->num == MDSS_MDP_INTF_LAYERMIXER3)
			return MDSS_MDP_REG_CTL_LAYER_EXTN(5);
		else
			return MDSS_MDP_REG_CTL_LAYER_EXTN(mixer->num);
	} else {
		wb_mixer_num = __mdss_mdp_get_wb_mixer(mixer);
		return MDSS_MDP_REG_CTL_LAYER_EXTN(wb_mixer_num);
	}
}

u32 mdss_mdp_get_mixercfg(struct mdss_mdp_mixer *mixer, bool extn)
{
	u32 mixer_off;

	if (!mixer || !mixer->ctl)
		return 0;

	if (extn)
		mixer_off = __mdss_mdp_ctl_get_mixer_extn_off(mixer);
	else
		mixer_off = __mdss_mdp_ctl_get_mixer_off(mixer);

	return mdss_mdp_ctl_read(mixer->ctl, mixer_off);
}

static inline u32 mdss_mdp_get_pclk_rate(struct mdss_mdp_ctl *ctl)
{
	struct mdss_panel_info *pinfo = &ctl->panel_data->panel_info;
@@ -4083,56 +4039,157 @@ void mdss_mdp_set_roi(struct mdss_mdp_ctl *ctl,
	}
}

u32 mdss_mdp_get_mixer_mask(u32 pipe_num, u32 stage)
static void __mdss_mdp_mixer_update_cfg_masks(u32 pnum, u32 stage,
		struct mdss_mdp_mixer_cfg *cfg)
{
	u32 mask = 0;
	u32 masks[NUM_MIXERCFG_REGS] = { 0 };
	int i;

	if ((pipe_num == MDSS_MDP_SSPP_VIG3 ||
			pipe_num == MDSS_MDP_SSPP_RGB3)) {
		/* Add 2 to account for Cursor & Border bits */
		mask = stage << ((3 * pipe_num) + 2);
	} else {
		mask = stage << (3 * pipe_num);
	}
	return mask;
	if (pnum >= MDSS_MDP_MAX_SSPP)
		return;

	masks[0] = mdss_mdp_hwio_mask(&mdp_pipe_hwio[pnum].base, stage);
	masks[1] = mdss_mdp_hwio_mask(&mdp_pipe_hwio[pnum].ext, stage);
	masks[2] = mdss_mdp_hwio_mask(&mdp_pipe_hwio[pnum].ext2, stage);

	for (i = 0; i < NUM_MIXERCFG_REGS; i++)
		cfg->config_masks[i] |= masks[i];

	pr_debug("pnum=%d stage=%d cfg=0x%08x ext=0x%08x\n",
			pnum, stage, masks[0], masks[1]);
}

u32 mdss_mdp_get_mixer_extn_mask(u32 pipe_num, u32 stage)
static void __mdss_mdp_mixer_get_offsets(u32 mixer_num,
		u32 *offsets, size_t count)
{
	u32 mask = 0;
	BUG_ON(count < NUM_MIXERCFG_REGS);

	offsets[0] = MDSS_MDP_REG_CTL_LAYER(mixer_num);
	offsets[1] = MDSS_MDP_REG_CTL_LAYER_EXTN(mixer_num);
	offsets[2] = MDSS_MDP_REG_CTL_LAYER_EXTN2(mixer_num);
}

static inline int __mdss_mdp_mixer_get_hw_num(struct mdss_mdp_mixer *mixer)
{
	/*
	 * The ctl layer extension bits are ordered
	 * VIG0-3, RGB0-3, DMA0-1
	 * mapping to hardware expectation of actual mixer programming to
	 * happen on following registers:
	 *  INTF: 0, 1, 2, 5
	 *  WB: 3, 4
	 * With some exceptions on certain revisions
	 */
	if (pipe_num < MDSS_MDP_SSPP_RGB0) {
		mask = BIT(pipe_num << 1);
	} else if (pipe_num >= MDSS_MDP_SSPP_RGB0 &&
			pipe_num < MDSS_MDP_SSPP_DMA0) {
		mask = BIT((pipe_num + 1) << 1);
	} else if (pipe_num >= MDSS_MDP_SSPP_DMA0 &&
			pipe_num < MDSS_MDP_SSPP_VIG3) {
		mask = BIT((pipe_num + 2) << 1);
	} else if (pipe_num >= MDSS_MDP_SSPP_CURSOR0 &&
			pipe_num <= MDSS_MDP_SSPP_CURSOR1) {
		mask = stage << (20 + (6 * (pipe_num - MDSS_MDP_SSPP_CURSOR0)));
	} else if (pipe_num == MDSS_MDP_SSPP_VIG3) {
		mask = BIT(6);
	} else if (pipe_num == MDSS_MDP_SSPP_RGB3) {
		mask = BIT(14);
	}

	return mask;
	if (mixer->type == MDSS_MDP_MIXER_TYPE_WRITEBACK) {
		u32 wb_offset;

		if (test_bit(MDSS_CAPS_MIXER_1_FOR_WB,
					mixer->ctl->mdata->mdss_caps_map))
			wb_offset = MDSS_MDP_INTF_LAYERMIXER1;
		else
			wb_offset = MDSS_MDP_INTF_LAYERMIXER3;

		return mixer->num + wb_offset;
	} else if (mixer->num == MDSS_MDP_INTF_LAYERMIXER3) {
		return 5;
	} else {
		return mixer->num;
	}
}

static inline void __mdss_mdp_mixer_write_layer(struct mdss_mdp_ctl *ctl,
		u32 mixer_num, u32 *values, size_t count)
{
	u32 off[NUM_MIXERCFG_REGS];
	int i;

	BUG_ON(!values || count < NUM_MIXERCFG_REGS);

	__mdss_mdp_mixer_get_offsets(mixer_num, off, ARRAY_SIZE(off));

	for (i = 0; i < count; i++)
		mdss_mdp_ctl_write(ctl, off[i], values[i]);
}

static void __mdss_mdp_mixer_write_cfg(struct mdss_mdp_mixer *mixer,
		struct mdss_mdp_mixer_cfg *cfg)
{
	u32 vals[NUM_MIXERCFG_REGS] = {0};
	int i, mixer_num;

	if (!mixer)
		return;

	mixer_num = __mdss_mdp_mixer_get_hw_num(mixer);

	if (cfg) {
		for (i = 0; i < NUM_MIXERCFG_REGS; i++)
			vals[i] = cfg->config_masks[i];

		if (cfg->border_enabled)
			vals[0] |= MDSS_MDP_LM_BORDER_COLOR;
		if (cfg->cursor_enabled)
			vals[0] |= MDSS_MDP_LM_CURSOR_OUT;
	}

	__mdss_mdp_mixer_write_layer(mixer->ctl, mixer_num,
			vals, ARRAY_SIZE(vals));

	pr_debug("mixer=%d cfg=0%08x cfg_extn=0x%08x\n",
		mixer->num, vals[0], vals[1]);
	MDSS_XLOG(mixer->num, vals[0], vals[1]);
}

static void __mdss_mdp_reset_mixercfg(struct mdss_mdp_ctl *ctl)
{
	u32 vals[NUM_MIXERCFG_REGS] = {0};
	int i, nmixers;

	if (!ctl)
		return;

	nmixers = MDSS_MDP_INTF_MAX_LAYERMIXER + MDSS_MDP_WB_MAX_LAYERMIXER;

	for (i = 0; i < nmixers; i++)
		__mdss_mdp_mixer_write_layer(ctl, i, vals, ARRAY_SIZE(vals));
}

bool mdss_mdp_mixer_reg_has_pipe(struct mdss_mdp_mixer *mixer,
		struct mdss_mdp_pipe *pipe)
{
	u32 offs[NUM_MIXERCFG_REGS];
	u32 cfgs[NUM_MIXERCFG_REGS];
	struct mdss_mdp_mixer_cfg mixercfg;
	int i, mixer_num;

	if (!mixer)
		return false;

	memset(&mixercfg, 0, sizeof(mixercfg));

	mixer_num = __mdss_mdp_mixer_get_hw_num(mixer);
	__mdss_mdp_mixer_get_offsets(mixer_num, offs, NUM_MIXERCFG_REGS);

	for (i = 0; i < NUM_MIXERCFG_REGS; i++)
		cfgs[i] = mdss_mdp_ctl_read(mixer->ctl, offs[i]);

	__mdss_mdp_mixer_update_cfg_masks(pipe->num, -1, &mixercfg);
	for (i = 0; i < NUM_MIXERCFG_REGS; i++) {
		if (cfgs[i] & mixercfg.config_masks[i]) {
			MDSS_XLOG(mixer->num, cfgs[0], cfgs[1]);
			return true;
		}
	}

	return false;
}

static void mdss_mdp_mixer_setup(struct mdss_mdp_ctl *master_ctl,
	int mixer_mux, bool lm_swap)
{
	int i;
	int i, mixer_num;
	int stage, screen_state, outsize;
	u32 off, blend_op, blend_stage;
	u32 mixercfg = 0, mixer_op_mode = 0, bg_alpha_enable = 0,
	    mixercfg_extn = 0;
	u32 mixer_op_mode = 0, bg_alpha_enable = 0;
	struct mdss_mdp_mixer_cfg mixercfg;
	u32 fg_alpha = 0, bg_alpha = 0;
	struct mdss_mdp_pipe *pipe;
	struct mdss_mdp_ctl *ctl, *ctl_hw;
@@ -4153,10 +4210,12 @@ static void mdss_mdp_mixer_setup(struct mdss_mdp_ctl *master_ctl,

	/* check if mixer setup for rotator is needed */
	if (mixer_hw->rotator_mode) {
		__mdss_mdp_reset_mixercfg(ctl_hw);
		__mdss_mdp_mixer_write_cfg(mixer_hw, NULL);
		return;
	}

	memset(&mixercfg, 0, sizeof(mixercfg));

	if (lm_swap) {
		if (mixer_mux == MDSS_MDP_MIXER_MUX_RIGHT)
			mixer = mdss_mdp_mixer_get(master_ctl,
@@ -4186,11 +4245,7 @@ static void mdss_mdp_mixer_setup(struct mdss_mdp_ctl *master_ctl,
		 * mode is MDP_DUAL_LM_SINGLE_DISPLAY but update is only on
		 * one side.
		 */
		off = __mdss_mdp_ctl_get_mixer_off(mixer_hw);
		mdss_mdp_ctl_write(ctl_hw, off, 0);
		/* Program ctl layer extension bits */
		off = __mdss_mdp_ctl_get_mixer_extn_off(mixer_hw);
		mdss_mdp_ctl_write(ctl_hw, off, 0);
		__mdss_mdp_mixer_write_cfg(mixer_hw, NULL);

		MDSS_XLOG(mixer->num, mixer_hw->num, XLOG_FUNC_EXIT);
		return;
@@ -4204,19 +4259,16 @@ static void mdss_mdp_mixer_setup(struct mdss_mdp_ctl *master_ctl,
	mdp_mixer_write(mixer_hw, MDSS_MDP_REG_LM_OUT_SIZE, outsize);

	if (screen_state == MDSS_SCREEN_FORCE_BLANK) {
		mixercfg = MDSS_MDP_LM_BORDER_COLOR;
		mixercfg.border_enabled = true;
		goto update_mixer;
	}

	pipe = mixer->stage_pipe[MDSS_MDP_STAGE_BASE * MAX_PIPES_PER_STAGE];
	if (pipe == NULL) {
		mixercfg = MDSS_MDP_LM_BORDER_COLOR;
		mixercfg.border_enabled = true;
	} else {
		if (pipe->type == MDSS_MDP_PIPE_TYPE_CURSOR)
			mixercfg_extn |= mdss_mdp_get_mixer_extn_mask(
						pipe->num, 1);
		else
			mixercfg  |= mdss_mdp_get_mixer_mask(pipe->num, 1);
		__mdss_mdp_mixer_update_cfg_masks(pipe->num,
				MDSS_MDP_STAGE_BASE, &mixercfg);

		if (pipe->src_fmt->alpha_enable)
			bg_alpha_enable = 1;
@@ -4317,12 +4369,7 @@ static void mdss_mdp_mixer_setup(struct mdss_mdp_ctl *master_ctl,
		if (!pipe->src_fmt->alpha_enable && bg_alpha_enable)
			mixer_op_mode = 0;

		if ((stage < MDSS_MDP_STAGE_6) &&
			(pipe->type != MDSS_MDP_PIPE_TYPE_CURSOR))
			mixercfg |= mdss_mdp_get_mixer_mask(pipe->num, stage);
		else
			mixercfg_extn |= mdss_mdp_get_mixer_extn_mask(
						pipe->num, stage);
		__mdss_mdp_mixer_update_cfg_masks(pipe->num, stage, &mixercfg);

		trace_mdp_sspp_change(pipe);

@@ -4337,20 +4384,11 @@ static void mdss_mdp_mixer_setup(struct mdss_mdp_ctl *master_ctl,
	}

	if (mixer->cursor_enabled)
		mixercfg |= MDSS_MDP_LM_CURSOR_OUT;
		mixercfg.cursor_enabled = true;

update_mixer:
	if (mixer_hw->num == MDSS_MDP_INTF_LAYERMIXER3) {
		ctl_hw->flush_bits |= BIT(20);
	} else if (mixer_hw->type == MDSS_MDP_MIXER_TYPE_WRITEBACK) {
		if (test_bit(MDSS_CAPS_MIXER_1_FOR_WB,
			 mdata->mdss_caps_map))
			ctl_hw->flush_bits |= BIT(7) << mixer_hw->num;
		else
			ctl_hw->flush_bits |= BIT(9) << mixer_hw->num;
	} else {
		ctl_hw->flush_bits |= BIT(6) << mixer_hw->num;
	}
	mixer_num = __mdss_mdp_mixer_get_hw_num(mixer_hw);
	ctl_hw->flush_bits |= BIT(mixer_num < 5 ? 6 + mixer_num : 20);

	/* Read GC enable/disable status on LM */
	mixer_op_mode |=
@@ -4366,18 +4404,14 @@ update_mixer:
	mdp_mixer_write(mixer_hw, MDSS_MDP_REG_LM_BORDER_COLOR_1,
		mdata->bcolor2 & 0xFFF);

	off = __mdss_mdp_ctl_get_mixer_off(mixer_hw);
	mdss_mdp_ctl_write(ctl_hw, off, mixercfg);
	/* Program ctl layer extension bits */
	off = __mdss_mdp_ctl_get_mixer_extn_off(mixer_hw);
	mdss_mdp_ctl_write(ctl_hw, off, mixercfg_extn);
	__mdss_mdp_mixer_write_cfg(mixer_hw, &mixercfg);

	pr_debug("mixer=%d hw=%d cfg=0%08x cfg_extn=0x%08x op_mode=0x%08x w=%d h=%d bc0=0x%x bc1=0x%x\n",
		mixer->num, mixer_hw->num, mixercfg, mixercfg_extn,
	pr_debug("mixer=%d hw=%d op_mode=0x%08x w=%d h=%d bc0=0x%x bc1=0x%x\n",
		mixer->num, mixer_hw->num,
		mixer_op_mode, mixer->roi.w, mixer->roi.h,
		(mdata->bcolor0 & 0xFFF) | ((mdata->bcolor1 & 0xFFF) << 16),
		mdata->bcolor2 & 0xFFF);
	MDSS_XLOG(mixer->num, mixer_hw->num, mixercfg, mixercfg_extn,
	MDSS_XLOG(mixer->num, mixer_hw->num,
		mixer_op_mode, mixer->roi.h, mixer->roi.w);
}

@@ -4571,19 +4605,10 @@ struct mdss_mdp_pipe *mdss_mdp_get_staged_pipe(struct mdss_mdp_ctl *ctl,

int mdss_mdp_get_pipe_flush_bits(struct mdss_mdp_pipe *pipe)
{
	u32 flush_bits;

	if (pipe->type == MDSS_MDP_PIPE_TYPE_DMA)
		flush_bits |= BIT(pipe->num) << 5;
	else if (pipe->num == MDSS_MDP_SSPP_VIG3 ||
			pipe->num == MDSS_MDP_SSPP_RGB3)
		flush_bits |= BIT(pipe->num) << 10;
	else if (pipe->type == MDSS_MDP_PIPE_TYPE_CURSOR)
		flush_bits |= BIT(22 + pipe->num - MDSS_MDP_SSPP_CURSOR0);
	else /* RGB/VIG 0-2 pipes */
		flush_bits |= BIT(pipe->num);
	if (WARN_ON(!pipe || pipe->num >= MDSS_MDP_MAX_SSPP))
		return 0;

	return flush_bits;
	return BIT(mdp_pipe_hwio[pipe->num].flush_bit);
}

int mdss_mdp_async_ctl_flush(struct msm_fb_data_type *mfd,
+33 −8

File changed.

Preview size limit exceeded, changes collapsed.

+12 −25

File changed.

Preview size limit exceeded, changes collapsed.