aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMihail Atanassov <mihail.atanassov@arm.com>2017-02-13 07:49:03 -0500
committerLiviu Dudau <Liviu.Dudau@arm.com>2017-04-24 05:45:34 -0400
commit6954f24588ebddc2e3c840103f02d1fe7e65a2d6 (patch)
tree2699bd1b9e39adc819d43307f67bc6c56605315a
parent02725d31371b66b97bc58b2a81f0c6dc40970598 (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.c64
-rw-r--r--drivers/gpu/drm/arm/malidp_drv.c35
-rw-r--r--drivers/gpu/drm/arm/malidp_drv.h1
-rw-r--r--drivers/gpu/drm/arm/malidp_hw.h1
-rw-r--r--drivers/gpu/drm/arm/malidp_regs.h1
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 */
205static 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
198static int malidp_crtc_atomic_check(struct drm_crtc *crtc, 250static 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
276static const struct drm_crtc_helper_funcs malidp_crtc_helper_funcs = { 332static 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
82static
83void 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 {
51struct malidp_crtc_state { 51struct 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 */