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

Commit 9945a157 authored by Jayant Shekhar's avatar Jayant Shekhar Committed by Gerrit - the friendly Code Review server
Browse files

msm: mdss: Add atomic commit support for MDP3 driver



Atomic commit IOCTL adds validate and commit layer support
for framebuffer driver clients. Clients sends the validate
request with layer list for each display to put layers in
validate list. Once layers are validated; clients sends the
commit request for all validated layers. Validate request
may fail while commit must not fail because clients have
no fall back mechanism for commit failure.

If clients calls the atomic commit without validate request
then commit will validate all the layers before kickoff. In
such situation; commit may fail due to validate failure.

Change-Id: If5b6e3afcded909b6a3096edddec85148634274b
Signed-off-by: default avatarJayant Shekhar <jshekhar@codeaurora.org>
parent 19a63f49
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -2,7 +2,7 @@ ccflags-y += -I$(src)

obj-$(CONFIG_FB_MSM_MDSS_MHL3) += mhl3/

mdss-mdp3-objs = mdp3.o mdp3_dma.o mdp3_ctrl.o dsi_status_v2.o
mdss-mdp3-objs = mdp3.o mdp3_layer.o mdp3_dma.o mdp3_ctrl.o dsi_status_v2.o
mdss-mdp3-objs += mdp3_ppp.o mdp3_ppp_hwio.o mdp3_ppp_data.o
obj-$(CONFIG_FB_MSM_MDSS_MDP3) += mdss-mdp3.o
ifeq ($(CONFIG_FB_MSM_MDSS_MDP3), y)
+95 −1
Original line number Diff line number Diff line
@@ -78,6 +78,13 @@ struct mdp3_hw_resource *mdp3_res;
		.ib = (ib_val),				\
	}

#define SET_BIT(value, bit_num) \
{ \
	value[bit_num >> 3] |= (1 << (bit_num & 7)); \
}

#define MAX_BPP_SUPPORTED 4

