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

Commit 4bdd02c8 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: Add SDM855 support in REG DMA framework"

parents 44a15edd e14fe3a2
Loading
Loading
Loading
Loading
+110 −30
Original line number Diff line number Diff line
@@ -24,17 +24,12 @@

#define DECODE_SEL_OP (BIT(HW_BLK_SELECT))
#define REG_WRITE_OP ((BIT(REG_SINGLE_WRITE)) | (BIT(REG_BLK_WRITE_SINGLE)) | \
	(BIT(REG_BLK_WRITE_INC)) | (BIT(REG_BLK_WRITE_MULTIPLE)))
	(BIT(REG_BLK_WRITE_INC)) | (BIT(REG_BLK_WRITE_MULTIPLE)) | \
	(BIT(REG_SINGLE_MODIFY)))

#define REG_DMA_OPS (DECODE_SEL_OP | REG_WRITE_OP)
#define IS_OP_ALLOWED(op, buf_op) (BIT(op) & buf_op)

#define REG_DMA_OP_MODE_OFF 0x4

#define REG_DMA_CTL0_QUEUE_0_CMD0_OFF 0x14
#define REG_DMA_CTL0_RESET_OFF 0xE4
#define REG_DMA_CTL_TRIGGER_OFF 0xD4

#define SET_UP_REG_DMA_REG(hw, reg_dma) \
	do { \
		(hw).base_off = (reg_dma)->addr; \
@@ -47,13 +42,14 @@


#define GRP_VIG_HW_BLK_SELECT (VIG0 | VIG1 | VIG2 | VIG3)
#define GRP_DMA_HW_BLK_SELECT (DMA0 | DMA1 | DMA2 | DMA3)
#define GRP_DSPP_HW_BLK_SELECT (DSPP0 | DSPP1 | DSPP2 | DSPP3)
#define BUFFER_SPACE_LEFT(cfg) ((cfg)->dma_buf->buffer_size - \
			(cfg)->dma_buf->index)

#define REG_DMA_DECODE_SEL 0x180AC060
#define SINGLE_REG_WRITE_OPCODE (BIT(28))
#define REL_ADDR_OPCODE (BIT(27))
#define SINGLE_REG_WRITE_OPCODE (BIT(28))
#define SINGLE_REG_MODIFY_OPCODE (BIT(29))
#define HW_INDEX_REG_WRITE_OPCODE (BIT(28) | BIT(29))
#define AUTO_INC_REG_WRITE_OPCODE (BIT(30))
#define BLK_REG_WRITE_OPCODE (BIT(30) | BIT(28))
@@ -64,9 +60,14 @@
#define REG_DMA_HEADERS_BUFFER_SZ (sizeof(u32) * 128)

static uint32_t reg_dma_register_count;
static uint32_t reg_dma_decode_sel;
static uint32_t reg_dma_opmode_offset;
static uint32_t reg_dma_ctl0_queue0_cmd0_offset;
static uint32_t reg_dma_intr_status_offset;
static uint32_t reg_dma_intr_4_status_offset;
static uint32_t reg_dma_intr_clear_offset;
static uint32_t reg_dma_ctl_trigger_offset;
static uint32_t reg_dma_ctl0_reset_offset;

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

@@ -76,7 +77,8 @@ static u32 ops_mem_size[REG_DMA_SETUP_OPS_MAX] = {
	[REG_BLK_WRITE_INC] = sizeof(u32) * 2,
	[REG_BLK_WRITE_MULTIPLE] = sizeof(u32) * 2,
	[HW_BLK_SELECT] = sizeof(u32) * 2,
	[REG_SINGLE_WRITE] = sizeof(u32) * 2
	[REG_SINGLE_WRITE] = sizeof(u32) * 2,
	[REG_SINGLE_MODIFY] = sizeof(u32) * 3,
};

