Skip to content

Commit 4259ff7

Browse files
Kalyan Thotarobclark
authored andcommitted
drm/msm/dpu: add support for pcc color block in dpu driver
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> Signed-off-by: Rob Clark <robdclark@chromium.org>
1 parent e47616d commit 4259ff7

File tree

4 files changed

+164
-4
lines changed

4 files changed

+164
-4
lines changed

drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
#include <linux/sort.h>
1010
#include <linux/debugfs.h>
1111
#include <linux/ktime.h>
12+
#include <linux/bits.h>
1213

1314
#include <drm/drm_crtc.h>
1415
#include <drm/drm_flip_work.h>
@@ -20,6 +21,7 @@
2021
#include "dpu_kms.h"
2122
#include "dpu_hw_lm.h"
2223
#include "dpu_hw_ctl.h"
24+
#include "dpu_hw_dspp.h"
2325
#include "dpu_crtc.h"
2426
#include "dpu_plane.h"
2527
#include "dpu_encoder.h"
@@ -40,6 +42,9 @@
4042
/* timeout in ms waiting for frame done */
4143
#define DPU_CRTC_FRAME_DONE_TIMEOUT_MS 60
4244

45+
#define CONVERT_S3_15(val) \
46+
(((((u64)val) & ~BIT_ULL(63)) >> 17) & GENMASK_ULL(17, 0))
47+
4348
static struct dpu_kms *_dpu_crtc_get_kms(struct drm_crtc *crtc)
4449
{
4550
struct msm_drm_private *priv = crtc->dev->dev_private;
@@ -420,6 +425,74 @@ static void _dpu_crtc_setup_lm_bounds(struct drm_crtc *crtc,
420425
drm_mode_debug_printmodeline(adj_mode);
421426
}
422427

428+
static void _dpu_crtc_get_pcc_coeff(struct drm_crtc_state *state,
429+
struct dpu_hw_pcc_cfg *cfg)
430+
{
431+
struct drm_color_ctm *ctm;
432+
433+
memset(cfg, 0, sizeof(struct dpu_hw_pcc_cfg));
434+
435+
ctm = (struct drm_color_ctm *)state->ctm->data;
436+
437+
if (!ctm)
438+
return;
439+
440+
cfg->r.r = CONVERT_S3_15(ctm->matrix[0]);
441+
cfg->g.r = CONVERT_S3_15(ctm->matrix[1]);
442+
cfg->b.r = CONVERT_S3_15(ctm->matrix[2]);
443+
444+
cfg->r.g = CONVERT_S3_15(ctm->matrix[3]);
445+
cfg->g.g = CONVERT_S3_15(ctm->matrix[4]);
446+
cfg->b.g = CONVERT_S3_15(ctm->matrix[5]);
447+
448+
cfg->r.b = CONVERT_S3_15(ctm->matrix[6]);
449+
cfg->g.b = CONVERT_S3_15(ctm->matrix[7]);
450+
cfg->b.b = CONVERT_S3_15(ctm->matrix[8]);
451+
}
452+
453+
static void _dpu_crtc_setup_cp_blocks(struct drm_crtc *crtc)
454+
{
455+
struct drm_crtc_state *state = crtc->state;
456+
struct dpu_crtc_state *cstate = to_dpu_crtc_state(crtc->state);
457+
struct dpu_crtc_mixer *mixer = cstate->mixers;
458+
struct dpu_hw_pcc_cfg cfg;
459+
struct dpu_hw_ctl *ctl;
460+
struct dpu_hw_mixer *lm;
461+
struct dpu_hw_dspp *dspp;
462+
int i;
463+
464+
465+
if (!state->color_mgmt_changed)
466+
return;
467+
468+
for (i = 0; i < cstate->num_mixers; i++) {
469+
ctl = mixer[i].lm_ctl;
470+
lm = mixer[i].hw_lm;
471+
dspp = mixer[i].hw_dspp;
472+
473+
if (!dspp || !dspp->ops.setup_pcc)
474+
continue;
475+
476+
if (!state->ctm) {
477+
dspp->ops.setup_pcc(dspp, NULL);
478+
} else {
479+
_dpu_crtc_get_pcc_coeff(state, &cfg);
480+
dspp->ops.setup_pcc(dspp, &cfg);
481+
}
482+
483+
mixer[i].flush_mask |= ctl->ops.get_bitmask_dspp(ctl,
484+
mixer[i].hw_dspp->idx);
485+
486+
/* stage config flush mask */
487+
ctl->ops.update_pending_flush(ctl, mixer[i].flush_mask);
488+
489+
DPU_DEBUG("lm %d, ctl %d, flush mask 0x%x\n",
490+
mixer[i].hw_lm->idx - DSPP_0,
491+
ctl->idx - CTL_0,
492+
mixer[i].flush_mask);
493+
}
494+
}
495+
423496
static void dpu_crtc_atomic_begin(struct drm_crtc *crtc,
424497
struct drm_crtc_state *old_state)
425498
{
@@ -471,6 +544,8 @@ static void dpu_crtc_atomic_begin(struct drm_crtc *crtc,
471544

472545
_dpu_crtc_blend_setup(crtc);
473546

547+
_dpu_crtc_setup_cp_blocks(crtc);
548+
474549
/*
475550
* PP_DONE irq is only used by command mode for now.
476551
* It is better to request pending before FLUSH and START trigger
@@ -1301,6 +1376,8 @@ struct drm_crtc *dpu_crtc_init(struct drm_device *dev, struct drm_plane *plane,
13011376

13021377
drm_crtc_helper_add(crtc, &dpu_crtc_helper_funcs);
13031378

1379+
drm_crtc_enable_color_mgmt(crtc, 0, true, 0);
1380+
13041381
/* save user friendly CRTC name for later */
13051382
snprintf(dpu_crtc->name, DPU_CRTC_NAME_SIZE, "crtc%u", crtc->base.id);
13061383

drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@
4141
#define PINGPONG_SDM845_SPLIT_MASK \
4242
(PINGPONG_SDM845_MASK | BIT(DPU_PINGPONG_TE2))
4343

44-
#define DSPP_SC7180_MASK 0
44+
#define DSPP_SC7180_MASK BIT(DPU_DSPP_PCC)
4545

4646
#define DEFAULT_PIXEL_RAM_SIZE (50 * 1024)
4747
#define DEFAULT_DPU_LINE_WIDTH 2048
@@ -339,12 +339,17 @@ static const struct dpu_lm_cfg sc7180_lm[] = {
339339
/*************************************************************
340340
* DSPP sub blocks config
341341
*************************************************************/
342+
static const struct dpu_dspp_sub_blks sc7180_dspp_sblk = {
343+
.pcc = {.id = DPU_DSPP_PCC, .base = 0x1700,
344+
.len = 0x90, .version = 0x10000},
345+
};
346+
342347
#define DSPP_BLK(_name, _id, _base) \
343348
{\
344349
.name = _name, .id = _id, \
345350
.base = _base, .len = 0x1800, \
346351
.features = DSPP_SC7180_MASK, \
347-
.sblk = NULL, \
352+
.sblk = &sc7180_dspp_sblk \
348353
}
349354

350355
static const struct dpu_dspp_cfg sc7180_dspp[] = {

drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dspp.c

Lines changed: 48 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,57 @@
99
#include "dpu_kms.h"
1010

1111

12+
/* DSPP_PCC */
13+
#define PCC_EN BIT(0)
14+
#define PCC_DIS 0
15+
#define PCC_RED_R_OFF 0x10
16+
#define PCC_RED_G_OFF 0x1C
17+
#define PCC_RED_B_OFF 0x28
18+
#define PCC_GREEN_R_OFF 0x14
19+
#define PCC_GREEN_G_OFF 0x20
20+
#define PCC_GREEN_B_OFF 0x2C
21+
#define PCC_BLUE_R_OFF 0x18
22+
#define PCC_BLUE_G_OFF 0x24
23+
#define PCC_BLUE_B_OFF 0x30
24+
25+
void dpu_setup_dspp_pcc(struct dpu_hw_dspp *ctx,
26+
struct dpu_hw_pcc_cfg *cfg)
27+
{
28+
29+
u32 base = ctx->cap->sblk->pcc.base;
30+
31+
if (!ctx || !base) {
32+
DRM_ERROR("invalid ctx %pK pcc base 0x%x\n", ctx, base);
33+
return;
34+
}
35+
36+
if (!cfg) {
37+
DRM_DEBUG_DRIVER("disable pcc feature\n");
38+
DPU_REG_WRITE(&ctx->hw, base, PCC_DIS);
39+
return;
40+
}
41+
42+
DPU_REG_WRITE(&ctx->hw, base + PCC_RED_R_OFF, cfg->r.r);
43+
DPU_REG_WRITE(&ctx->hw, base + PCC_RED_G_OFF, cfg->r.g);
44+
DPU_REG_WRITE(&ctx->hw, base + PCC_RED_B_OFF, cfg->r.b);
45+
46+
DPU_REG_WRITE(&ctx->hw, base + PCC_GREEN_R_OFF, cfg->g.r);
47+
DPU_REG_WRITE(&ctx->hw, base + PCC_GREEN_G_OFF, cfg->g.g);
48+
DPU_REG_WRITE(&ctx->hw, base + PCC_GREEN_B_OFF, cfg->g.b);
49+
50+
DPU_REG_WRITE(&ctx->hw, base + PCC_BLUE_R_OFF, cfg->b.r);
51+
DPU_REG_WRITE(&ctx->hw, base + PCC_BLUE_G_OFF, cfg->b.g);
52+
DPU_REG_WRITE(&ctx->hw, base + PCC_BLUE_B_OFF, cfg->b.b);
53+
54+
DPU_REG_WRITE(&ctx->hw, base, PCC_EN);
55+
}
56+
1257
static void _setup_dspp_ops(struct dpu_hw_dspp *c,
1358
unsigned long features)
1459
{
15-
return;
60+
if (test_bit(DPU_DSPP_PCC, &features) &&
61+
IS_SC7180_TARGET(c->hw.hwversion))
62+
c->ops.setup_pcc = dpu_setup_dspp_pcc;
1663
}
1764

1865
static const struct dpu_dspp_cfg *_dspp_offset(enum dpu_dspp dspp,

drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dspp.h

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,14 +9,45 @@
99

1010
struct dpu_hw_dspp;
1111

12+
/**
13+
* struct dpu_hw_pcc_coeff - PCC coefficient structure for each color
14+
* component.
15+
* @r: red coefficient.
16+
* @g: green coefficient.
17+
* @b: blue coefficient.
18+
*/
19+
20+
struct dpu_hw_pcc_coeff {
21+
__u32 r;
22+
__u32 g;
23+
__u32 b;
24+
};
25+
26+
/**
27+
* struct dpu_hw_pcc - pcc feature structure
28+
* @r: red coefficients.
29+
* @g: green coefficients.
30+
* @b: blue coefficients.
31+
*/
32+
struct dpu_hw_pcc_cfg {
33+
struct dpu_hw_pcc_coeff r;
34+
struct dpu_hw_pcc_coeff g;
35+
struct dpu_hw_pcc_coeff b;
36+
};
37+
1238
/**
1339
* struct dpu_hw_dspp_ops - interface to the dspp hardware driver functions
1440
* Caller must call the init function to get the dspp context for each dspp
1541
* Assumption is these functions will be called after clocks are enabled
1642
*/
1743
struct dpu_hw_dspp_ops {
44+
/**
45+
* setup_pcc - setup dspp pcc
46+
* @ctx: Pointer to dspp context
47+
* @cfg: Pointer to configuration
48+
*/
49+
void (*setup_pcc)(struct dpu_hw_dspp *ctx, struct dpu_hw_pcc_cfg *cfg);
1850

19-
void (*dummy)(struct dpu_hw_dspp *ctx);
2051
};
2152

2253
/**

0 commit comments

Comments
 (0)