From c5378278f38622b4ff62af74c2cbf2b94eace992 Mon Sep 17 00:00:00 2001 From: Christopher Braga Date: Tue, 14 Jan 2020 13:55:29 -0500 Subject: [PATCH] disp: msm: sde: Add SSPP Gamut support using new opcode A new LUTDMA opcode is added to LUTDMA V2 to speed up certain LUT programming. This change updates the SSPP Gamut LUT programming using the new opcode and new LUT BUS. Change-Id: I8b88483dc3acbfcdbd6f441bc2105f4368fa42bb Signed-off-by: Ping Li Signed-off-by: Christopher Braga --- msm/sde/sde_hw_reg_dma_v1_color_proc.c | 141 +++++++++++++++++++++++++ msm/sde/sde_hw_reg_dma_v1_color_proc.h | 9 ++ msm/sde/sde_hw_sspp.c | 11 +- 3 files changed, 160 insertions(+), 1 deletion(-) diff --git a/msm/sde/sde_hw_reg_dma_v1_color_proc.c b/msm/sde/sde_hw_reg_dma_v1_color_proc.c index 8edd28f2185e..098dd5d10c7c 100644 --- a/msm/sde/sde_hw_reg_dma_v1_color_proc.c +++ b/msm/sde/sde_hw_reg_dma_v1_color_proc.c @@ -4196,3 +4196,144 @@ void reg_dmav2_setup_dspp_3d_gamutv43(struct sde_hw_dspp *ctx, void *cfg) exit: kfree(data); } + +void reg_dmav2_setup_vig_gamutv61(struct sde_hw_pipe *ctx, void *cfg) +{ + struct sde_hw_cp_cfg *hw_cfg = cfg; + struct drm_msm_3d_gamut *payload; + struct sde_hw_reg_dma_ops *dma_ops; + struct sde_reg_dma_setup_ops_cfg dma_write_cfg; + struct sde_reg_dma_kickoff_cfg kick_off; + int rc; + enum sde_sspp_multirect_index idx = SDE_SSPP_RECT_0; + + u32 gamut_base = ctx->cap->sblk->gamut_blk.base - REG_DMA_VIG_SWI_DIFF; + u32 i, j, k = 0, len, table_select = 0; + u32 op_mode, scale_offset, scale_tbl_offset, transfer_size_bytes; + u16 *data; + + rc = reg_dma_sspp_check(ctx, cfg, GAMUT, idx); + if (rc) + return; + + if (!hw_cfg->payload) { + DRM_DEBUG_DRIVER("disable gamut feature\n"); + /* v5 and v6 call the same off version */ + vig_gamutv5_off(ctx, cfg); + return; + } + + if (hw_cfg->len != sizeof(struct drm_msm_3d_gamut)) { + DRM_ERROR("invalid size of payload len %d exp %zd\n", + hw_cfg->len, sizeof(struct drm_msm_3d_gamut)); + return; + } + + payload = hw_cfg->payload; + if (payload->mode != GAMUT_3D_MODE_17) { + DRM_ERROR("invalid mode %d", payload->mode); + return; + } + + op_mode = SDE_REG_READ(&ctx->hw, ctx->cap->sblk->gamut_blk.base); + op_mode = (op_mode & (BIT(5) - 1)) >> 2; + if (op_mode == gamut_mode_17b) { + op_mode = gamut_mode_17; + table_select = 0; + scale_offset = GAMUT_SCALEA_OFFSET_OFF; + } else { + op_mode = gamut_mode_17b; + table_select = 1; + scale_offset = GAMUT_SCALEB_OFFSET_OFF; + } + + op_mode <<= 2; + if (payload->flags & GAMUT_3D_MAP_EN) + op_mode |= GAMUT_MAP_EN; + op_mode |= GAMUT_EN; + + dma_ops = sde_reg_dma_get_ops(); + dma_ops->reset_reg_dma_buf(sspp_buf[idx][GAMUT][ctx->idx]); + + REG_DMA_INIT_OPS(dma_write_cfg, sspp_mapping[ctx->idx], GAMUT, + sspp_buf[idx][GAMUT][ctx->idx]); + + REG_DMA_SETUP_OPS(dma_write_cfg, 0, NULL, 0, HW_BLK_SELECT, 0, 0, 0); + rc = dma_ops->setup_payload(&dma_write_cfg); + if (rc) { + DRM_ERROR("write decode select failed ret %d\n", rc); + return; + } + + len = GAMUT_3D_TBL_NUM * GAMUT_3D_MODE17_TBL_SZ * 3 * sizeof(u16); + /* Data size must be aligned with word size AND LUT transfer size */ + transfer_size_bytes = LUTBUS_GAMUT_TRANS_SIZE * sizeof(u32); + if (len % transfer_size_bytes) + len = len + (transfer_size_bytes - len % transfer_size_bytes); + + data = kzalloc(len, GFP_KERNEL); + if (!data) + return; + + k = 0; + for (j = 0; j < GAMUT_3D_MODE17_TBL_SZ; j++) { + for (i = 0; i < GAMUT_3D_TBL_NUM; i++) { + /* 10 bit entries, 16 bit per LUTBUS entry and MSB + * aligned to allow expansion, hence, sw needs to + * left shift 6 bits before sending to HW. + */ + data[k++] = (u16)(payload->col[i][j].c0 << 6); + data[k++] = (u16) + ((payload->col[i][j].c2_c1 >> 16) << 6); + data[k++] = (u16)((payload->col[i][j].c2_c1) << 6); + } + } + + REG_DMA_SETUP_OPS(dma_write_cfg, 0, (u32 *)data, len, + REG_BLK_LUT_WRITE, 0, 0, 0); + dma_write_cfg.table_sel = table_select; + dma_write_cfg.block_sel = LUTBUS_BLOCK_GAMUT; + dma_write_cfg.trans_size = LUTBUS_GAMUT_TRANS_SIZE; + dma_write_cfg.lut_size = len / transfer_size_bytes; + + rc = dma_ops->setup_payload(&dma_write_cfg); + if (rc) { + DRM_ERROR("lut write failed ret %d\n", rc); + goto exit; + } + + if (op_mode & GAMUT_MAP_EN) { + for (i = 0; i < GAMUT_3D_SCALE_OFF_TBL_NUM; i++) { + scale_tbl_offset = gamut_base + scale_offset + + (i * GAMUT_SCALE_OFF_LEN); + REG_DMA_SETUP_OPS(dma_write_cfg, scale_tbl_offset, + &payload->scale_off[i][0], + GAMUT_SCALE_OFF_LEN, + REG_BLK_WRITE_SINGLE, 0, 0, 0); + rc = dma_ops->setup_payload(&dma_write_cfg); + if (rc) { + DRM_ERROR("write scale/off reg failed ret %d\n", + rc); + goto exit; + } + } + } + + REG_DMA_SETUP_OPS(dma_write_cfg, gamut_base, + &op_mode, sizeof(op_mode), REG_SINGLE_WRITE, 0, 0, 0); + rc = dma_ops->setup_payload(&dma_write_cfg); + if (rc) { + DRM_ERROR("opmode write single reg failed ret %d\n", rc); + goto exit; + } + + REG_DMA_SETUP_KICKOFF(kick_off, hw_cfg->ctl, + sspp_buf[idx][GAMUT][ctx->idx], REG_DMA_WRITE, + DMA_CTL_QUEUE0, WRITE_IMMEDIATE); + rc = dma_ops->kick_off(&kick_off); + if (rc) + DRM_ERROR("failed to kick off ret %d\n", rc); + +exit: + kfree(data); +} diff --git a/msm/sde/sde_hw_reg_dma_v1_color_proc.h b/msm/sde/sde_hw_reg_dma_v1_color_proc.h index b7e601e5b67d..6a58aa3b5c07 100644 --- a/msm/sde/sde_hw_reg_dma_v1_color_proc.h +++ b/msm/sde/sde_hw_reg_dma_v1_color_proc.h @@ -271,4 +271,13 @@ void reg_dmav2_setup_dspp_igcv32(struct sde_hw_dspp *ctx, void *cfg); */ void reg_dmav2_setup_dspp_3d_gamutv43(struct sde_hw_dspp *ctx, void *cfg); +/** + * reg_dmav2_setup_vig_gamutv61() - VIG 3D lut gamut v61 implementation + * using reg dma v2. + * @ctx: sspp ctx info + * @cfg: pointer to struct sde_hw_cp_cfg + */ +void reg_dmav2_setup_vig_gamutv61(struct sde_hw_pipe *ctx, void *cfg); + + #endif /* _SDE_HW_REG_DMA_V1_COLOR_PROC_H */ diff --git a/msm/sde/sde_hw_sspp.c b/msm/sde/sde_hw_sspp.c index 10cc110a6b98..cb3b0e7a58f9 100644 --- a/msm/sde/sde_hw_sspp.c +++ b/msm/sde/sde_hw_sspp.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2015-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2015-2020, The Linux Foundation. All rights reserved. */ #include "sde_hwio.h" @@ -1085,6 +1085,15 @@ static void _setup_layer_ops_colorproc(struct sde_hw_pipe *c, reg_dmav1_setup_vig_gamutv6; else c->ops.setup_vig_gamut = NULL; + } else if (c->cap->sblk->gamut_blk.version == + (SDE_COLOR_PROCESS_VER(0x6, 0x1))) { + ret = reg_dmav1_init_sspp_op_v4(SDE_SSPP_VIG_GAMUT, + c->idx); + if (!ret) + c->ops.setup_vig_gamut = + reg_dmav2_setup_vig_gamutv61; + else + c->ops.setup_vig_gamut = NULL; } }