aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMihail Atanassov <mihail.atanassov@arm.com>2017-02-13 10:09:01 -0500
committerLiviu Dudau <Liviu.Dudau@arm.com>2017-04-24 08:28:09 -0400
commitc2e7f82d336a451ebb904b8bf9a5a558cf16c39b (patch)
tree7a589b812cf505c31464b2e6628b1eb846600aad
parent0274e6a0ba9a4994a449fcd3483ef530027e152f (diff)
drm: mali-dp: Check the mclk rate and allow up/down scaling
When downscaling, mclk needs to be sufficiently higher than pxlclk in order to be able to fetch the higher-resolution data and produce output pixels. When not scaling, or when upscaling, mclk can be equal to pxlclk. Since the driver doesn't control mclk, just ensure that the requirement is satisfied with the current clock rate. 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.c23
-rw-r--r--drivers/gpu/drm/arm/malidp_hw.c70
-rw-r--r--drivers/gpu/drm/arm/malidp_hw.h4
3 files changed, 85 insertions, 12 deletions
diff --git a/drivers/gpu/drm/arm/malidp_crtc.c b/drivers/gpu/drm/arm/malidp_crtc.c
index b0f0365efd23..19f1f3b34691 100644
--- a/drivers/gpu/drm/arm/malidp_crtc.c
+++ b/drivers/gpu/drm/arm/malidp_crtc.c
@@ -36,13 +36,6 @@ static bool malidp_crtc_mode_fixup(struct drm_crtc *crtc,
36 long rate, req_rate = mode->crtc_clock * 1000; 36 long rate, req_rate = mode->crtc_clock * 1000;
37 37
38 if (req_rate) { 38 if (req_rate) {
39 rate = clk_round_rate(hwdev->mclk, req_rate);
40 if (rate < req_rate) {
41 DRM_DEBUG_DRIVER("mclk clock unable to reach %d kHz\n",
42 mode->crtc_clock);
43 return false;
44 }
45
46 rate = clk_round_rate(hwdev->pxlclk, req_rate); 39 rate = clk_round_rate(hwdev->pxlclk, req_rate);
47 if (rate != req_rate) { 40 if (rate != req_rate) {
48 DRM_DEBUG_DRIVER("pxlclk doesn't support %ld Hz\n", 41 DRM_DEBUG_DRIVER("pxlclk doesn't support %ld Hz\n",
@@ -250,17 +243,21 @@ static int malidp_crtc_atomic_check_ctm(struct drm_crtc *crtc,
250static int malidp_crtc_atomic_check_scaling(struct drm_crtc *crtc, 243static int malidp_crtc_atomic_check_scaling(struct drm_crtc *crtc,
251 struct drm_crtc_state *state) 244 struct drm_crtc_state *state)
252{ 245{
246 struct malidp_drm *malidp = crtc_to_malidp_device(crtc);
247 struct malidp_hw_device *hwdev = malidp->dev;
253 struct malidp_crtc_state *cs = to_malidp_crtc_state(state); 248 struct malidp_crtc_state *cs = to_malidp_crtc_state(state);
254 struct malidp_se_config *s = &cs->scaler_config; 249 struct malidp_se_config *s = &cs->scaler_config;
255 struct drm_plane *plane; 250 struct drm_plane *plane;
251 struct videomode vm;
256 const struct drm_plane_state *pstate; 252 const struct drm_plane_state *pstate;
257 u32 h_upscale_factor = 0; /* U16.16 */ 253 u32 h_upscale_factor = 0; /* U16.16 */
258 u32 v_upscale_factor = 0; /* U16.16 */ 254 u32 v_upscale_factor = 0; /* U16.16 */
259 u8 scaling = cs->scaled_planes_mask; 255 u8 scaling = cs->scaled_planes_mask;
256 int ret;
260 257
261 if (!scaling) { 258 if (!scaling) {
262 s->scale_enable = false; 259 s->scale_enable = false;
263 return 0; 260 goto mclk_calc;
264 } 261 }
265 262
266 /* The scaling engine can only handle one plane at a time. */ 263 /* The scaling engine can only handle one plane at a time. */
@@ -284,10 +281,6 @@ static int malidp_crtc_atomic_check_scaling(struct drm_crtc *crtc,
284 h_upscale_factor = (u32)(crtc_w / pstate->src_w); 281 h_upscale_factor = (u32)(crtc_w / pstate->src_w);
285 v_upscale_factor = (u32)(crtc_h / pstate->src_h); 282 v_upscale_factor = (u32)(crtc_h / pstate->src_h);
286 283
287 /* Downscaling won't work when mclk == pxlclk. */
288 if (!(h_upscale_factor >> 16) || !(v_upscale_factor >> 16))
289 return -EINVAL;
290
291 s->enhancer_enable = ((h_upscale_factor >> 16) >= 2 || 284 s->enhancer_enable = ((h_upscale_factor >> 16) >= 2 ||
292 (v_upscale_factor >> 16) >= 2); 285 (v_upscale_factor >> 16) >= 2);
293 286
@@ -323,6 +316,12 @@ static int malidp_crtc_atomic_check_scaling(struct drm_crtc *crtc,
323 s->scale_enable = true; 316 s->scale_enable = true;
324 s->hcoeff = malidp_se_select_coeffs(h_upscale_factor); 317 s->hcoeff = malidp_se_select_coeffs(h_upscale_factor);
325 s->vcoeff = malidp_se_select_coeffs(v_upscale_factor); 318 s->vcoeff = malidp_se_select_coeffs(v_upscale_factor);
319
320mclk_calc:
321 drm_display_mode_to_videomode(&state->adjusted_mode, &vm);
322 ret = hwdev->se_calc_mclk(hwdev, s, &vm);
323 if (ret < 0)
324 return -EINVAL;
326 return 0; 325 return 0;
327} 326}
328 327
diff --git a/drivers/gpu/drm/arm/malidp_hw.c b/drivers/gpu/drm/arm/malidp_hw.c
index e444c23a8261..28360b8542f7 100644
--- a/drivers/gpu/drm/arm/malidp_hw.c
+++ b/drivers/gpu/drm/arm/malidp_hw.c
@@ -12,6 +12,7 @@
12 * in an attempt to provide to the rest of the driver code a unified view 12 * in an attempt to provide to the rest of the driver code a unified view
13 */ 13 */
14 14
15#include <linux/clk.h>
15#include <linux/types.h> 16#include <linux/types.h>
16#include <linux/io.h> 17#include <linux/io.h>
17#include <drm/drmP.h> 18#include <drm/drmP.h>
@@ -334,6 +335,39 @@ static int malidp500_se_set_scaling_coeffs(struct malidp_hw_device *hwdev,
334 return 0; 335 return 0;
335} 336}
336 337
338static long malidp500_se_calc_mclk(struct malidp_hw_device *hwdev,
339 struct malidp_se_config *se_config,
340 struct videomode *vm)
341{
342 unsigned long mclk;
343 unsigned long pxlclk = vm->pixelclock; /* Hz */
344 unsigned long htotal = vm->hactive + vm->hfront_porch +
345 vm->hback_porch + vm->hsync_len;
346 unsigned long input_size = se_config->input_w * se_config->input_h;
347 unsigned long a = 10;
348 long ret;
349
350 /*
351 * mclk = max(a, 1.5) * pxlclk
352 *
353 * To avoid float calculaiton, using 15 instead of 1.5 and div by
354 * 10 to get mclk.
355 */
356 if (se_config->scale_enable) {
357 a = 15 * input_size / (htotal * se_config->output_h);
358 if (a < 15)
359 a = 15;
360 }
361 mclk = a * pxlclk / 10;
362 ret = clk_get_rate(hwdev->mclk);
363 if (ret < mclk) {
364 DRM_DEBUG_DRIVER("mclk requirement of %lu kHz can't be met.\n",
365 mclk / 1000);
366 return -EINVAL;
367 }
368 return ret;
369}
370
337static int malidp550_query_hw(struct malidp_hw_device *hwdev) 371static int malidp550_query_hw(struct malidp_hw_device *hwdev)
338{ 372{
339 u32 conf = malidp_hw_read(hwdev, MALIDP550_CONFIG_ID); 373 u32 conf = malidp_hw_read(hwdev, MALIDP550_CONFIG_ID);
@@ -521,6 +555,39 @@ static int malidp550_se_set_scaling_coeffs(struct malidp_hw_device *hwdev,
521 return 0; 555 return 0;
522} 556}
523 557
558static long malidp550_se_calc_mclk(struct malidp_hw_device *hwdev,
559 struct malidp_se_config *se_config,
560 struct videomode *vm)
561{
562 unsigned long mclk;
563 unsigned long pxlclk = vm->pixelclock;
564 unsigned long htotal = vm->hactive + vm->hfront_porch +
565 vm->hback_porch + vm->hsync_len;
566 unsigned long numerator = 1, denominator = 1;
567 long ret;
568
569 if (se_config->scale_enable) {
570 numerator = max(se_config->input_w, se_config->output_w) *
571 se_config->input_h;
572 numerator += se_config->output_w *
573 (se_config->output_h -
574 min(se_config->input_h, se_config->output_h));
575 denominator = (htotal - 2) * se_config->output_h;
576 }
577
578 /* mclk can't be slower than pxlclk. */
579 if (numerator < denominator)
580 numerator = denominator = 1;
581 mclk = (pxlclk * numerator) / denominator;
582 ret = clk_get_rate(hwdev->mclk);
583 if (ret < mclk) {
584 DRM_DEBUG_DRIVER("mclk requirement of %lu kHz can't be met.\n",
585 mclk / 1000);
586 return -EINVAL;
587 }
588 return ret;
589}
590
524static int malidp650_query_hw(struct malidp_hw_device *hwdev) 591static int malidp650_query_hw(struct malidp_hw_device *hwdev)
525{ 592{
526 u32 conf = malidp_hw_read(hwdev, MALIDP550_CONFIG_ID); 593 u32 conf = malidp_hw_read(hwdev, MALIDP550_CONFIG_ID);
@@ -586,6 +653,7 @@ const struct malidp_hw_device malidp_device[MALIDP_MAX_DEVICES] = {
586 .modeset = malidp500_modeset, 653 .modeset = malidp500_modeset,
587 .rotmem_required = malidp500_rotmem_required, 654 .rotmem_required = malidp500_rotmem_required,
588 .se_set_scaling_coeffs = malidp500_se_set_scaling_coeffs, 655 .se_set_scaling_coeffs = malidp500_se_set_scaling_coeffs,
656 .se_calc_mclk = malidp500_se_calc_mclk,
589 .features = MALIDP_DEVICE_LV_HAS_3_STRIDES, 657 .features = MALIDP_DEVICE_LV_HAS_3_STRIDES,
590 }, 658 },
591 [MALIDP_550] = { 659 [MALIDP_550] = {
@@ -622,6 +690,7 @@ const struct malidp_hw_device malidp_device[MALIDP_MAX_DEVICES] = {
622 .modeset = malidp550_modeset, 690 .modeset = malidp550_modeset,
623 .rotmem_required = malidp550_rotmem_required, 691 .rotmem_required = malidp550_rotmem_required,
624 .se_set_scaling_coeffs = malidp550_se_set_scaling_coeffs, 692 .se_set_scaling_coeffs = malidp550_se_set_scaling_coeffs,
693 .se_calc_mclk = malidp550_se_calc_mclk,
625 .features = 0, 694 .features = 0,
626 }, 695 },