On Wed, Mar 25, 2020 at 1:17 AM Kalyan Thota kalyan_t@codeaurora.org wrote:
This change adds support for color correction sub block for SC7180 device.
Signed-off-by: Kalyan Thota kalyan_t@codeaurora.org
Tested-by: Fritz Koenig frkoenig@google.com
drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c | 77 ++++++++++++++++++++++++++ drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c | 9 ++- drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dspp.c | 49 +++++++++++++++- drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dspp.h | 33 ++++++++++- 4 files changed, 164 insertions(+), 4 deletions(-)
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c index bf51341..156a997 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c @@ -9,6 +9,7 @@ #include <linux/sort.h> #include <linux/debugfs.h> #include <linux/ktime.h> +#include <linux/bits.h>
#include <drm/drm_crtc.h> #include <drm/drm_flip_work.h> @@ -20,6 +21,7 @@ #include "dpu_kms.h" #include "dpu_hw_lm.h" #include "dpu_hw_ctl.h" +#include "dpu_hw_dspp.h" #include "dpu_crtc.h" #include "dpu_plane.h" #include "dpu_encoder.h" @@ -40,6 +42,9 @@ /* timeout in ms waiting for frame done */ #define DPU_CRTC_FRAME_DONE_TIMEOUT_MS 60
+#define CONVERT_S3_15(val) \
(((((u64)val) & ~BIT_ULL(63)) >> 17) & GENMASK_ULL(17, 0))
static struct dpu_kms *_dpu_crtc_get_kms(struct drm_crtc *crtc) { struct msm_drm_private *priv = crtc->dev->dev_private; @@ -422,6 +427,74 @@ static void _dpu_crtc_setup_lm_bounds(struct drm_crtc *crtc, drm_mode_debug_printmodeline(adj_mode); }
+static void _dpu_crtc_get_pcc_coeff(struct drm_crtc_state *state,
struct dpu_hw_pcc_cfg *cfg)
+{
struct drm_color_ctm *ctm;
memset(cfg, 0, sizeof(struct dpu_hw_pcc_cfg));
ctm = (struct drm_color_ctm *)state->ctm->data;
if (!ctm)
return;
cfg->r.r = CONVERT_S3_15(ctm->matrix[0]);
cfg->g.r = CONVERT_S3_15(ctm->matrix[1]);
cfg->b.r = CONVERT_S3_15(ctm->matrix[2]);
cfg->r.g = CONVERT_S3_15(ctm->matrix[3]);
cfg->g.g = CONVERT_S3_15(ctm->matrix[4]);
cfg->b.g = CONVERT_S3_15(ctm->matrix[5]);
cfg->r.b = CONVERT_S3_15(ctm->matrix[6]);
cfg->g.b = CONVERT_S3_15(ctm->matrix[7]);
cfg->b.b = CONVERT_S3_15(ctm->matrix[8]);
+}
+static void _dpu_crtc_setup_cp_blocks(struct drm_crtc *crtc) +{
struct drm_crtc_state *state = crtc->state;
struct dpu_crtc_state *cstate = to_dpu_crtc_state(crtc->state);
struct dpu_crtc_mixer *mixer = cstate->mixers;
struct dpu_hw_pcc_cfg cfg;
struct dpu_hw_ctl *ctl;
struct dpu_hw_mixer *lm;
struct dpu_hw_dspp *dspp;
int i;
if (!state->color_mgmt_changed)
return;
for (i = 0; i < cstate->num_mixers; i++) {
ctl = mixer[i].lm_ctl;
lm = mixer[i].hw_lm;
dspp = mixer[i].hw_dspp;
if (!dspp || !dspp->ops.setup_pcc)
continue;
if (!state->ctm) {
dspp->ops.setup_pcc(dspp, NULL);
} else {
_dpu_crtc_get_pcc_coeff(state, &cfg);
dspp->ops.setup_pcc(dspp, &cfg);
}
mixer[i].flush_mask |= ctl->ops.get_bitmask_dspp(ctl,
mixer[i].hw_dspp->idx);
/* stage config flush mask */
ctl->ops.update_pending_flush(ctl, mixer[i].flush_mask);
DPU_DEBUG("lm %d, ctl %d, flush mask 0x%x\n",
mixer[i].hw_lm->idx - DSPP_0,
ctl->idx - CTL_0,
mixer[i].flush_mask);
}
+}
static void dpu_crtc_atomic_begin(struct drm_crtc *crtc, struct drm_crtc_state *old_state) { @@ -475,6 +548,8 @@ static void dpu_crtc_atomic_begin(struct drm_crtc *crtc,
_dpu_crtc_blend_setup(crtc);
_dpu_crtc_setup_cp_blocks(crtc);
/* * PP_DONE irq is only used by command mode for now. * It is better to request pending before FLUSH and START trigger
@@ -1317,6 +1392,8 @@ struct drm_crtc *dpu_crtc_init(struct drm_device *dev, struct drm_plane *plane,
drm_crtc_helper_add(crtc, &dpu_crtc_helper_funcs);
drm_crtc_enable_color_mgmt(crtc, 0, true, 0);
/* save user friendly CRTC name for later */ snprintf(dpu_crtc->name, DPU_CRTC_NAME_SIZE, "crtc%u", crtc->base.id);
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c index 19d065a..731b4fb 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c @@ -41,7 +41,7 @@ #define PINGPONG_SDM845_SPLIT_MASK \ (PINGPONG_SDM845_MASK | BIT(DPU_PINGPONG_TE2))
-#define DSPP_SC7180_MASK 0 +#define DSPP_SC7180_MASK BIT(DPU_DSPP_PCC)
#define DEFAULT_PIXEL_RAM_SIZE (50 * 1024) #define DEFAULT_DPU_LINE_WIDTH 2048 @@ -339,12 +339,17 @@ /*************************************************************
- DSPP sub blocks config
*************************************************************/ +static const struct dpu_dspp_sub_blks sc7180_dspp_sblk = {
.pcc = {.id = DPU_DSPP_PCC, .base = 0x1700,
.len = 0x90, .version = 0x10000},
+};
#define DSPP_BLK(_name, _id, _base) \ {\ .name = _name, .id = _id, \ .base = _base, .len = 0x1800, \ .features = DSPP_SC7180_MASK, \
.sblk = NULL, \
.sblk = &sc7180_dspp_sblk \ }
static const struct dpu_dspp_cfg sc7180_dspp[] = { diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dspp.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dspp.c index 75c82e9..b5189ce 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dspp.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dspp.c @@ -9,10 +9,57 @@ #include "dpu_kms.h"
+/* DSPP_PCC */ +#define PCC_EN BIT(0) +#define PCC_DIS 0 +#define PCC_RED_R_OFF 0x10 +#define PCC_RED_G_OFF 0x1C +#define PCC_RED_B_OFF 0x28 +#define PCC_GREEN_R_OFF 0x14 +#define PCC_GREEN_G_OFF 0x20 +#define PCC_GREEN_B_OFF 0x2C +#define PCC_BLUE_R_OFF 0x18 +#define PCC_BLUE_G_OFF 0x24 +#define PCC_BLUE_B_OFF 0x30
+void dpu_setup_dspp_pcc(struct dpu_hw_dspp *ctx,
struct dpu_hw_pcc_cfg *cfg)
+{
u32 base = ctx->cap->sblk->pcc.base;
if (!ctx || !base) {
DRM_ERROR("invalid ctx %pK pcc base 0x%x\n", ctx, base);
return;
}
if (!cfg) {
DRM_DEBUG_DRIVER("disable pcc feature\n");
DPU_REG_WRITE(&ctx->hw, base, PCC_DIS);
return;
}
DPU_REG_WRITE(&ctx->hw, base + PCC_RED_R_OFF, cfg->r.r);
DPU_REG_WRITE(&ctx->hw, base + PCC_RED_G_OFF, cfg->r.g);
DPU_REG_WRITE(&ctx->hw, base + PCC_RED_B_OFF, cfg->r.b);
DPU_REG_WRITE(&ctx->hw, base + PCC_GREEN_R_OFF, cfg->g.r);
DPU_REG_WRITE(&ctx->hw, base + PCC_GREEN_G_OFF, cfg->g.g);
DPU_REG_WRITE(&ctx->hw, base + PCC_GREEN_B_OFF, cfg->g.b);
DPU_REG_WRITE(&ctx->hw, base + PCC_BLUE_R_OFF, cfg->b.r);
DPU_REG_WRITE(&ctx->hw, base + PCC_BLUE_G_OFF, cfg->b.g);
DPU_REG_WRITE(&ctx->hw, base + PCC_BLUE_B_OFF, cfg->b.b);
DPU_REG_WRITE(&ctx->hw, base, PCC_EN);
+}
static void _setup_dspp_ops(struct dpu_hw_dspp *c, unsigned long features) {
return;
if (test_bit(DPU_DSPP_PCC, &features) &&
IS_SC7180_TARGET(c->hw.hwversion))
c->ops.setup_pcc = dpu_setup_dspp_pcc;
}
static const struct dpu_dspp_cfg *_dspp_offset(enum dpu_dspp dspp, diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dspp.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dspp.h index 09807ea..7fa189c 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dspp.h +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dspp.h @@ -10,13 +10,44 @@ struct dpu_hw_dspp;
/**
- struct dpu_hw_pcc_coeff - PCC coefficient structure for each color
component.
- @r: red coefficient.
- @g: green coefficient.
- @b: blue coefficient.
- */
+struct dpu_hw_pcc_coeff {
__u32 r;
__u32 g;
__u32 b;
+};
+/**
- struct dpu_hw_pcc - pcc feature structure
- @r: red coefficients.
- @g: green coefficients.
- @b: blue coefficients.
- */
+struct dpu_hw_pcc_cfg {
struct dpu_hw_pcc_coeff r;
struct dpu_hw_pcc_coeff g;
struct dpu_hw_pcc_coeff b;
+};
+/**
- struct dpu_hw_dspp_ops - interface to the dspp hardware driver functions
- Caller must call the init function to get the dspp context for each dspp
- Assumption is these functions will be called after clocks are enabled
*/ struct dpu_hw_dspp_ops {
/**
* setup_pcc - setup dspp pcc
* @ctx: Pointer to dspp context
* @cfg: Pointer to configuration
*/
void (*setup_pcc)(struct dpu_hw_dspp *ctx, struct dpu_hw_pcc_cfg *cfg);
void (*dummy)(struct dpu_hw_dspp *ctx);
};
/**
1.9.1
dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel