Loading drivers/gpu/drm/msm/sde/sde_color_processing.c +55 −1 Original line number Diff line number Diff line Loading @@ -51,6 +51,10 @@ static void dspp_ad_install_property(struct drm_crtc *crtc); static void dspp_vlut_install_property(struct drm_crtc *crtc); static void dspp_gamut_install_property(struct drm_crtc *crtc); static void dspp_gc_install_property(struct drm_crtc *crtc); typedef void (*dspp_prop_install_func_t)(struct drm_crtc *crtc); static dspp_prop_install_func_t dspp_prop_install_func[SDE_DSPP_MAX]; Loading @@ -61,6 +65,8 @@ do { \ func[SDE_DSPP_HSIC] = dspp_hsic_install_property; \ func[SDE_DSPP_AD] = dspp_ad_install_property; \ func[SDE_DSPP_VLUT] = dspp_vlut_install_property; \ func[SDE_DSPP_GAMUT] = dspp_gamut_install_property; \ func[SDE_DSPP_GC] = dspp_gc_install_property; \ } while (0) typedef void (*lm_prop_install_func_t)(struct drm_crtc *crtc); Loading Loading @@ -454,7 +460,7 @@ static void sde_cp_crtc_setfeature(struct sde_cp_node *prop_node, 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; switch (prop_node->feature) { case SDE_CP_CRTC_DSPP_VLUT: if (!hw_dspp || !hw_dspp->ops.setup_vlut) { Loading Loading @@ -988,3 +994,51 @@ static void lm_gc_install_property(struct drm_crtc *crtc) break; } } static void dspp_gamut_install_property(struct drm_crtc *crtc) { char feature_name[256]; struct sde_kms *kms = NULL; struct sde_mdss_cfg *catalog = NULL; u32 version; kms = get_kms(crtc); catalog = kms->catalog; version = catalog->dspp[0].sblk->gamut.version >> 16; snprintf(feature_name, ARRAY_SIZE(feature_name), "%s%d", "SDE_DSPP_GAMUT_V", version); switch (version) { case 4: sde_cp_crtc_create_blob_property(crtc, feature_name, SDE_CP_CRTC_DSPP_GAMUT); break; default: DRM_ERROR("version %d not supported\n", version); break; } } static void dspp_gc_install_property(struct drm_crtc *crtc) { char feature_name[256]; struct sde_kms *kms = NULL; struct sde_mdss_cfg *catalog = NULL; u32 version; kms = get_kms(crtc); catalog = kms->catalog; version = catalog->dspp[0].sblk->gc.version >> 16; snprintf(feature_name, ARRAY_SIZE(feature_name), "%s%d", "SDE_DSPP_GC_V", version); switch (version) { case 1: sde_cp_crtc_create_blob_property(crtc, feature_name, SDE_CP_CRTC_DSPP_GC); break; default: DRM_ERROR("version %d not supported\n", version); break; } } drivers/gpu/drm/msm/sde/sde_hw_color_proc_common_v4.h 0 → 100644 +39 −0 Original line number Diff line number Diff line /* Copyright (c) 2017, 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 * only version 2 as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. */ #ifndef _SDE_HW_COLOR_PROC_COMMON_V4_H_ #define _SDE_HW_COLOR_PROC_COMMON_V4_H_ #define GAMUT_TABLE_SEL_OFF 0x4 #define GAMUT_SCALEA_OFFSET_OFF 0x10 #define GAMUT_SCALEB_OFFSET_OFF 0x50 #define GAMUT_LOWER_COLOR_OFF 0xc #define GAMUT_UPPER_COLOR_OFF 0x8 #define GAMUT_TABLE0_SEL BIT(12) #define GAMUT_MAP_EN BIT(1) #define GAMUT_EN BIT(0) #define GAMUT_MODE_13B_OFF 640 enum { gamut_mode_17 = 0, gamut_mode_5, gamut_mode_13a, gamut_mode_13b, }; #define GC_C0_OFF 0x4 #define GC_C0_INDEX_OFF 0x8 #define GC_8B_ROUND_EN BIT(1) #define GC_EN BIT(0) #define GC_TBL_NUM 3 #define GC_LUT_SWAP_OFF 0x1c #endif /* _SDE_HW_COLOR_PROC_COMMON_V4_H_ */ drivers/gpu/drm/msm/sde/sde_hw_dspp.c +18 −0 Original line number Diff line number Diff line Loading @@ -67,6 +67,24 @@ static void _setup_dspp_ops(struct sde_hw_dspp *c, unsigned long features) reg_dmav1_setup_dspp_vlutv18; } break; case SDE_DSPP_GAMUT: if (c->cap->sblk->gamut.version == SDE_COLOR_PROCESS_VER(0x4, 0)) { ret = reg_dmav1_init_dspp_op_v4(i, c->idx); if (!ret) c->ops.setup_gamut = reg_dmav1_setup_dspp_3d_gamutv4; } break; case SDE_DSPP_GC: if (c->cap->sblk->gc.version == SDE_COLOR_PROCESS_VER(0x1, 8)) { ret = reg_dmav1_init_dspp_op_v4(i, c->idx); if (!ret) c->ops.setup_gc = reg_dmav1_setup_dspp_gcv18; } break; default: break; } Loading drivers/gpu/drm/msm/sde/sde_hw_reg_dma_v1.c +3 −2 Original line number Diff line number Diff line Loading @@ -67,7 +67,7 @@ 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) [REG_SINGLE_WRITE] = sizeof(u32) * 2 }; static u32 queue_sel[DMA_CTL_QUEUE_MAX] = { Loading @@ -86,6 +86,7 @@ static u32 dspp_read_sel[DSPP_HIST_MAX] = { static u32 v1_supported[REG_DMA_FEATURES_MAX] = { [GAMUT] = GRP_VIG_HW_BLK_SELECT | GRP_DSPP_HW_BLK_SELECT, [VLUT] = GRP_DSPP_HW_BLK_SELECT, [GC] = GRP_DSPP_HW_BLK_SELECT, }; static int validate_dma_cfg(struct sde_reg_dma_setup_ops_cfg *cfg); Loading Loading @@ -216,7 +217,7 @@ static int write_multi_lut_reg(struct sde_reg_dma_setup_ops_cfg *cfg) loc[0] = BLK_REG_WRITE_OPCODE; loc[0] |= (cfg->blk_offset & MAX_RELATIVE_OFF); loc[1] = (cfg->inc) ? 0 : BIT(31); loc[1] |= (cfg->wrap_size & WRAP_MAX_SIZE) << 19; loc[1] |= (cfg->wrap_size & WRAP_MAX_SIZE) << 16; loc[1] |= ((SIZE_DWORD(cfg->data_size)) & MAX_DWORDS_SZ); cfg->dma_buf->next_op_allowed = REG_WRITE_OP; cfg->dma_buf->index += ops_mem_size[cfg->ops]; Loading drivers/gpu/drm/msm/sde/sde_hw_reg_dma_v1_color_proc.c +256 −5 Original line number Diff line number Diff line Loading @@ -12,6 +12,7 @@ #include <drm/msm_drm_pp.h> #include "sde_reg_dma.h" #include "sde_hw_reg_dma_v1_color_proc.h" #include "sde_hw_color_proc_common_v4.h" /* Reserve space of 128 words for LUT dma payload set-up */ #define REG_DMA_HEADERS_BUFFER_SZ (sizeof(u32) * 128) Loading @@ -23,6 +24,11 @@ #define GAMUT_LUT_MEM_SIZE ((sizeof(struct drm_msm_3d_gamut)) + \ REG_DMA_HEADERS_BUFFER_SZ) #define GAMUT_SCALE_OFF_LEN (GAMUT_3D_SCALE_OFF_SZ * \ GAMUT_3D_SCALE_OFF_TBL_NUM * sizeof(u32)) #define GC_LUT_MEM_SIZE ((sizeof(struct drm_msm_pgc_lut)) + \ REG_DMA_HEADERS_BUFFER_SZ) #define REG_MASK(n) ((BIT(n)) - 1) Loading @@ -33,7 +39,7 @@ static u32 feature_map[SDE_DSPP_MAX] = { [SDE_DSPP_GAMUT] = GAMUT, [SDE_DSPP_IGC] = REG_DMA_FEATURES_MAX, [SDE_DSPP_PCC] = REG_DMA_FEATURES_MAX, [SDE_DSPP_GC] = REG_DMA_FEATURES_MAX, [SDE_DSPP_GC] = GC, [SDE_DSPP_HSIC] = REG_DMA_FEATURES_MAX, [SDE_DSPP_MEMCOLOR] = REG_DMA_FEATURES_MAX, [SDE_DSPP_SIXZONE] = REG_DMA_FEATURES_MAX, Loading @@ -45,6 +51,7 @@ static u32 feature_map[SDE_DSPP_MAX] = { static u32 feature_reg_dma_sz[SDE_DSPP_MAX] = { [SDE_DSPP_VLUT] = VLUT_MEM_SIZE, [SDE_DSPP_GAMUT] = GAMUT_LUT_MEM_SIZE, [SDE_DSPP_GC] = GC_LUT_MEM_SIZE, }; static u32 dspp_mapping[DSPP_MAX] = { Loading @@ -54,12 +61,34 @@ static u32 dspp_mapping[DSPP_MAX] = { [DSPP_3] = DSPP3, }; #define REG_DMA_OP_SETUP(cfg, block, reg_dma_feature, op, buf) \ #define REG_DMA_INIT_OPS(cfg, block, reg_dma_feature, feature_dma_buf) \ do { \ memset(&cfg, 0, sizeof(cfg)); \ (cfg).blk = block; \ (cfg).feature = reg_dma_feature; \ (cfg).dma_buf = feature_dma_buf; \ } while (0) #define REG_DMA_SETUP_OPS(cfg, block_off, data_ptr, data_len, op, \ wrap_sz, wrap_inc) \ do { \ (cfg).ops = op; \ (cfg).dma_buf = buf; \ (cfg).blk_offset = block_off; \ (cfg).data_size = data_len; \ (cfg).data = data_ptr; \ (cfg).inc = wrap_inc; \ (cfg).wrap_size = wrap_sz; \ } while (0) #define REG_DMA_SETUP_KICKOFF(cfg, hw_ctl, feature_dma_buf, ops, ctl_q, \ mode) \ do { \ memset(&cfg, 0, sizeof(cfg)); \ (cfg).ctl = hw_ctl; \ (cfg).dma_buf = feature_dma_buf; \ (cfg).op = ops; \ (cfg).queue_select = ctl_q; \ (cfg).trigger_mode = mode; \ } while (0) static int reg_dma_buf_init(struct sde_reg_dma_buffer **buf, u32 sz); Loading @@ -75,7 +104,6 @@ static int reg_dma_kick_off(enum sde_reg_dma_op op, enum sde_reg_dma_queue q, enum sde_reg_dma_trigger_mode mode, struct sde_reg_dma_buffer *dma_buf, struct sde_hw_ctl *ctl); static int reg_dma_buf_init(struct sde_reg_dma_buffer **buf, u32 size) { struct sde_hw_reg_dma_ops *dma_ops; Loading Loading @@ -130,7 +158,6 @@ static int reg_dma_dspp_check(struct sde_hw_dspp *ctx, void *cfg, return 0; } static int reg_dma_blk_select(enum sde_reg_dma_features feature, enum sde_reg_dma_blk blk, struct sde_reg_dma_buffer *dma_buf) { Loading Loading @@ -300,3 +327,227 @@ void reg_dmav1_setup_dspp_vlutv18(struct sde_hw_dspp *ctx, void *cfg) exit: kfree(data); } static int sde_gamut_get_mode_info(struct drm_msm_3d_gamut *payload, u32 *tbl_len, u32 *tbl_off, u32 *opcode, u32 *scale_off) { int rc = 0; if (payload->mode > GAMUT_3D_MODE_13) { DRM_ERROR("invalid mode %d", payload->mode); return -EINVAL; } switch (payload->mode) { case GAMUT_3D_MODE_17: *tbl_len = GAMUT_3D_MODE17_TBL_SZ * sizeof(u32) * 2; *tbl_off = 0; *scale_off = GAMUT_SCALEA_OFFSET_OFF; *opcode = gamut_mode_17 << 2; break; case GAMUT_3D_MODE_5: *tbl_len = GAMUT_3D_MODE5_TBL_SZ * sizeof(u32) * 2; *tbl_off = 0; *scale_off = GAMUT_SCALEB_OFFSET_OFF; *opcode = gamut_mode_5 << 2; *opcode |= GAMUT_MAP_EN; break; case GAMUT_3D_MODE_13: *tbl_len = GAMUT_3D_MODE13_TBL_SZ * sizeof(u32) * 2; *opcode = (*opcode & (BIT(4) - 1)) >> 2; if (*opcode == gamut_mode_13a) *opcode = gamut_mode_13b; else *opcode = gamut_mode_13a; *tbl_off = (*opcode == gamut_mode_13a) ? 0 : GAMUT_MODE_13B_OFF; *scale_off = (*opcode == gamut_mode_13a) ? GAMUT_SCALEA_OFFSET_OFF : GAMUT_SCALEB_OFFSET_OFF; *opcode <<= 2; *opcode |= GAMUT_MAP_EN; break; default: rc = -EINVAL; break; } if (payload->flags & GAMUT_3D_MAP_EN) *opcode |= GAMUT_MAP_EN; *opcode |= GAMUT_EN; return rc; } void reg_dmav1_setup_dspp_3d_gamutv4(struct sde_hw_dspp *ctx, void *cfg) { struct drm_msm_3d_gamut *payload; struct sde_reg_dma_kickoff_cfg kick_off; struct sde_hw_cp_cfg *hw_cfg = cfg; u32 op_mode, reg, tbl_len, tbl_off, scale_off, i; struct sde_reg_dma_setup_ops_cfg dma_write_cfg; struct sde_hw_reg_dma_ops *dma_ops; int rc; rc = reg_dma_dspp_check(ctx, cfg, GAMUT); if (rc) return; op_mode = SDE_REG_READ(&ctx->hw, ctx->cap->sblk->gamut.base); if (!hw_cfg->payload) { DRM_DEBUG_DRIVER("disable gamut feature\n"); SDE_REG_WRITE(&ctx->hw, ctx->cap->sblk->gamut.base, 0); 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; rc = sde_gamut_get_mode_info(payload, &tbl_len, &tbl_off, &op_mode, &scale_off); if (rc) { DRM_ERROR("invalid mode info rc %d\n", rc); return; } dma_ops = sde_reg_dma_get_ops(); dma_ops->reset_reg_dma_buf(dspp_buf[GAMUT][ctx->idx]); REG_DMA_INIT_OPS(dma_write_cfg, dspp_mapping[ctx->idx], GAMUT, dspp_buf[GAMUT][ctx->idx]); REG_DMA_SETUP_OPS(dma_write_cfg, 0, NULL, 0, HW_BLK_SELECT, 0, 0); rc = dma_ops->setup_payload(&dma_write_cfg); if (rc) { DRM_ERROR("write decode select failed ret %d\n", rc); return; } for (i = 0; i < GAMUT_3D_TBL_NUM; i++) { reg = GAMUT_TABLE0_SEL << i; reg |= ((tbl_off) & (BIT(11) - 1)); REG_DMA_SETUP_OPS(dma_write_cfg, ctx->cap->sblk->gamut.base + GAMUT_TABLE_SEL_OFF, ®, sizeof(reg), REG_SINGLE_WRITE, 0, 0); rc = dma_ops->setup_payload(&dma_write_cfg); if (rc) { DRM_ERROR("write tbl sel reg failed ret %d\n", rc); return; } REG_DMA_SETUP_OPS(dma_write_cfg, ctx->cap->sblk->gamut.base + GAMUT_LOWER_COLOR_OFF, &payload->col[i][0].c0, tbl_len, REG_BLK_WRITE_MULTIPLE, 2, 0); rc = dma_ops->setup_payload(&dma_write_cfg); if (rc) { DRM_ERROR("write color reg failed ret %d\n", rc); return; } } if (op_mode & GAMUT_MAP_EN) { REG_DMA_SETUP_OPS(dma_write_cfg, ctx->cap->sblk->gamut.base + scale_off, payload->scale_off[0], GAMUT_SCALE_OFF_LEN, REG_BLK_WRITE_SINGLE, 0, 0); rc = dma_ops->setup_payload(&dma_write_cfg); if (rc) { DRM_ERROR("write scale/off reg failed ret %d\n", rc); return; } } REG_DMA_SETUP_OPS(dma_write_cfg, ctx->cap->sblk->gamut.base, &op_mode, sizeof(op_mode), REG_SINGLE_WRITE, 0, 0); rc = dma_ops->setup_payload(&dma_write_cfg); if (rc) { DRM_ERROR("opmode write single reg failed ret %d\n", rc); return; } REG_DMA_SETUP_KICKOFF(kick_off, hw_cfg->ctl, dspp_buf[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); } void reg_dmav1_setup_dspp_gcv18(struct sde_hw_dspp *ctx, void *cfg) { struct drm_msm_pgc_lut *lut_cfg; struct sde_hw_reg_dma_ops *dma_ops; struct sde_reg_dma_kickoff_cfg kick_off; struct sde_hw_cp_cfg *hw_cfg = cfg; struct sde_reg_dma_setup_ops_cfg dma_write_cfg; int rc, i = 0; u32 reg; rc = reg_dma_dspp_check(ctx, cfg, GAMUT); if (rc) return; if (!hw_cfg->payload) { DRM_DEBUG_DRIVER("disable pgc feature\n"); SDE_REG_WRITE(&ctx->hw, ctx->cap->sblk->gc.base, 0); return; } if (hw_cfg->len != sizeof(struct drm_msm_pgc_lut)) { DRM_ERROR("invalid size of payload len %d exp %zd\n", hw_cfg->len, sizeof(struct drm_msm_pgc_lut)); return; } lut_cfg = hw_cfg->payload; dma_ops = sde_reg_dma_get_ops(); dma_ops->reset_reg_dma_buf(dspp_buf[GC][ctx->idx]); REG_DMA_INIT_OPS(dma_write_cfg, dspp_mapping[ctx->idx], GC, dspp_buf[GC][ctx->idx]); REG_DMA_SETUP_OPS(dma_write_cfg, 0, NULL, 0, HW_BLK_SELECT, 0, 0); rc = dma_ops->setup_payload(&dma_write_cfg); if (rc) { DRM_ERROR("write decode select failed ret %d\n", rc); return; } for (i = 0; i < GC_TBL_NUM; i++) { reg = 0; REG_DMA_SETUP_OPS(dma_write_cfg, ctx->cap->sblk->gc.base + GC_C0_INDEX_OFF + (i * sizeof(u32) * 2), ®, sizeof(reg), REG_SINGLE_WRITE, 0, 0); rc = dma_ops->setup_payload(&dma_write_cfg); if (rc) { DRM_ERROR("index init failed ret %d\n", rc); return; } REG_DMA_SETUP_OPS(dma_write_cfg, ctx->cap->sblk->gc.base + GC_C0_OFF + (i * sizeof(u32) * 2), lut_cfg->c0 + ARRAY_SIZE(lut_cfg->c0), PGC_TBL_LEN * sizeof(u32), REG_BLK_WRITE_INC, 0, 0); rc = dma_ops->setup_payload(&dma_write_cfg); if (rc) { DRM_ERROR("index init failed ret %d\n", rc); return; } } REG_DMA_SETUP_KICKOFF(kick_off, hw_cfg->ctl, dspp_buf[GC][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); return; } reg = GC_EN | ((lut_cfg->flags & PGC_8B_ROUND) ? GC_8B_ROUND_EN : 0); SDE_REG_WRITE(&ctx->hw, ctx->cap->sblk->gc.base + GC_LUT_SWAP_OFF, BIT(0)); SDE_REG_WRITE(&ctx->hw, ctx->cap->sblk->gc.base, reg); } Loading
drivers/gpu/drm/msm/sde/sde_color_processing.c +55 −1 Original line number Diff line number Diff line Loading @@ -51,6 +51,10 @@ static void dspp_ad_install_property(struct drm_crtc *crtc); static void dspp_vlut_install_property(struct drm_crtc *crtc); static void dspp_gamut_install_property(struct drm_crtc *crtc); static void dspp_gc_install_property(struct drm_crtc *crtc); typedef void (*dspp_prop_install_func_t)(struct drm_crtc *crtc); static dspp_prop_install_func_t dspp_prop_install_func[SDE_DSPP_MAX]; Loading @@ -61,6 +65,8 @@ do { \ func[SDE_DSPP_HSIC] = dspp_hsic_install_property; \ func[SDE_DSPP_AD] = dspp_ad_install_property; \ func[SDE_DSPP_VLUT] = dspp_vlut_install_property; \ func[SDE_DSPP_GAMUT] = dspp_gamut_install_property; \ func[SDE_DSPP_GC] = dspp_gc_install_property; \ } while (0) typedef void (*lm_prop_install_func_t)(struct drm_crtc *crtc); Loading Loading @@ -454,7 +460,7 @@ static void sde_cp_crtc_setfeature(struct sde_cp_node *prop_node, 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; switch (prop_node->feature) { case SDE_CP_CRTC_DSPP_VLUT: if (!hw_dspp || !hw_dspp->ops.setup_vlut) { Loading Loading @@ -988,3 +994,51 @@ static void lm_gc_install_property(struct drm_crtc *crtc) break; } } static void dspp_gamut_install_property(struct drm_crtc *crtc) { char feature_name[256]; struct sde_kms *kms = NULL; struct sde_mdss_cfg *catalog = NULL; u32 version; kms = get_kms(crtc); catalog = kms->catalog; version = catalog->dspp[0].sblk->gamut.version >> 16; snprintf(feature_name, ARRAY_SIZE(feature_name), "%s%d", "SDE_DSPP_GAMUT_V", version); switch (version) { case 4: sde_cp_crtc_create_blob_property(crtc, feature_name, SDE_CP_CRTC_DSPP_GAMUT); break; default: DRM_ERROR("version %d not supported\n", version); break; } } static void dspp_gc_install_property(struct drm_crtc *crtc) { char feature_name[256]; struct sde_kms *kms = NULL; struct sde_mdss_cfg *catalog = NULL; u32 version; kms = get_kms(crtc); catalog = kms->catalog; version = catalog->dspp[0].sblk->gc.version >> 16; snprintf(feature_name, ARRAY_SIZE(feature_name), "%s%d", "SDE_DSPP_GC_V", version); switch (version) { case 1: sde_cp_crtc_create_blob_property(crtc, feature_name, SDE_CP_CRTC_DSPP_GC); break; default: DRM_ERROR("version %d not supported\n", version); break; } }
drivers/gpu/drm/msm/sde/sde_hw_color_proc_common_v4.h 0 → 100644 +39 −0 Original line number Diff line number Diff line /* Copyright (c) 2017, 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 * only version 2 as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. */ #ifndef _SDE_HW_COLOR_PROC_COMMON_V4_H_ #define _SDE_HW_COLOR_PROC_COMMON_V4_H_ #define GAMUT_TABLE_SEL_OFF 0x4 #define GAMUT_SCALEA_OFFSET_OFF 0x10 #define GAMUT_SCALEB_OFFSET_OFF 0x50 #define GAMUT_LOWER_COLOR_OFF 0xc #define GAMUT_UPPER_COLOR_OFF 0x8 #define GAMUT_TABLE0_SEL BIT(12) #define GAMUT_MAP_EN BIT(1) #define GAMUT_EN BIT(0) #define GAMUT_MODE_13B_OFF 640 enum { gamut_mode_17 = 0, gamut_mode_5, gamut_mode_13a, gamut_mode_13b, }; #define GC_C0_OFF 0x4 #define GC_C0_INDEX_OFF 0x8 #define GC_8B_ROUND_EN BIT(1) #define GC_EN BIT(0) #define GC_TBL_NUM 3 #define GC_LUT_SWAP_OFF 0x1c #endif /* _SDE_HW_COLOR_PROC_COMMON_V4_H_ */
drivers/gpu/drm/msm/sde/sde_hw_dspp.c +18 −0 Original line number Diff line number Diff line Loading @@ -67,6 +67,24 @@ static void _setup_dspp_ops(struct sde_hw_dspp *c, unsigned long features) reg_dmav1_setup_dspp_vlutv18; } break; case SDE_DSPP_GAMUT: if (c->cap->sblk->gamut.version == SDE_COLOR_PROCESS_VER(0x4, 0)) { ret = reg_dmav1_init_dspp_op_v4(i, c->idx); if (!ret) c->ops.setup_gamut = reg_dmav1_setup_dspp_3d_gamutv4; } break; case SDE_DSPP_GC: if (c->cap->sblk->gc.version == SDE_COLOR_PROCESS_VER(0x1, 8)) { ret = reg_dmav1_init_dspp_op_v4(i, c->idx); if (!ret) c->ops.setup_gc = reg_dmav1_setup_dspp_gcv18; } break; default: break; } Loading
drivers/gpu/drm/msm/sde/sde_hw_reg_dma_v1.c +3 −2 Original line number Diff line number Diff line Loading @@ -67,7 +67,7 @@ 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) [REG_SINGLE_WRITE] = sizeof(u32) * 2 }; static u32 queue_sel[DMA_CTL_QUEUE_MAX] = { Loading @@ -86,6 +86,7 @@ static u32 dspp_read_sel[DSPP_HIST_MAX] = { static u32 v1_supported[REG_DMA_FEATURES_MAX] = { [GAMUT] = GRP_VIG_HW_BLK_SELECT | GRP_DSPP_HW_BLK_SELECT, [VLUT] = GRP_DSPP_HW_BLK_SELECT, [GC] = GRP_DSPP_HW_BLK_SELECT, }; static int validate_dma_cfg(struct sde_reg_dma_setup_ops_cfg *cfg); Loading Loading @@ -216,7 +217,7 @@ static int write_multi_lut_reg(struct sde_reg_dma_setup_ops_cfg *cfg) loc[0] = BLK_REG_WRITE_OPCODE; loc[0] |= (cfg->blk_offset & MAX_RELATIVE_OFF); loc[1] = (cfg->inc) ? 0 : BIT(31); loc[1] |= (cfg->wrap_size & WRAP_MAX_SIZE) << 19; loc[1] |= (cfg->wrap_size & WRAP_MAX_SIZE) << 16; loc[1] |= ((SIZE_DWORD(cfg->data_size)) & MAX_DWORDS_SZ); cfg->dma_buf->next_op_allowed = REG_WRITE_OP; cfg->dma_buf->index += ops_mem_size[cfg->ops]; Loading
drivers/gpu/drm/msm/sde/sde_hw_reg_dma_v1_color_proc.c +256 −5 Original line number Diff line number Diff line Loading @@ -12,6 +12,7 @@ #include <drm/msm_drm_pp.h> #include "sde_reg_dma.h" #include "sde_hw_reg_dma_v1_color_proc.h" #include "sde_hw_color_proc_common_v4.h" /* Reserve space of 128 words for LUT dma payload set-up */ #define REG_DMA_HEADERS_BUFFER_SZ (sizeof(u32) * 128) Loading @@ -23,6 +24,11 @@ #define GAMUT_LUT_MEM_SIZE ((sizeof(struct drm_msm_3d_gamut)) + \ REG_DMA_HEADERS_BUFFER_SZ) #define GAMUT_SCALE_OFF_LEN (GAMUT_3D_SCALE_OFF_SZ * \ GAMUT_3D_SCALE_OFF_TBL_NUM * sizeof(u32)) #define GC_LUT_MEM_SIZE ((sizeof(struct drm_msm_pgc_lut)) + \ REG_DMA_HEADERS_BUFFER_SZ) #define REG_MASK(n) ((BIT(n)) - 1) Loading @@ -33,7 +39,7 @@ static u32 feature_map[SDE_DSPP_MAX] = { [SDE_DSPP_GAMUT] = GAMUT, [SDE_DSPP_IGC] = REG_DMA_FEATURES_MAX, [SDE_DSPP_PCC] = REG_DMA_FEATURES_MAX, [SDE_DSPP_GC] = REG_DMA_FEATURES_MAX, [SDE_DSPP_GC] = GC, [SDE_DSPP_HSIC] = REG_DMA_FEATURES_MAX, [SDE_DSPP_MEMCOLOR] = REG_DMA_FEATURES_MAX, [SDE_DSPP_SIXZONE] = REG_DMA_FEATURES_MAX, Loading @@ -45,6 +51,7 @@ static u32 feature_map[SDE_DSPP_MAX] = { static u32 feature_reg_dma_sz[SDE_DSPP_MAX] = { [SDE_DSPP_VLUT] = VLUT_MEM_SIZE, [SDE_DSPP_GAMUT] = GAMUT_LUT_MEM_SIZE, [SDE_DSPP_GC] = GC_LUT_MEM_SIZE, }; static u32 dspp_mapping[DSPP_MAX] = { Loading @@ -54,12 +61,34 @@ static u32 dspp_mapping[DSPP_MAX] = { [DSPP_3] = DSPP3, }; #define REG_DMA_OP_SETUP(cfg, block, reg_dma_feature, op, buf) \ #define REG_DMA_INIT_OPS(cfg, block, reg_dma_feature, feature_dma_buf) \ do { \ memset(&cfg, 0, sizeof(cfg)); \ (cfg).blk = block; \ (cfg).feature = reg_dma_feature; \ (cfg).dma_buf = feature_dma_buf; \ } while (0) #define REG_DMA_SETUP_OPS(cfg, block_off, data_ptr, data_len, op, \ wrap_sz, wrap_inc) \ do { \ (cfg).ops = op; \ (cfg).dma_buf = buf; \ (cfg).blk_offset = block_off; \ (cfg).data_size = data_len; \ (cfg).data = data_ptr; \ (cfg).inc = wrap_inc; \ (cfg).wrap_size = wrap_sz; \ } while (0) #define REG_DMA_SETUP_KICKOFF(cfg, hw_ctl, feature_dma_buf, ops, ctl_q, \ mode) \ do { \ memset(&cfg, 0, sizeof(cfg)); \ (cfg).ctl = hw_ctl; \ (cfg).dma_buf = feature_dma_buf; \ (cfg).op = ops; \ (cfg).queue_select = ctl_q; \ (cfg).trigger_mode = mode; \ } while (0) static int reg_dma_buf_init(struct sde_reg_dma_buffer **buf, u32 sz); Loading @@ -75,7 +104,6 @@ static int reg_dma_kick_off(enum sde_reg_dma_op op, enum sde_reg_dma_queue q, enum sde_reg_dma_trigger_mode mode, struct sde_reg_dma_buffer *dma_buf, struct sde_hw_ctl *ctl); static int reg_dma_buf_init(struct sde_reg_dma_buffer **buf, u32 size) { struct sde_hw_reg_dma_ops *dma_ops; Loading Loading @@ -130,7 +158,6 @@ static int reg_dma_dspp_check(struct sde_hw_dspp *ctx, void *cfg, return 0; } static int reg_dma_blk_select(enum sde_reg_dma_features feature, enum sde_reg_dma_blk blk, struct sde_reg_dma_buffer *dma_buf) { Loading Loading @@ -300,3 +327,227 @@ void reg_dmav1_setup_dspp_vlutv18(struct sde_hw_dspp *ctx, void *cfg) exit: kfree(data); } static int sde_gamut_get_mode_info(struct drm_msm_3d_gamut *payload, u32 *tbl_len, u32 *tbl_off, u32 *opcode, u32 *scale_off) { int rc = 0; if (payload->mode > GAMUT_3D_MODE_13) { DRM_ERROR("invalid mode %d", payload->mode); return -EINVAL; } switch (payload->mode) { case GAMUT_3D_MODE_17: *tbl_len = GAMUT_3D_MODE17_TBL_SZ * sizeof(u32) * 2; *tbl_off = 0; *scale_off = GAMUT_SCALEA_OFFSET_OFF; *opcode = gamut_mode_17 << 2; break; case GAMUT_3D_MODE_5: *tbl_len = GAMUT_3D_MODE5_TBL_SZ * sizeof(u32) * 2; *tbl_off = 0; *scale_off = GAMUT_SCALEB_OFFSET_OFF; *opcode = gamut_mode_5 << 2; *opcode |= GAMUT_MAP_EN; break; case GAMUT_3D_MODE_13: *tbl_len = GAMUT_3D_MODE13_TBL_SZ * sizeof(u32) * 2; *opcode = (*opcode & (BIT(4) - 1)) >> 2; if (*opcode == gamut_mode_13a) *opcode = gamut_mode_13b; else *opcode = gamut_mode_13a; *tbl_off = (*opcode == gamut_mode_13a) ? 0 : GAMUT_MODE_13B_OFF; *scale_off = (*opcode == gamut_mode_13a) ? GAMUT_SCALEA_OFFSET_OFF : GAMUT_SCALEB_OFFSET_OFF; *opcode <<= 2; *opcode |= GAMUT_MAP_EN; break; default: rc = -EINVAL; break; } if (payload->flags & GAMUT_3D_MAP_EN) *opcode |= GAMUT_MAP_EN; *opcode |= GAMUT_EN; return rc; } void reg_dmav1_setup_dspp_3d_gamutv4(struct sde_hw_dspp *ctx, void *cfg) { struct drm_msm_3d_gamut *payload; struct sde_reg_dma_kickoff_cfg kick_off; struct sde_hw_cp_cfg *hw_cfg = cfg; u32 op_mode, reg, tbl_len, tbl_off, scale_off, i; struct sde_reg_dma_setup_ops_cfg dma_write_cfg; struct sde_hw_reg_dma_ops *dma_ops; int rc; rc = reg_dma_dspp_check(ctx, cfg, GAMUT); if (rc) return; op_mode = SDE_REG_READ(&ctx->hw, ctx->cap->sblk->gamut.base); if (!hw_cfg->payload) { DRM_DEBUG_DRIVER("disable gamut feature\n"); SDE_REG_WRITE(&ctx->hw, ctx->cap->sblk->gamut.base, 0); 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; rc = sde_gamut_get_mode_info(payload, &tbl_len, &tbl_off, &op_mode, &scale_off); if (rc) { DRM_ERROR("invalid mode info rc %d\n", rc); return; } dma_ops = sde_reg_dma_get_ops(); dma_ops->reset_reg_dma_buf(dspp_buf[GAMUT][ctx->idx]); REG_DMA_INIT_OPS(dma_write_cfg, dspp_mapping[ctx->idx], GAMUT, dspp_buf[GAMUT][ctx->idx]); REG_DMA_SETUP_OPS(dma_write_cfg, 0, NULL, 0, HW_BLK_SELECT, 0, 0); rc = dma_ops->setup_payload(&dma_write_cfg); if (rc) { DRM_ERROR("write decode select failed ret %d\n", rc); return; } for (i = 0; i < GAMUT_3D_TBL_NUM; i++) { reg = GAMUT_TABLE0_SEL << i; reg |= ((tbl_off) & (BIT(11) - 1)); REG_DMA_SETUP_OPS(dma_write_cfg, ctx->cap->sblk->gamut.base + GAMUT_TABLE_SEL_OFF, ®, sizeof(reg), REG_SINGLE_WRITE, 0, 0); rc = dma_ops->setup_payload(&dma_write_cfg); if (rc) { DRM_ERROR("write tbl sel reg failed ret %d\n", rc); return; } REG_DMA_SETUP_OPS(dma_write_cfg, ctx->cap->sblk->gamut.base + GAMUT_LOWER_COLOR_OFF, &payload->col[i][0].c0, tbl_len, REG_BLK_WRITE_MULTIPLE, 2, 0); rc = dma_ops->setup_payload(&dma_write_cfg); if (rc) { DRM_ERROR("write color reg failed ret %d\n", rc); return; } } if (op_mode & GAMUT_MAP_EN) { REG_DMA_SETUP_OPS(dma_write_cfg, ctx->cap->sblk->gamut.base + scale_off, payload->scale_off[0], GAMUT_SCALE_OFF_LEN, REG_BLK_WRITE_SINGLE, 0, 0); rc = dma_ops->setup_payload(&dma_write_cfg); if (rc) { DRM_ERROR("write scale/off reg failed ret %d\n", rc); return; } } REG_DMA_SETUP_OPS(dma_write_cfg, ctx->cap->sblk->gamut.base, &op_mode, sizeof(op_mode), REG_SINGLE_WRITE, 0, 0); rc = dma_ops->setup_payload(&dma_write_cfg); if (rc) { DRM_ERROR("opmode write single reg failed ret %d\n", rc); return; } REG_DMA_SETUP_KICKOFF(kick_off, hw_cfg->ctl, dspp_buf[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); } void reg_dmav1_setup_dspp_gcv18(struct sde_hw_dspp *ctx, void *cfg) { struct drm_msm_pgc_lut *lut_cfg; struct sde_hw_reg_dma_ops *dma_ops; struct sde_reg_dma_kickoff_cfg kick_off; struct sde_hw_cp_cfg *hw_cfg = cfg; struct sde_reg_dma_setup_ops_cfg dma_write_cfg; int rc, i = 0; u32 reg; rc = reg_dma_dspp_check(ctx, cfg, GAMUT); if (rc) return; if (!hw_cfg->payload) { DRM_DEBUG_DRIVER("disable pgc feature\n"); SDE_REG_WRITE(&ctx->hw, ctx->cap->sblk->gc.base, 0); return; } if (hw_cfg->len != sizeof(struct drm_msm_pgc_lut)) { DRM_ERROR("invalid size of payload len %d exp %zd\n", hw_cfg->len, sizeof(struct drm_msm_pgc_lut)); return; } lut_cfg = hw_cfg->payload; dma_ops = sde_reg_dma_get_ops(); dma_ops->reset_reg_dma_buf(dspp_buf[GC][ctx->idx]); REG_DMA_INIT_OPS(dma_write_cfg, dspp_mapping[ctx->idx], GC, dspp_buf[GC][ctx->idx]); REG_DMA_SETUP_OPS(dma_write_cfg, 0, NULL, 0, HW_BLK_SELECT, 0, 0); rc = dma_ops->setup_payload(&dma_write_cfg); if (rc) { DRM_ERROR("write decode select failed ret %d\n", rc); return; } for (i = 0; i < GC_TBL_NUM; i++) { reg = 0; REG_DMA_SETUP_OPS(dma_write_cfg, ctx->cap->sblk->gc.base + GC_C0_INDEX_OFF + (i * sizeof(u32) * 2), ®, sizeof(reg), REG_SINGLE_WRITE, 0, 0); rc = dma_ops->setup_payload(&dma_write_cfg); if (rc) { DRM_ERROR("index init failed ret %d\n", rc); return; } REG_DMA_SETUP_OPS(dma_write_cfg, ctx->cap->sblk->gc.base + GC_C0_OFF + (i * sizeof(u32) * 2), lut_cfg->c0 + ARRAY_SIZE(lut_cfg->c0), PGC_TBL_LEN * sizeof(u32), REG_BLK_WRITE_INC, 0, 0); rc = dma_ops->setup_payload(&dma_write_cfg); if (rc) { DRM_ERROR("index init failed ret %d\n", rc); return; } } REG_DMA_SETUP_KICKOFF(kick_off, hw_cfg->ctl, dspp_buf[GC][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); return; } reg = GC_EN | ((lut_cfg->flags & PGC_8B_ROUND) ? GC_8B_ROUND_EN : 0); SDE_REG_WRITE(&ctx->hw, ctx->cap->sblk->gc.base + GC_LUT_SWAP_OFF, BIT(0)); SDE_REG_WRITE(&ctx->hw, ctx->cap->sblk->gc.base, reg); }