Loading drivers/gpu/drm/msm/sde/sde_hw_reg_dma_v1.c +110 −30 Original line number Diff line number Diff line Loading @@ -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; \ Loading @@ -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)) Loading @@ -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); Loading @@ -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] = { Loading Loading @@ -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); Loading @@ -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, Loading @@ -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] = { Loading @@ -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]; Loading @@ -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; Loading Loading @@ -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; Loading Loading @@ -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; Loading Loading @@ -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"); Loading @@ -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]); } Loading Loading @@ -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; } Loading Loading @@ -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", Loading @@ -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; } Loading Loading @@ -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; Loading drivers/gpu/drm/msm/sde/sde_hw_reg_dma_v1.h +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 Loading @@ -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 */ Loading drivers/gpu/drm/msm/sde/sde_reg_dma.c +13 −2 Original line number Diff line number Diff line Loading @@ -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) Loading Loading @@ -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(®_dma); if (rc) DRM_DEBUG("init v1 dma ops failed\n"); break; case REG_DMA_VER_1_1: rc = init_v11(®_dma); if (rc) DRM_DEBUG("init v11 dma ops failed\n"); break; default: break; } Loading @@ -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: Loading drivers/gpu/drm/msm/sde/sde_reg_dma.h +7 −3 Original line number Diff line number Diff line Loading @@ -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 { Loading @@ -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, }; Loading Loading @@ -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; }; Loading Loading
drivers/gpu/drm/msm/sde/sde_hw_reg_dma_v1.c +110 −30 Original line number Diff line number Diff line Loading @@ -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; \ Loading @@ -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)) Loading @@ -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); Loading @@ -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] = { Loading Loading @@ -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); Loading @@ -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, Loading @@ -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] = { Loading @@ -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]; Loading @@ -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; Loading Loading @@ -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; Loading Loading @@ -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; Loading Loading @@ -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"); Loading @@ -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]); } Loading Loading @@ -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; } Loading Loading @@ -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", Loading @@ -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; } Loading Loading @@ -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; Loading
drivers/gpu/drm/msm/sde/sde_hw_reg_dma_v1.h +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 Loading @@ -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 */ Loading
drivers/gpu/drm/msm/sde/sde_reg_dma.c +13 −2 Original line number Diff line number Diff line Loading @@ -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) Loading Loading @@ -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(®_dma); if (rc) DRM_DEBUG("init v1 dma ops failed\n"); break; case REG_DMA_VER_1_1: rc = init_v11(®_dma); if (rc) DRM_DEBUG("init v11 dma ops failed\n"); break; default: break; } Loading @@ -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: Loading
drivers/gpu/drm/msm/sde/sde_reg_dma.h +7 −3 Original line number Diff line number Diff line Loading @@ -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 { Loading @@ -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, }; Loading Loading @@ -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; }; Loading