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

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

Merge "drm: msm: sde: last command support for reg dma"

parents 339b33cc db90fa1d
Loading
Loading
Loading
Loading
+4 −20
Original line number Diff line number Diff line
@@ -526,7 +526,7 @@ static void sde_cp_crtc_install_enum_property(struct drm_crtc *crtc,
}

static void sde_cp_crtc_setfeature(struct sde_cp_node *prop_node,
				   struct sde_crtc *sde_crtc, u32 last_feature)
				   struct sde_crtc *sde_crtc)
{
	struct sde_hw_cp_cfg hw_cfg;
	struct sde_hw_mixer *hw_lm;
@@ -541,16 +541,13 @@ static void sde_cp_crtc_setfeature(struct sde_cp_node *prop_node,
	hw_cfg.num_of_mixers = sde_crtc->num_mixers;
	hw_cfg.displayh = sde_crtc->base.mode.hdisplay;
	hw_cfg.displayv = sde_crtc->base.mode.vdisplay;
	hw_cfg.last_feature = 0;

	for (i = 0; i < num_mixers && !ret; i++) {
		hw_lm = sde_crtc->mixers[i].hw_lm;
		hw_dspp = sde_crtc->mixers[i].hw_dspp;
		hw_cfg.ctl = sde_crtc->mixers[i].hw_ctl;
		hw_cfg.mixer_info = hw_lm;
		if (i == num_mixers - 1)
			hw_cfg.last_feature = last_feature;
		else
			hw_cfg.last_feature = 0;
		switch (prop_node->feature) {
		case SDE_CP_CRTC_DSPP_VLUT:
			if (!hw_dspp || !hw_dspp->ops.setup_vlut) {
@@ -724,7 +721,6 @@ void sde_cp_crtc_apply_properties(struct drm_crtc *crtc)
	struct sde_hw_ctl *ctl;
	uint32_t flush_mask = 0;
	u32 num_mixers = 0, i = 0;
	u32 num_of_features;

	if (!crtc || !crtc->dev) {
		DRM_ERROR("invalid crtc %pK dev %pK\n", crtc,
@@ -757,15 +753,9 @@ void sde_cp_crtc_apply_properties(struct drm_crtc *crtc)
		set_dspp_flush = true;
	}

	num_of_features = 0;
	list_for_each_entry(prop_node, &sde_crtc->dirty_list, dirty_list)
		num_of_features++;

	list_for_each_entry_safe(prop_node, n, &sde_crtc->dirty_list,
				dirty_list) {
		num_of_features--;
		sde_cp_crtc_setfeature(prop_node, sde_crtc,
				(num_of_features == 0));
		sde_cp_crtc_setfeature(prop_node, sde_crtc);
		/* Set the flush flag to true */
		if (prop_node->is_dspp_feature)
			set_dspp_flush = true;
@@ -773,16 +763,10 @@ void sde_cp_crtc_apply_properties(struct drm_crtc *crtc)
			set_lm_flush = true;
	}

	num_of_features = 0;
	list_for_each_entry(prop_node, &sde_crtc->ad_dirty, dirty_list)
		num_of_features++;

	list_for_each_entry_safe(prop_node, n, &sde_crtc->ad_dirty,
				dirty_list) {
		num_of_features--;
		set_dspp_flush = true;
		sde_cp_crtc_setfeature(prop_node, sde_crtc,
				(num_of_features == 0));
		sde_cp_crtc_setfeature(prop_node, sde_crtc);
	}

	for (i = 0; i < num_mixers; i++) {
+1 −0
Original line number Diff line number Diff line
@@ -2459,6 +2459,7 @@ static void sde_crtc_handle_power_event(u32 event_type, void *arg)
			sde_plane_set_revalidate(plane, true);

		drm_modeset_unlock_crtc(crtc);
		sde_cp_crtc_suspend(crtc);
	}

	mutex_unlock(&sde_crtc->crtc_lock);
+6 −0
Original line number Diff line number Diff line
@@ -15,6 +15,7 @@
#include "sde_hw_ctl.h"
#include "sde_dbg.h"
#include "sde_kms.h"
#include "sde_reg_dma.h"

#define   CTL_LAYER(lm)                 \
	(((lm) == LM_5) ? (0x024) : (((lm) - LM_0) * 0x004))
@@ -111,6 +112,11 @@ static u32 sde_hw_ctl_get_pending_flush(struct sde_hw_ctl *ctx)

static inline void sde_hw_ctl_trigger_flush(struct sde_hw_ctl *ctx)
{
	struct sde_hw_reg_dma_ops *ops = sde_reg_dma_get_ops();

	if (ops && ops->last_command)
		ops->last_command(ctx, DMA_CTL_QUEUE0);

	SDE_REG_WRITE(&ctx->hw, CTL_FLUSH, ctx->pending_flush_mask);
}

+86 −0
Original line number Diff line number Diff line
@@ -49,6 +49,7 @@
			(cfg)->dma_buf->index)

#define REG_DMA_DECODE_SEL 0x180AC060
#define REG_DMA_LAST_CMD 0x180AC004
#define SINGLE_REG_WRITE_OPCODE (BIT(28))
#define REL_ADDR_OPCODE (BIT(27))
#define HW_INDEX_REG_WRITE_OPCODE (BIT(28) | BIT(29))
@@ -58,6 +59,7 @@
#define WRAP_MIN_SIZE 2
#define WRAP_MAX_SIZE (BIT(4) - 1)
#define MAX_DWORDS_SZ (BIT(14) - 1)
#define REG_DMA_HEADERS_BUFFER_SZ (sizeof(u32) * 128)

typedef int (*reg_dma_internal_ops) (struct sde_reg_dma_setup_ops_cfg *cfg);

@@ -93,17 +95,20 @@ static int validate_dma_cfg(struct sde_reg_dma_setup_ops_cfg *cfg);
static int validate_write_decode_sel(struct sde_reg_dma_setup_ops_cfg *cfg);
static int validate_write_reg(struct sde_reg_dma_setup_ops_cfg *cfg);
static int validate_write_multi_lut_reg(struct sde_reg_dma_setup_ops_cfg *cfg);
static int validate_last_cmd(struct sde_reg_dma_setup_ops_cfg *cfg);
static int write_decode_sel(struct sde_reg_dma_setup_ops_cfg *cfg);
static int write_single_reg(struct sde_reg_dma_setup_ops_cfg *cfg);
static int write_multi_reg_index(struct sde_reg_dma_setup_ops_cfg *cfg);
static int write_multi_reg_inc(struct sde_reg_dma_setup_ops_cfg *cfg);
static int write_multi_lut_reg(struct sde_reg_dma_setup_ops_cfg *cfg);
static int write_last_cmd(struct sde_reg_dma_setup_ops_cfg *cfg);
static int reset_reg_dma_buffer_v1(struct sde_reg_dma_buffer *lut_buf);
static int check_support_v1(enum sde_reg_dma_features feature,
		enum sde_reg_dma_blk blk, bool *is_supported);
static int setup_payload_v1(struct sde_reg_dma_setup_ops_cfg *cfg);
static int kick_off_v1(struct sde_reg_dma_kickoff_cfg *cfg);
static int reset_v1(struct sde_hw_ctl *ctl);
static int last_cmd_v1(struct sde_hw_ctl *ctl, enum sde_reg_dma_queue q);
static struct sde_reg_dma_buffer *alloc_reg_dma_buf_v1(u32 size);
static int dealloc_reg_dma_v1(struct sde_reg_dma_buffer *lut_buf);

@@ -123,6 +128,8 @@ static reg_dma_internal_ops validate_dma_op_params[REG_DMA_SETUP_OPS_MAX] = {
	[REG_BLK_WRITE_MULTIPLE] = validate_write_multi_lut_reg,
};

static struct sde_reg_dma_buffer *last_cmd_buf;

static void get_decode_sel(unsigned long blk, u32 *decode_sel)
{
	int i = 0;
@@ -474,6 +481,11 @@ int init_v1(struct sde_hw_reg_dma *cfg)
		return -EINVAL;

	reg_dma = cfg;
	if (!last_cmd_buf) {
		last_cmd_buf = alloc_reg_dma_buf_v1(REG_DMA_HEADERS_BUFFER_SZ);
		if (IS_ERR_OR_NULL(last_cmd_buf))
			return -EINVAL;
	}
	reg_dma->ops.check_support = check_support_v1;
	reg_dma->ops.setup_payload = setup_payload_v1;
	reg_dma->ops.kick_off = kick_off_v1;
@@ -481,6 +493,7 @@ int init_v1(struct sde_hw_reg_dma *cfg)
	reg_dma->ops.alloc_reg_dma_buf = alloc_reg_dma_buf_v1;
	reg_dma->ops.dealloc_reg_dma = dealloc_reg_dma_v1;
	reg_dma->ops.reset_reg_dma_buf = reset_reg_dma_buffer_v1;
	reg_dma->ops.last_command = last_cmd_v1;

	reg_dma_ctl_queue_off[CTL_0] = REG_DMA_CTL0_QUEUE_0_CMD0_OFF;
	for (i = CTL_1; i < ARRAY_SIZE(reg_dma_ctl_queue_off); i++)
@@ -648,3 +661,76 @@ static int reset_reg_dma_buffer_v1(struct sde_reg_dma_buffer *lut_buf)
	lut_buf->next_op_allowed = DECODE_SEL_OP;
	return 0;
}

static int validate_last_cmd(struct sde_reg_dma_setup_ops_cfg *cfg)
{
	u32 remain_len, write_len;

	remain_len = BUFFER_SPACE_LEFT(cfg);
	write_len = sizeof(u32);
	if (remain_len < write_len) {
		DRM_ERROR("buffer is full sz %d needs %d bytes\n",
				remain_len, write_len);
		return -EINVAL;
	}
	return 0;
}

static int write_last_cmd(struct sde_reg_dma_setup_ops_cfg *cfg)
{
	u32 *loc = NULL;

	loc =  (u32 *)((u8 *)cfg->dma_buf->vaddr +
			cfg->dma_buf->index);
	loc[0] = REG_DMA_LAST_CMD;
	loc[1] = BIT(0);
	cfg->dma_buf->index = sizeof(u32) * 2;
	cfg->dma_buf->ops_completed = REG_WRITE_OP | DECODE_SEL_OP;
	cfg->dma_buf->next_op_allowed = REG_WRITE_OP;

	return 0;
}

static int last_cmd_v1(struct sde_hw_ctl *ctl, enum sde_reg_dma_queue q)
{
	struct sde_reg_dma_setup_ops_cfg cfg;
	struct sde_reg_dma_kickoff_cfg kick_off;

	if (!last_cmd_buf || !ctl || q >= DMA_CTL_QUEUE_MAX) {
		DRM_ERROR("invalid param buf %pK ctl %pK q %d\n", last_cmd_buf,
				ctl, q);
		return -EINVAL;
	}

	cfg.dma_buf = last_cmd_buf;
	reset_reg_dma_buffer_v1(last_cmd_buf);
	if (validate_last_cmd(&cfg)) {
		DRM_ERROR("validate buf failed\n");
		return -EINVAL;
	}

	if (write_last_cmd(&cfg)) {
		DRM_ERROR("write buf failed\n");
		return -EINVAL;
	}

	kick_off.ctl = ctl;
	kick_off.queue_select = q;
	kick_off.trigger_mode = WRITE_IMMEDIATE;
	kick_off.last_command = 1;
	kick_off.op = REG_DMA_WRITE;
	kick_off.dma_buf = last_cmd_buf;
	if (kick_off_v1(&kick_off)) {
		DRM_ERROR("kick off last cmd failed\n");
		return -EINVAL;
	}

	return 0;
}

void deinit_v1(void)
{
	if (last_cmd_buf)
		dealloc_reg_dma_v1(last_cmd_buf);
	last_cmd_buf = NULL;
}
+4 −0
Original line number Diff line number Diff line
@@ -20,4 +20,8 @@
 */
int init_v1(struct sde_hw_reg_dma *reg_dma);

/**
 * deinit_v1() - free up any resources allocated during the v1 reg dma init
 */
void deinit_v1(void);
#endif /* _SDE_HW_REG_DMA_V1_H */
Loading