static u32 queue_sel[DMA_CTL_QUEUE_MAX] = {
@@ -109,6 +111,10 @@ static u32 ctl_trigger_done_mask[CTL_MAX][DMA_CTL_QUEUE_MAX] = {
	[CTL_2][1] = BIT(23),
	[CTL_3][0] = BIT(19),
	[CTL_3][1] = BIT(24),
	[CTL_4][0] = BIT(25),
	[CTL_4][1] = BIT(27),
	[CTL_5][0] = BIT(26),
	[CTL_5][1] = BIT(28),
};

static int validate_dma_cfg(struct sde_reg_dma_setup_ops_cfg *cfg);
@@ -121,6 +127,7 @@ 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_single_modify(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,
@@ -140,6 +147,7 @@ static reg_dma_internal_ops write_dma_op_params[REG_DMA_SETUP_OPS_MAX] = {
	[REG_BLK_WRITE_SINGLE] = write_multi_reg_inc,
	[REG_BLK_WRITE_INC] = write_multi_reg_index,
	[REG_BLK_WRITE_MULTIPLE] = write_multi_lut_reg,
	[REG_SINGLE_MODIFY] = write_single_modify,
};

static reg_dma_internal_ops validate_dma_op_params[REG_DMA_SETUP_OPS_MAX] = {
@@ -148,6 +156,7 @@ static reg_dma_internal_ops validate_dma_op_params[REG_DMA_SETUP_OPS_MAX] = {
	[REG_BLK_WRITE_SINGLE] = validate_write_reg,
	[REG_BLK_WRITE_INC] = validate_write_reg,
	[REG_BLK_WRITE_MULTIPLE] = validate_write_multi_lut_reg,
	[REG_SINGLE_MODIFY] = validate_write_reg,
};

static struct sde_reg_dma_buffer *last_cmd_buf[CTL_MAX];
@@ -171,6 +180,18 @@ static void get_decode_sel(unsigned long blk, u32 *decode_sel)
		case VIG3:
			*decode_sel |= BIT(3);
			break;
		case DMA0:
			*decode_sel |= BIT(5);
			break;
		case DMA1:
			*decode_sel |= BIT(6);
			break;
		case DMA2:
			*decode_sel |= BIT(7);
			break;
		case DMA3:
			*decode_sel |= BIT(8);
			break;
		case DSPP0:
			*decode_sel |= BIT(17);
			break;
@@ -270,15 +291,32 @@ static int write_single_reg(struct sde_reg_dma_setup_ops_cfg *cfg)
	return 0;
}

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

	loc =  (u32 *)((u8 *)cfg->dma_buf->vaddr +
			cfg->dma_buf->index);
	loc[0] = SINGLE_REG_MODIFY_OPCODE;
	loc[0] |= (cfg->blk_offset & MAX_RELATIVE_OFF);
	loc[1] = cfg->mask;
	loc[2] = *cfg->data;
	cfg->dma_buf->index += ops_mem_size[cfg->ops];
	cfg->dma_buf->ops_completed |= REG_WRITE_OP;
	cfg->dma_buf->next_op_allowed = REG_WRITE_OP | DECODE_SEL_OP;

	return 0;
}

static int write_decode_sel(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_DECODE_SEL;
	loc[0] = reg_dma_decode_sel;
	get_decode_sel(cfg->blk, &loc[1]);
	cfg->dma_buf->index += sizeof(u32) * 2;
	cfg->dma_buf->index += ops_mem_size[cfg->ops];
	cfg->dma_buf->ops_completed |= DECODE_SEL_OP;
	cfg->dma_buf->next_op_allowed = REG_WRITE_OP;

@@ -353,9 +391,13 @@ static int validate_write_decode_sel(struct sde_reg_dma_setup_ops_cfg *cfg)
		DRM_ERROR("blk set as 0\n");
		return -EINVAL;
	}
	/* DSPP and VIG can't be combined */
	if ((cfg->blk & GRP_VIG_HW_BLK_SELECT) &&
		(cfg->blk & GRP_DSPP_HW_BLK_SELECT)) {
	/* VIG, DMA and DSPP can't be combined */
	if (((cfg->blk & GRP_VIG_HW_BLK_SELECT) &&
		(cfg->blk & GRP_DSPP_HW_BLK_SELECT)) ||
		((cfg->blk & GRP_DMA_HW_BLK_SELECT) &&
		(cfg->blk & GRP_DSPP_HW_BLK_SELECT)) ||
		((cfg->blk & GRP_VIG_HW_BLK_SELECT) &&
		(cfg->blk & GRP_DMA_HW_BLK_SELECT))) {
		DRM_ERROR("invalid blk combination %x\n",
			    cfg->blk);
		return -EINVAL;
@@ -485,7 +527,7 @@ static int write_kick_off_v1(struct sde_reg_dma_kickoff_cfg *cfg)
	cmd1 |= (SIZE_DWORD(cfg->dma_buf->index) & MAX_DWORDS_SZ);

	SET_UP_REG_DMA_REG(hw, reg_dma);
	SDE_REG_WRITE(&hw, REG_DMA_OP_MODE_OFF, BIT(0));
	SDE_REG_WRITE(&hw, reg_dma_opmode_offset, BIT(0));
	val = SDE_REG_READ(&hw, reg_dma_intr_4_status_offset);
	if (val)
		SDE_DBG_DUMP("all", "dbg_bus", "vbif_dbg_bus", "panic");
@@ -497,7 +539,7 @@ static int write_kick_off_v1(struct sde_reg_dma_kickoff_cfg *cfg)
	if (cfg->last_command) {
		mask = ctl_trigger_done_mask[cfg->ctl->idx][cfg->queue_select];
		SDE_REG_WRITE(&hw, reg_dma_intr_clear_offset, mask);
		SDE_REG_WRITE(&cfg->ctl->hw, REG_DMA_CTL_TRIGGER_OFF,
		SDE_REG_WRITE(&cfg->ctl->hw, reg_dma_ctl_trigger_offset,
			queue_sel[cfg->queue_select]);
	}

@@ -547,15 +589,53 @@ int init_v1(struct sde_hw_reg_dma *cfg)
	reg_dma->ops.last_command = last_cmd_v1;
	reg_dma->ops.dump_regs = dump_regs_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++)
		reg_dma_ctl_queue_off[i] = reg_dma_ctl_queue_off[i - 1] +
			(sizeof(u32) * 4);

	reg_dma_register_count = 60;
	reg_dma_decode_sel = 0x180ac060;
	reg_dma_opmode_offset = 0x4;
	reg_dma_ctl0_queue0_cmd0_offset = 0x14;
	reg_dma_intr_status_offset = 0x90;
	reg_dma_intr_4_status_offset = 0xa0;
	reg_dma_intr_clear_offset = 0xb0;
	reg_dma_ctl_trigger_offset = 0xd4;
	reg_dma_ctl0_reset_offset = 0xe4;

	reg_dma_ctl_queue_off[CTL_0] = reg_dma_ctl0_queue0_cmd0_offset;
	for (i = CTL_1; i < ARRAY_SIZE(reg_dma_ctl_queue_off); i++)
		reg_dma_ctl_queue_off[i] = reg_dma_ctl_queue_off[i - 1] +
			(sizeof(u32) * 4);

	return 0;
}

int init_v11(struct sde_hw_reg_dma *cfg)
{
	int ret = 0, i = 0;

	ret = init_v1(cfg);
	if (ret) {
		DRM_ERROR("failed to initialize v1: ret %d\n", ret);
		return -EINVAL;
	}

	/* initialize register offsets and v1_supported based on version */
	reg_dma_register_count = 133;
	reg_dma_decode_sel = 0x180ac114;
	reg_dma_opmode_offset = 0x4;
	reg_dma_ctl0_queue0_cmd0_offset = 0x14;
	reg_dma_intr_status_offset = 0x160;
	reg_dma_intr_4_status_offset = 0x170;
	reg_dma_intr_clear_offset = 0x1a0;
	reg_dma_ctl_trigger_offset = 0xd4;
	reg_dma_ctl0_reset_offset = 0x200;

	reg_dma_ctl_queue_off[CTL_0] = reg_dma_ctl0_queue0_cmd0_offset;
	for (i = CTL_1; i < ARRAY_SIZE(reg_dma_ctl_queue_off); i++)
		reg_dma_ctl_queue_off[i] = reg_dma_ctl_queue_off[i - 1] +
			(sizeof(u32) * 4);

	v1_supported[IGC] = DSPP_IGC | GRP_DSPP_HW_BLK_SELECT |
				GRP_VIG_HW_BLK_SELECT | GRP_DMA_HW_BLK_SELECT;
	v1_supported[GC] = GRP_DMA_HW_BLK_SELECT | GRP_DSPP_HW_BLK_SELECT;

	return 0;
}
@@ -609,7 +689,7 @@ static int kick_off_v1(struct sde_reg_dma_kickoff_cfg *cfg)
int reset_v1(struct sde_hw_ctl *ctl)
{
	struct sde_hw_blk_reg_map hw;
	u32 index, val;
	u32 index, val, i = 0;

	if (!ctl || ctl->idx > CTL_MAX) {
		DRM_ERROR("invalid ctl %pK ctl idx %d\n",
@@ -620,17 +700,17 @@ int reset_v1(struct sde_hw_ctl *ctl)
	memset(&hw, 0, sizeof(hw));
	index = ctl->idx - CTL_0;
	SET_UP_REG_DMA_REG(hw, reg_dma);
	SDE_REG_WRITE(&hw, REG_DMA_OP_MODE_OFF, BIT(0));
	SDE_REG_WRITE(&hw, (REG_DMA_CTL0_RESET_OFF + index * sizeof(u32)),
	SDE_REG_WRITE(&hw, reg_dma_opmode_offset, BIT(0));
	SDE_REG_WRITE(&hw, (reg_dma_ctl0_reset_offset + index * sizeof(u32)),
			BIT(0));

	index = 0;
	i = 0;
	do {
		udelay(1000);
		index++;
		i++;
		val = SDE_REG_READ(&hw,
			(REG_DMA_CTL0_RESET_OFF + index * sizeof(u32)));
	} while (index < 2 && val);
			(reg_dma_ctl0_reset_offset + index * sizeof(u32)));
	} while (i < 2 && val);

	return 0;
}
@@ -809,7 +889,7 @@ static int write_last_cmd(struct sde_reg_dma_setup_ops_cfg *cfg)

	loc =  (u32 *)((u8 *)cfg->dma_buf->vaddr +
			cfg->dma_buf->index);
	loc[0] = REG_DMA_DECODE_SEL;
	loc[0] = reg_dma_decode_sel;
	loc[1] = 0;
	cfg->dma_buf->index = sizeof(u32) * 2;
	cfg->dma_buf->ops_completed = REG_WRITE_OP | DECODE_SEL_OP;
+7 −1
Original line number Diff line number Diff line
/* Copyright (c) 2017, The Linux Foundation. All rights reserved.
/* Copyright (c) 2017-2018, 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
@@ -20,6 +20,12 @@
 */
int init_v1(struct sde_hw_reg_dma *reg_dma);

/**
 * init_v11() - initialize the reg dma v11 driver by installing v11 ops
 * @reg_dma - reg_dma hw info structure exposing capabilities.
 */
int init_v11(struct sde_hw_reg_dma *reg_dma);

/**
 * deinit_v1() - free up any resources allocated during the v1 reg dma init
 */
+13 −2
Original line number Diff line number Diff line
@@ -14,6 +14,9 @@
#include "sde_hw_reg_dma_v1.h"
#include "sde_dbg.h"

#define REG_DMA_VER_1_0 0x00010000
#define REG_DMA_VER_1_1 0x00010001

static int default_check_support(enum sde_reg_dma_features feature,
		     enum sde_reg_dma_blk blk,
		     bool *is_supported)
@@ -99,11 +102,16 @@ int sde_reg_dma_init(void __iomem *addr, struct sde_mdss_cfg *m,
		return 0;

	switch (reg_dma.caps->version) {
	case 1:
	case REG_DMA_VER_1_0:
		rc = init_v1(&reg_dma);
		if (rc)
			DRM_DEBUG("init v1 dma ops failed\n");
		break;
	case REG_DMA_VER_1_1:
		rc = init_v11(&reg_dma);
		if (rc)
			DRM_DEBUG("init v11 dma ops failed\n");
		break;
	default:
		break;
	}
@@ -129,7 +137,10 @@ void sde_reg_dma_deinit(void)
		return;

	switch (reg_dma.caps->version) {
	case 1:
	case REG_DMA_VER_1_0:
		deinit_v1();
		break;
	case REG_DMA_VER_1_1:
		deinit_v1();
		break;
	default:
+7 −3
Original line number Diff line number Diff line
@@ -106,12 +106,14 @@ enum sde_reg_dma_trigger_mode {
 * @HW_BLK_SELECT: op for selecting the hardware block
 * @REG_SINGLE_WRITE: op for writing single register value
 *                    at the address provided
 * @REG_BLK_WRITE_SINGLE: op for writing multiple registers using hw index
 *                        register
 * @REG_BLK_WRITE_INC: op for writing multiple registers using auto address
 * @REG_BLK_WRITE_SINGLE: op for writing multiple registers using auto address
 *                     increment
 * @REG_BLK_WRITE_INC: op for writing multiple registers using hw index
 *                        register
 * @REG_BLK_WRITE_MULTIPLE: op for writing hw index based registers at
 *                         non-consecutive location
 * @REG_SINGLE_MODIFY: op for modifying single register value
 *                    with bitmask at the address provided
 * @REG_DMA_SETUP_OPS_MAX: invalid operation
 */
enum sde_reg_dma_setup_ops {
@@ -120,6 +122,7 @@ enum sde_reg_dma_setup_ops {
	REG_BLK_WRITE_SINGLE,
	REG_BLK_WRITE_INC,
	REG_BLK_WRITE_MULTIPLE,
	REG_SINGLE_MODIFY,
	REG_DMA_SETUP_OPS_MAX,
};

@@ -230,6 +233,7 @@ struct sde_reg_dma_setup_ops_cfg {
	u32 blk_offset;
	struct sde_reg_dma_buffer *dma_buf;
	u32 *data;
	u32 mask;
	u32 data_size;
};