static struct msm_bus_vectors mdp_bus_vectors[] = {
	MDP_BUS_VECTOR_ENTRY(0, 0),
	MDP_BUS_VECTOR_ENTRY(SZ_128M, SZ_256M),
@@ -2271,6 +2278,14 @@ splash_on_err:
static int mdp3_panel_register_done(struct mdss_panel_data *pdata)
{
	int rc = 0;
	u64 ab = 0; u64 ib = 0;
	u64 mdp_clk_rate = 0;

	/* Store max bandwidth supported in mdp res */
	mdp3_calc_dma_res(&pdata->panel_info, &mdp_clk_rate, &ab, &ib,
			MAX_BPP_SUPPORTED);
	do_div(ab, 1024);
	mdp3_res->max_bw = ab+1;

	/*
	* If idle pc feature is not enabled, then get a reference to the
@@ -2428,6 +2443,61 @@ static void mdp3_dma_underrun_intr_handler(int type, void *arg)
	}
}

uint32_t ppp_formats_supported[] = {
	MDP_RGB_565,
	MDP_BGR_565,
	MDP_RGB_888,
	MDP_BGR_888,
	MDP_XRGB_8888,
	MDP_ARGB_8888,
	MDP_RGBA_8888,
	MDP_BGRA_8888,
	MDP_RGBX_8888,
	MDP_Y_CBCR_H2V1,
	MDP_Y_CBCR_H2V2,
	MDP_Y_CBCR_H2V2_ADRENO,
	MDP_Y_CBCR_H2V2_VENUS,
	MDP_Y_CRCB_H2V1,
	MDP_Y_CRCB_H2V2,
	MDP_YCRYCB_H2V1,
	MDP_BGRX_8888,
};

uint32_t dma_formats_supported[] = {
	MDP_RGB_565,
	MDP_RGB_888,
	MDP_XRGB_8888,
};

static void __mdp3_set_supported_formats(void)
{
	int i;

	for (i = 0; i < ARRAY_SIZE(ppp_formats_supported); i++)
		SET_BIT(mdp3_res->ppp_formats, ppp_formats_supported[i]);

	for (i = 0; i < ARRAY_SIZE(dma_formats_supported); i++)
		SET_BIT(mdp3_res->dma_formats, dma_formats_supported[i]);
}

static void __update_format_supported_info(char *buf, int *cnt)
{
	int j;
	size_t len = PAGE_SIZE;
	int num_bytes = BITS_TO_BYTES(MDP_IMGTYPE_LIMIT1);
#define SPRINT(fmt, ...) \
	(*cnt += scnprintf(buf + *cnt, len - *cnt, fmt, ##__VA_ARGS__))

	SPRINT("ppp_input_fmts=");
	for (j = 0; j < num_bytes; j++)
		SPRINT("%d,", mdp3_res->ppp_formats[j]);
	SPRINT("\ndma_output_fmts=");
	for (j = 0; j < num_bytes; j++)
		SPRINT("%d,", mdp3_res->dma_formats[j]);
	SPRINT("\n");
#undef SPRINT
}

static ssize_t mdp3_show_capabilities(struct device *dev,
		struct device_attribute *attr, char *buf)
{
@@ -2437,10 +2507,32 @@ static ssize_t mdp3_show_capabilities(struct device *dev,
#define SPRINT(fmt, ...) \
		(cnt += scnprintf(buf + cnt, len - cnt, fmt, ##__VA_ARGS__))

	SPRINT("dma_pipes=%d\n", 1);
	SPRINT("mdp_version=3\n");
	SPRINT("hw_rev=%d\n", 305);
	SPRINT("pipe_count:%d\n", 1);
	SPRINT("pipe_num:%d pipe_type:dma pipe_ndx:%d rects:%d ", 0, 1, 1);
	SPRINT("pipe_is_handoff:%d display_id:%d\n", 0, 0);
	__update_format_supported_info(buf, &cnt);
	SPRINT("rgb_pipes=%d\n", 0);
	SPRINT("vig_pipes=%d\n", 0);
	SPRINT("dma_pipes=%d\n", 1);
	SPRINT("\n");
	SPRINT("blending_stages=%d\n", 1);
	SPRINT("cursor_pipes=%d\n", 0);
	SPRINT("max_cursor_size=%d\n", 0);
	SPRINT("smp_count=%d\n", 0);
	SPRINT("smp_size=%d\n", 0);
	SPRINT("smp_mb_per_pipe=%d\n", 0);
	SPRINT("max_downscale_ratio=%d\n", PPP_DOWNSCALE_MAX);
	SPRINT("max_upscale_ratio=%d\n", PPP_UPSCALE_MAX);
	SPRINT("max_pipe_bw=%u\n", mdp3_res->max_bw);
	SPRINT("max_bandwidth_low=%u\n", mdp3_res->max_bw);
	SPRINT("max_bandwidth_high=%u\n", mdp3_res->max_bw);
	SPRINT("max_mdp_clk=%u\n", MDP_CORE_CLK_RATE_MAX);
	SPRINT("clk_fudge_factor=%u,%u\n", CLK_FUDGE_NUM, CLK_FUDGE_DEN);
	SPRINT("features=has_ppp\n");

#undef SPRINT

	return cnt;
}
@@ -2812,6 +2904,8 @@ static int mdp3_probe(struct platform_device *pdev)
	if (rc)
		pr_err("mdss smmu init failed\n");

	__mdp3_set_supported_formats();

	mdp3_res->mdss_util->mdp_probe_done = true;
	pr_debug("%s: END\n", __func__);

+16 −0
Original line number Diff line number Diff line
@@ -31,6 +31,9 @@
#define MDP_CORE_CLK_RATE_SUPER_SVS	200000000
#define MDP_CORE_CLK_RATE_MAX	307200000

#define CLK_FUDGE_NUM		12
#define CLK_FUDGE_DEN		10

/* PPP cant work at SVS for panel res above qHD */
#define SVS_MAX_PIXEL		(540 * 960)

@@ -44,6 +47,9 @@
 */
#define MDP_SMART_BLIT                 0xC0000000

#define BITS_PER_BYTE 8
#define MDP_IMGTYPE_LIMIT1 0x100
#define BITS_TO_BYTES(x) DIV_ROUND_UP(x, BITS_PER_BYTE)

enum  {
	MDP3_CLK_AHB,
@@ -204,6 +210,11 @@ struct mdp3_hw_resource {
	bool solid_fill_vote_en;
	struct list_head reg_bus_clist;
	struct mutex reg_bus_lock;

	u32 max_bw;

	u8 ppp_formats[BITS_TO_BYTES(MDP_IMGTYPE_LIMIT1)];
	u8 dma_formats[BITS_TO_BYTES(MDP_IMGTYPE_LIMIT1)];
};

struct mdp3_img_data {
@@ -269,6 +280,11 @@ void mdp3_calc_dma_res(struct mdss_panel_info *panel_info, u64 *clk_rate,
void mdp3_clear_irq(u32 interrupt_mask);
int mdp3_enable_panic_ctrl(void);

int mdp3_layer_pre_commit(struct msm_fb_data_type *mfd,
	struct file *file, struct mdp_layer_commit_v1 *commit);
int mdp3_layer_atomic_validate(struct msm_fb_data_type *mfd,
	struct file *file, struct mdp_layer_commit_v1 *commit);

#define MDP3_REG_WRITE(addr, val) writel_relaxed(val, mdp3_res->mdp_base + addr)
#define MDP3_REG_READ(addr) readl_relaxed(mdp3_res->mdp_base + addr)
#define VBIF_REG_WRITE(off, val) writel_relaxed(val, mdp3_res->vbif_base + off)
+83 −7
Original line number Diff line number Diff line
@@ -22,6 +22,7 @@
#include <linux/delay.h>
#include <linux/dma-buf.h>
#include <linux/pm_runtime.h>
#include <linux/sw_sync.h>

#include "mdp3_ctrl.h"
#include "mdp3.h"
@@ -42,8 +43,6 @@ static int mdp3_ctrl_lut_read(struct msm_fb_data_type *mfd,
static int mdp3_ctrl_lut_config(struct msm_fb_data_type *mfd,
				struct mdp_rgb_lut_data *cfg);
static void mdp3_ctrl_pp_resume(struct msm_fb_data_type *mfd);
static int mdp3_ctrl_reset(struct msm_fb_data_type *mfd);
static int mdp3_ctrl_get_pack_pattern(u32 imgType);

u32 mdp_lut_inverse16[MDP_LUT_SIZE] = {
0, 65536, 32768, 21845, 16384, 13107, 10923, 9362, 8192, 7282, 6554, 5958,
@@ -72,7 +71,7 @@ static void mdp3_bufq_init(struct mdp3_buffer_queue *bufq)
	bufq->pop_idx = 0;
}

static void mdp3_bufq_deinit(struct mdp3_buffer_queue *bufq)
void mdp3_bufq_deinit(struct mdp3_buffer_queue *bufq)
{
	int count = bufq->count;

@@ -89,7 +88,7 @@ static void mdp3_bufq_deinit(struct mdp3_buffer_queue *bufq)
	bufq->pop_idx = 0;
}

static int mdp3_bufq_push(struct mdp3_buffer_queue *bufq,
int mdp3_bufq_push(struct mdp3_buffer_queue *bufq,
			struct mdp3_img_data *data)
{
	if (bufq->count >= MDP3_MAX_BUF_QUEUE) {
@@ -206,6 +205,45 @@ retry_dma_done:
	mutex_unlock(&session->lock);
}

static void mdp3_vsync_retire_handle_vsync(void *arg)
{
	struct mdp3_session_data *mdp3_session;

	mdp3_session = (struct mdp3_session_data *)arg;

	if (!mdp3_session) {
		pr_warn("Invalid handle for vsync\n");
		return;
	}

	schedule_work(&mdp3_session->retire_work);
}

static void mdp3_vsync_retire_signal(struct msm_fb_data_type *mfd, int val)
{
	struct mdp3_session_data *mdp3_session;

	mdp3_session = (struct mdp3_session_data *)mfd->mdp.private1;

	mutex_lock(&mfd->mdp_sync_pt_data.sync_mutex);
	if (mdp3_session->retire_cnt > 0) {
		sw_sync_timeline_inc(mdp3_session->vsync_timeline, val);
		mdp3_session->retire_cnt -= min(val, mdp3_session->retire_cnt);
	}
	mutex_unlock(&mfd->mdp_sync_pt_data.sync_mutex);
}

static void mdp3_vsync_retire_work_handler(struct work_struct *work)
{
	struct mdp3_session_data *mdp3_session =
		container_of(work, struct mdp3_session_data, retire_work);

	if (!mdp3_session)
		return;

	mdp3_vsync_retire_signal(mdp3_session->mfd, 1);
}

void vsync_notify_handler(void *arg)
{
	struct mdp3_session_data *session = (struct mdp3_session_data *)arg;
@@ -553,7 +591,7 @@ static int mdp3_ctrl_get_intf_type(struct msm_fb_data_type *mfd)
	return type;
}

static int mdp3_ctrl_get_source_format(u32 imgType)
int mdp3_ctrl_get_source_format(u32 imgType)
{
	int format;
	switch (imgType) {
@@ -573,7 +611,7 @@ static int mdp3_ctrl_get_source_format(u32 imgType)
	return format;
}

static int mdp3_ctrl_get_pack_pattern(u32 imgType)
int mdp3_ctrl_get_pack_pattern(u32 imgType)
{
	int packPattern = MDP3_DMA_OUTPUT_PACK_PATTERN_RGB;
	if (imgType == MDP_RGBA_8888 || imgType == MDP_RGB_888)
@@ -1052,7 +1090,7 @@ off_error:
	return 0;
}

static int mdp3_ctrl_reset(struct msm_fb_data_type *mfd)
int mdp3_ctrl_reset(struct msm_fb_data_type *mfd)
{
	int rc = 0;
	struct mdp3_session_data *mdp3_session;
@@ -2684,6 +2722,33 @@ static int mdp3_update_panel_info(struct msm_fb_data_type *mfd, int mode,
	return 0;
}

static int mdp3_vsync_retire_setup(struct msm_fb_data_type *mfd)
{
	struct mdp3_session_data *mdp3_session;
	struct mdp3_notification retire_client;
	char name[24];

	mdp3_session = (struct mdp3_session_data *)mfd->mdp.private1;

	snprintf(name, sizeof(name), "mdss_fb%d_retire", mfd->index);
	mdp3_session->vsync_timeline = sw_sync_timeline_create(name);
	if (mdp3_session->vsync_timeline == NULL) {
		pr_err("cannot vsync create time line");
		return -ENOMEM;
	}

	/* Add retire vsync handler */
	retire_client.handler = mdp3_vsync_retire_handle_vsync;
	retire_client.arg = mdp3_session;

	if (mdp3_session->dma)
		mdp3_session->dma->retire_client = retire_client;

	INIT_WORK(&mdp3_session->retire_work, mdp3_vsync_retire_work_handler);

	return 0;
}

int mdp3_ctrl_init(struct msm_fb_data_type *mfd)
{
	struct device *dev = mfd->fbi->dev;
@@ -2705,6 +2770,8 @@ int mdp3_ctrl_init(struct msm_fb_data_type *mfd)
	mdp3_interface->dma_fnc = mdp3_ctrl_pan_display;
	mdp3_interface->ioctl_handler = mdp3_ctrl_ioctl_handler;
	mdp3_interface->kickoff_fnc = mdp3_ctrl_display_commit_kickoff;
	mdp3_interface->pre_commit = mdp3_layer_pre_commit;
	mdp3_interface->atomic_validate = mdp3_layer_atomic_validate;
	mdp3_interface->lut_update = NULL;
	mdp3_interface->configure_panel = mdp3_update_panel_info;

@@ -2812,6 +2879,15 @@ int mdp3_ctrl_init(struct msm_fb_data_type *mfd)

	mdp3_session->vsync_before_commit = true;
	mdp3_session->dyn_pu_state = mfd->panel_info->partial_update_enabled;

	if (mfd->panel_info->mipi.dms_mode ||
			mfd->panel_info->type == MIPI_CMD_PANEL) {
		rc = mdp3_vsync_retire_setup(mfd);
		if (IS_ERR_VALUE(rc)) {
			pr_err("unable to create vsync timeline\n");
			goto init_done;
		}
	}
init_done:
	if (IS_ERR_VALUE(rc))
		kfree(mdp3_session);
+11 −0
Original line number Diff line number Diff line
@@ -70,8 +70,19 @@ struct mdp3_session_data {
	bool dma_active;
	struct completion dma_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;
};

void mdp3_bufq_deinit(struct mdp3_buffer_queue *bufq);
int mdp3_ctrl_init(struct msm_fb_data_type *mfd);
int mdp3_bufq_push(struct mdp3_buffer_queue *bufq,
			struct mdp3_img_data *data);
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);

#endif /* MDP3_CTRL_H */
Loading