diff options
| author | Mihail Atanassov <mihail.atanassov@arm.com> | 2017-02-13 07:49:03 -0500 |
|---|---|---|
| committer | Liviu Dudau <Liviu.Dudau@arm.com> | 2017-04-24 05:45:34 -0400 |
| commit | 6954f24588ebddc2e3c840103f02d1fe7e65a2d6 (patch) | |
| tree | 2699bd1b9e39adc819d43307f67bc6c56605315a | |
| parent | 02725d31371b66b97bc58b2a81f0c6dc40970598 (diff) | |
drm: mali-dp: Add CTM support
All DPs have a COLORADJ matrix which is applied prior to output gamma.
Attach that to the CTM property. Also, ensure the input CTM's coefficients
can fit in the DP registers' Q3.12 format.
Signed-off-by: Mihail Atanassov <mihail.atanassov@arm.com>
Signed-off-by: Liviu Dudau <Liviu.Dudau@arm.com>
| -rw-r--r-- | drivers/gpu/drm/arm/malidp_crtc.c | 64 | ||||
| -rw-r--r-- | drivers/gpu/drm/arm/malidp_drv.c | 35 | ||||
| -rw-r--r-- | drivers/gpu/drm/arm/malidp_drv.h | 1 | ||||
| -rw-r--r-- | drivers/gpu/drm/arm/malidp_hw.h | 1 | ||||
| -rw-r--r-- | drivers/gpu/drm/arm/malidp_regs.h | 1 |
5 files changed, 98 insertions, 4 deletions
diff --git a/drivers/gpu/drm/arm/malidp_crtc.c b/drivers/gpu/drm/arm/malidp_crtc.c index 27ab09459b9d..8f2e1ae51ba0 100644 --- a/drivers/gpu/drm/arm/malidp_crtc.c +++ b/drivers/gpu/drm/arm/malidp_crtc.c | |||
| @@ -195,6 +195,58 @@ static int malidp_crtc_atomic_check_gamma(struct drm_crtc *crtc, | |||
| 195 | return 0; | 195 | return 0; |
| 196 | } | 196 | } |
| 197 | 197 | ||
| 198 | /* | ||
| 199 | * Check if there is a new CTM and if it contains valid input. Valid here means | ||
| 200 | * that the number is inside the representable range for a Q3.12 number, | ||
| 201 | * excluding truncating the fractional part of the input data. | ||
| 202 | * | ||
| 203 | * The COLORADJ registers can be changed atomically. | ||
| 204 | */ | ||
| 205 | static int malidp_crtc_atomic_check_ctm(struct drm_crtc *crtc, | ||
| 206 | struct drm_crtc_state *state) | ||
| 207 | { | ||
| 208 | struct malidp_crtc_state *mc = to_malidp_crtc_state(state); | ||
| 209 | struct drm_color_ctm *ctm; | ||
| 210 | int i; | ||
| 211 | |||
| 212 | if (!state->color_mgmt_changed) | ||
| 213 | return 0; | ||
| 214 | |||
| 215 | if (!state->ctm) | ||
| 216 | return 0; | ||
| 217 | |||
| 218 | if (crtc->state->ctm && (crtc->state->ctm->base.id == | ||
| 219 | state->ctm->base.id)) | ||
| 220 | return 0; | ||
| 221 | |||
| 222 | /* | ||
| 223 | * The size of the ctm is checked in | ||
| 224 | * drm_atomic_replace_property_blob_from_id. | ||
| 225 | */ | ||
| 226 | ctm = (struct drm_color_ctm *)state->ctm->data; | ||
| 227 | for (i = 0; i < ARRAY_SIZE(ctm->matrix); ++i) { | ||
| 228 | /* Convert from S31.32 to Q3.12. */ | ||
| 229 | s64 val = ctm->matrix[i]; | ||
| 230 | u32 mag = ((((u64)val) & ~BIT_ULL(63)) >> 20) & | ||
| 231 | GENMASK_ULL(14, 0); | ||
| 232 | |||
| 233 | /* | ||
| 234 | * Convert to 2s complement and check the destination's top bit | ||
| 235 | * for overflow. NB: Can't check before converting or it'd | ||
| 236 | * incorrectly reject the case: | ||
| 237 | * sign == 1 | ||
| 238 | * mag == 0x2000 | ||
| 239 | */ | ||
| 240 | if (val & BIT_ULL(63)) | ||
| 241 | mag = ~mag + 1; | ||
| 242 | if (!!(val & BIT_ULL(63)) != !!(mag & BIT(14))) | ||
| 243 | return -EINVAL; | ||
| 244 | mc->coloradj_coeffs[i] = mag; | ||
| 245 | } | ||
| 246 | |||
| 247 | return 0; | ||
| 248 | } | ||
| 249 | |||
| 198 | static int malidp_crtc_atomic_check(struct drm_crtc *crtc, | 250 | static int malidp_crtc_atomic_check(struct drm_crtc *crtc, |
| 199 | struct drm_crtc_state *state) | 251 | struct drm_crtc_state *state) |
| 200 | { | 252 | { |
| @@ -204,6 +256,7 @@ static int malidp_crtc_atomic_check(struct drm_crtc *crtc, | |||
| 204 | const struct drm_plane_state *pstate; | 256 | const struct drm_plane_state *pstate; |
| 205 | u32 rot_mem_free, rot_mem_usable; | 257 | u32 rot_mem_free, rot_mem_usable; |
| 206 | int rotated_planes = 0; | 258 | int rotated_planes = 0; |
| 259 | int ret; | ||
| 207 | 260 | ||
| 208 | /* | 261 | /* |
| 209 | * check if there is enough rotation memory available for planes | 262 | * check if there is enough rotation memory available for planes |
| @@ -270,7 +323,10 @@ static int malidp_crtc_atomic_check(struct drm_crtc *crtc, | |||
| 270 | } | 323 | } |
| 271 | } | 324 | } |
| 272 | 325 | ||
| 273 | return malidp_crtc_atomic_check_gamma(crtc, state); | 326 | ret = malidp_crtc_atomic_check_gamma(crtc, state); |
| 327 | ret = ret ? ret : malidp_crtc_atomic_check_ctm(crtc, state); | ||
| 328 | |||
| 329 | return ret; | ||
| 274 | } | 330 | } |
| 275 | 331 | ||
| 276 | static const struct drm_crtc_helper_funcs malidp_crtc_helper_funcs = { | 332 | static const struct drm_crtc_helper_funcs malidp_crtc_helper_funcs = { |
| @@ -295,6 +351,8 @@ static struct drm_crtc_state *malidp_crtc_duplicate_state(struct drm_crtc *crtc) | |||
| 295 | __drm_atomic_helper_crtc_duplicate_state(crtc, &state->base); | 351 | __drm_atomic_helper_crtc_duplicate_state(crtc, &state->base); |
| 296 | memcpy(state->gamma_coeffs, old_state->gamma_coeffs, | 352 | memcpy(state->gamma_coeffs, old_state->gamma_coeffs, |
| 297 | sizeof(state->gamma_coeffs)); | 353 | sizeof(state->gamma_coeffs)); |
| 354 | memcpy(state->coloradj_coeffs, old_state->coloradj_coeffs, | ||
| 355 | sizeof(state->coloradj_coeffs)); | ||
| 298 | 356 | ||
| 299 | return &state->base; | 357 | return &state->base; |
| 300 | } | 358 | } |
| @@ -392,8 +450,8 @@ int malidp_crtc_init(struct drm_device *drm) | |||
| 392 | 450 | ||
| 393 | drm_crtc_helper_add(&malidp->crtc, &malidp_crtc_helper_funcs); | 451 | drm_crtc_helper_add(&malidp->crtc, &malidp_crtc_helper_funcs); |
| 394 | drm_mode_crtc_set_gamma_size(&malidp->crtc, MALIDP_GAMMA_LUT_SIZE); | 452 | drm_mode_crtc_set_gamma_size(&malidp->crtc, MALIDP_GAMMA_LUT_SIZE); |
| 395 | /* No inverse-gamma and color adjustments yet. */ | 453 | /* No inverse-gamma: it is per-plane */ |
| 396 | drm_crtc_enable_color_mgmt(&malidp->crtc, 0, false, MALIDP_GAMMA_LUT_SIZE); | 454 | drm_crtc_enable_color_mgmt(&malidp->crtc, 0, true, MALIDP_GAMMA_LUT_SIZE); |
| 397 | 455 | ||
| 398 | return 0; | 456 | return 0; |
| 399 | 457 | ||
diff --git a/drivers/gpu/drm/arm/malidp_drv.c b/drivers/gpu/drm/arm/malidp_drv.c index 1eb6bbc5118a..eae41e26b819 100644 --- a/drivers/gpu/drm/arm/malidp_drv.c +++ b/drivers/gpu/drm/arm/malidp_drv.c | |||
| @@ -79,6 +79,37 @@ static void malidp_atomic_commit_update_gamma(struct drm_crtc *crtc, | |||
| 79 | } | 79 | } |
| 80 | } | 80 | } |
| 81 | 81 | ||
| 82 | static | ||
| 83 | void malidp_atomic_commit_update_coloradj(struct drm_crtc *crtc, | ||
| 84 | struct drm_crtc_state *old_state) | ||
| 85 | { | ||
| 86 | struct malidp_drm *malidp = crtc_to_malidp_device(crtc); | ||
| 87 | struct malidp_hw_device *hwdev = malidp->dev; | ||
| 88 | int i; | ||
| 89 | |||
| 90 | if (!crtc->state->color_mgmt_changed) | ||
| 91 | return; | ||
| 92 | |||
| 93 | if (!crtc->state->ctm) { | ||
| 94 | malidp_hw_clearbits(hwdev, MALIDP_DISP_FUNC_CADJ, | ||
| 95 | MALIDP_DE_DISPLAY_FUNC); | ||
| 96 | } else { | ||
| 97 | struct malidp_crtc_state *mc = | ||
| 98 | to_malidp_crtc_state(crtc->state); | ||
| 99 | |||
| 100 | if (!old_state->ctm || (crtc->state->ctm->base.id != | ||
| 101 | old_state->ctm->base.id)) | ||
| 102 | for (i = 0; i < MALIDP_COLORADJ_NUM_COEFFS; ++i) | ||
| 103 | malidp_hw_write(hwdev, | ||
| 104 | mc->coloradj_coeffs[i], | ||
| 105 | hwdev->map.coeffs_base + | ||
| 106 | MALIDP_COLOR_ADJ_COEF + 4 * i); | ||
| 107 | |||
| 108 | malidp_hw_setbits(hwdev, MALIDP_DISP_FUNC_CADJ, | ||
| 109 | MALIDP_DE_DISPLAY_FUNC); | ||
| 110 | } | ||
| 111 | } | ||
| 112 | |||
| 82 | /* | 113 | /* |
| 83 | * set the "config valid" bit and wait until the hardware acts on it | 114 | * set the "config valid" bit and wait until the hardware acts on it |
| 84 | */ | 115 | */ |
| @@ -145,8 +176,10 @@ static void malidp_atomic_commit_tail(struct drm_atomic_state *state) | |||
| 145 | 176 | ||
| 146 | drm_atomic_helper_commit_modeset_disables(drm, state); | 177 | drm_atomic_helper_commit_modeset_disables(drm, state); |
| 147 | 178 | ||
| 148 | for_each_crtc_in_state(state, crtc, old_crtc_state, i) | 179 | for_each_crtc_in_state(state, crtc, old_crtc_state, i) { |
| 149 | malidp_atomic_commit_update_gamma(crtc, old_crtc_state); | 180 | malidp_atomic_commit_update_gamma(crtc, old_crtc_state); |
| 181 | malidp_atomic_commit_update_coloradj(crtc, old_crtc_state); | ||
| 182 | } | ||
| 150 | 183 | ||
| 151 | drm_atomic_helper_commit_planes(drm, state, 0); | 184 | drm_atomic_helper_commit_planes(drm, state, 0); |
| 152 | 185 | ||
diff --git a/drivers/gpu/drm/arm/malidp_drv.h b/drivers/gpu/drm/arm/malidp_drv.h index f5abd8bfbd2b..e1c784dcdd92 100644 --- a/drivers/gpu/drm/arm/malidp_drv.h +++ b/drivers/gpu/drm/arm/malidp_drv.h | |||
| @@ -51,6 +51,7 @@ struct malidp_plane_state { | |||
| 51 | struct malidp_crtc_state { | 51 | struct malidp_crtc_state { |
| 52 | struct drm_crtc_state base; | 52 | struct drm_crtc_state base; |
| 53 | u32 gamma_coeffs[MALIDP_COEFFTAB_NUM_COEFFS]; | 53 | u32 gamma_coeffs[MALIDP_COEFFTAB_NUM_COEFFS]; |
| 54 | u32 coloradj_coeffs[MALIDP_COLORADJ_NUM_COEFFS]; | ||
| 54 | }; | 55 | }; |
| 55 | 56 | ||
| 56 | #define to_malidp_crtc_state(x) container_of(x, struct malidp_crtc_state, base) | 57 | #define to_malidp_crtc_state(x) container_of(x, struct malidp_crtc_state, base) |
diff --git a/drivers/gpu/drm/arm/malidp_hw.h b/drivers/gpu/drm/arm/malidp_hw.h index c2df6b6e7645..470fe71724a3 100644 --- a/drivers/gpu/drm/arm/malidp_hw.h +++ b/drivers/gpu/drm/arm/malidp_hw.h | |||
| @@ -259,6 +259,7 @@ static inline bool malidp_hw_pitch_valid(struct malidp_hw_device *hwdev, | |||
| 259 | #define MALIDP_BGND_COLOR_G 0x000 | 259 | #define MALIDP_BGND_COLOR_G 0x000 |
| 260 | #define MALIDP_BGND_COLOR_B 0x000 | 260 | #define MALIDP_BGND_COLOR_B 0x000 |
| 261 | 261 | ||
| 262 | #define MALIDP_COLORADJ_NUM_COEFFS 12 | ||
| 262 | #define MALIDP_COEFFTAB_NUM_COEFFS 64 | 263 | #define MALIDP_COEFFTAB_NUM_COEFFS 64 |
| 263 | 264 | ||
| 264 | #define MALIDP_GAMMA_LUT_SIZE 4096 | 265 | #define MALIDP_GAMMA_LUT_SIZE 4096 |
diff --git a/drivers/gpu/drm/arm/malidp_regs.h b/drivers/gpu/drm/arm/malidp_regs.h index 28252c5b31b5..4bf338d4172e 100644 --- a/drivers/gpu/drm/arm/malidp_regs.h +++ b/drivers/gpu/drm/arm/malidp_regs.h | |||
| @@ -64,6 +64,7 @@ | |||
| 64 | /* bit masks that are common between products */ | 64 | /* bit masks that are common between products */ |
| 65 | #define MALIDP_CFG_VALID (1 << 0) | 65 | #define MALIDP_CFG_VALID (1 << 0) |
| 66 | #define MALIDP_DISP_FUNC_GAMMA (1 << 0) | 66 | #define MALIDP_DISP_FUNC_GAMMA (1 << 0) |
| 67 | #define MALIDP_DISP_FUNC_CADJ (1 << 4) | ||
| 67 | #define MALIDP_DISP_FUNC_ILACED (1 << 8) | 68 | #define MALIDP_DISP_FUNC_ILACED (1 << 8) |
| 68 | 69 | ||
| 69 | /* register offsets for IRQ management */ | 70 | /* register offsets for IRQ management */ |
