aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEric Anholt <eric@anholt.net>2016-09-29 18:34:44 -0400
committerEric Anholt <eric@anholt.net>2016-10-06 14:58:28 -0400
commitdfccd937deec9283d6ced73e138808e62bec54e8 (patch)
tree546c4042707df9cbbcc2c4c2dcf446dd03758d4c
parent21317b3fba5428c97779cc8a988ac603e82abd8b (diff)
drm/vc4: Add support for double-clocked modes.
Now that we have infoframes to report the pixel repeat flag, we can start using it. Fixes locking the 720x480i and 720x576i modes on my Dell 2408WFP. Like the 1920x1080i case, they don't fit properly on the screen, though. Signed-off-by: Eric Anholt <eric@anholt.net>
-rw-r--r--drivers/gpu/drm/vc4/vc4_crtc.c17
-rw-r--r--drivers/gpu/drm/vc4/vc4_hdmi.c16
-rw-r--r--drivers/gpu/drm/vc4/vc4_regs.h2
3 files changed, 24 insertions, 11 deletions
diff --git a/drivers/gpu/drm/vc4/vc4_crtc.c b/drivers/gpu/drm/vc4/vc4_crtc.c
index 83cafea03eff..7f08d681a74b 100644
--- a/drivers/gpu/drm/vc4/vc4_crtc.c
+++ b/drivers/gpu/drm/vc4/vc4_crtc.c
@@ -378,6 +378,7 @@ static void vc4_crtc_mode_set_nofb(struct drm_crtc *crtc)
378 struct drm_crtc_state *state = crtc->state; 378 struct drm_crtc_state *state = crtc->state;
379 struct drm_display_mode *mode = &state->adjusted_mode; 379 struct drm_display_mode *mode = &state->adjusted_mode;
380 bool interlace = mode->flags & DRM_MODE_FLAG_INTERLACE; 380 bool interlace = mode->flags & DRM_MODE_FLAG_INTERLACE;
381 u32 pixel_rep = (mode->flags & DRM_MODE_FLAG_DBLCLK) ? 2 : 1;
381 u32 format = PV_CONTROL_FORMAT_24; 382 u32 format = PV_CONTROL_FORMAT_24;
382 bool debug_dump_regs = false; 383 bool debug_dump_regs = false;
383 int clock_select = vc4_get_clock_select(crtc); 384 int clock_select = vc4_get_clock_select(crtc);
@@ -393,14 +394,17 @@ static void vc4_crtc_mode_set_nofb(struct drm_crtc *crtc)
393 CRTC_WRITE(PV_CONTROL, 0); 394 CRTC_WRITE(PV_CONTROL, 0);
394 395
395 CRTC_WRITE(PV_HORZA, 396 CRTC_WRITE(PV_HORZA,
396 VC4_SET_FIELD(mode->htotal - mode->hsync_end, 397 VC4_SET_FIELD((mode->htotal -
398 mode->hsync_end) * pixel_rep,
397 PV_HORZA_HBP) | 399 PV_HORZA_HBP) |
398 VC4_SET_FIELD(mode->hsync_end - mode->hsync_start, 400 VC4_SET_FIELD((mode->hsync_end -
401 mode->hsync_start) * pixel_rep,
399 PV_HORZA_HSYNC)); 402 PV_HORZA_HSYNC));
400 CRTC_WRITE(PV_HORZB, 403 CRTC_WRITE(PV_HORZB,
401 VC4_SET_FIELD(mode->hsync_start - mode->hdisplay, 404 VC4_SET_FIELD((mode->hsync_start -
405 mode->hdisplay) * pixel_rep,
402 PV_HORZB_HFP) | 406 PV_HORZB_HFP) |
403 VC4_SET_FIELD(mode->hdisplay, PV_HORZB_HACTIVE)); 407 VC4_SET_FIELD(mode->hdisplay * pixel_rep, PV_HORZB_HACTIVE));
404 408
405 CRTC_WRITE(PV_VERTA, 409 CRTC_WRITE(PV_VERTA,
406 VC4_SET_FIELD(mode->crtc_vtotal - mode->crtc_vsync_end, 410 VC4_SET_FIELD(mode->crtc_vtotal - mode->crtc_vsync_end,
@@ -434,20 +438,21 @@ static void vc4_crtc_mode_set_nofb(struct drm_crtc *crtc)
434 CRTC_WRITE(PV_V_CONTROL, 438 CRTC_WRITE(PV_V_CONTROL,
435 PV_VCONTROL_CONTINUOUS | 439 PV_VCONTROL_CONTINUOUS |
436 PV_VCONTROL_INTERLACE | 440 PV_VCONTROL_INTERLACE |
437 VC4_SET_FIELD(mode->htotal / 2, 441 VC4_SET_FIELD(mode->htotal * pixel_rep / 2,
438 PV_VCONTROL_ODD_DELAY)); 442 PV_VCONTROL_ODD_DELAY));
439 CRTC_WRITE(PV_VSYNCD_EVEN, 0); 443 CRTC_WRITE(PV_VSYNCD_EVEN, 0);
440 } else { 444 } else {
441 CRTC_WRITE(PV_V_CONTROL, PV_VCONTROL_CONTINUOUS); 445 CRTC_WRITE(PV_V_CONTROL, PV_VCONTROL_CONTINUOUS);
442 } 446 }
443 447
444 CRTC_WRITE(PV_HACT_ACT, mode->hdisplay); 448 CRTC_WRITE(PV_HACT_ACT, mode->hdisplay * pixel_rep);
445 449
446 450
447 CRTC_WRITE(PV_CONTROL, 451 CRTC_WRITE(PV_CONTROL,
448 VC4_SET_FIELD(format, PV_CONTROL_FORMAT) | 452 VC4_SET_FIELD(format, PV_CONTROL_FORMAT) |
449 VC4_SET_FIELD(vc4_get_fifo_full_level(format), 453 VC4_SET_FIELD(vc4_get_fifo_full_level(format),
450 PV_CONTROL_FIFO_LEVEL) | 454 PV_CONTROL_FIFO_LEVEL) |
455 VC4_SET_FIELD(pixel_rep - 1, PV_CONTROL_PIXEL_REP) |
451 PV_CONTROL_CLR_AT_START | 456 PV_CONTROL_CLR_AT_START |
452 PV_CONTROL_TRIGGER_UNDERFLOW | 457 PV_CONTROL_TRIGGER_UNDERFLOW |
453 PV_CONTROL_WAIT_HSTART | 458 PV_CONTROL_WAIT_HSTART |
diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
index d6b54b905bee..c4cb2e26de32 100644
--- a/drivers/gpu/drm/vc4/vc4_hdmi.c
+++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
@@ -402,6 +402,7 @@ static void vc4_hdmi_encoder_mode_set(struct drm_encoder *encoder,
402 bool hsync_pos = mode->flags & DRM_MODE_FLAG_PHSYNC; 402 bool hsync_pos = mode->flags & DRM_MODE_FLAG_PHSYNC;
403 bool vsync_pos = mode->flags & DRM_MODE_FLAG_PVSYNC; 403 bool vsync_pos = mode->flags & DRM_MODE_FLAG_PVSYNC;
404 bool interlaced = mode->flags & DRM_MODE_FLAG_INTERLACE; 404 bool interlaced = mode->flags & DRM_MODE_FLAG_INTERLACE;
405 u32 pixel_rep = (mode->flags & DRM_MODE_FLAG_DBLCLK) ? 2 : 1;
405 u32 verta = (VC4_SET_FIELD(mode->crtc_vsync_end - mode->crtc_vsync_start, 406 u32 verta = (VC4_SET_FIELD(mode->crtc_vsync_end - mode->crtc_vsync_start,
406 VC4_HDMI_VERTA_VSP) | 407 VC4_HDMI_VERTA_VSP) |
407 VC4_SET_FIELD(mode->crtc_vsync_start - mode->crtc_vdisplay, 408 VC4_SET_FIELD(mode->crtc_vsync_start - mode->crtc_vdisplay,
@@ -424,7 +425,8 @@ static void vc4_hdmi_encoder_mode_set(struct drm_encoder *encoder,
424 425
425 HD_WRITE(VC4_HD_VID_CTL, 0); 426 HD_WRITE(VC4_HD_VID_CTL, 0);
426 427
427 clk_set_rate(vc4->hdmi->pixel_clock, mode->clock * 1000); 428 clk_set_rate(vc4->hdmi->pixel_clock, mode->clock * 1000 *
429 ((mode->flags & DRM_MODE_FLAG_DBLCLK) ? 2 : 1));
428 430
429 HDMI_WRITE(VC4_HDMI_SCHEDULER_CONTROL, 431 HDMI_WRITE(VC4_HDMI_SCHEDULER_CONTROL,
430 HDMI_READ(VC4_HDMI_SCHEDULER_CONTROL) | 432 HDMI_READ(VC4_HDMI_SCHEDULER_CONTROL) |
@@ -434,14 +436,18 @@ static void vc4_hdmi_encoder_mode_set(struct drm_encoder *encoder,
434 HDMI_WRITE(VC4_HDMI_HORZA, 436 HDMI_WRITE(VC4_HDMI_HORZA,
435 (vsync_pos ? VC4_HDMI_HORZA_VPOS : 0) | 437 (vsync_pos ? VC4_HDMI_HORZA_VPOS : 0) |
436 (hsync_pos ? VC4_HDMI_HORZA_HPOS : 0) | 438 (hsync_pos ? VC4_HDMI_HORZA_HPOS : 0) |
437 VC4_SET_FIELD(mode->hdisplay, VC4_HDMI_HORZA_HAP)); 439 VC4_SET_FIELD(mode->hdisplay * pixel_rep,
440 VC4_HDMI_HORZA_HAP));
438 441
439 HDMI_WRITE(VC4_HDMI_HORZB, 442 HDMI_WRITE(VC4_HDMI_HORZB,
440 VC4_SET_FIELD(mode->htotal - mode->hsync_end, 443 VC4_SET_FIELD((mode->htotal -
444 mode->hsync_end) * pixel_rep,
441 VC4_HDMI_HORZB_HBP) | 445 VC4_HDMI_HORZB_HBP) |
442 VC4_SET_FIELD(mode->hsync_end - mode->hsync_start, 446 VC4_SET_FIELD((mode->hsync_end -
447 mode->hsync_start) * pixel_rep,
443 VC4_HDMI_HORZB_HSP) | 448 VC4_HDMI_HORZB_HSP) |
444 VC4_SET_FIELD(mode->hsync_start - mode->hdisplay, 449 VC4_SET_FIELD((mode->hsync_start -
450 mode->hdisplay) * pixel_rep,
445 VC4_HDMI_HORZB_HFP)); 451 VC4_HDMI_HORZB_HFP));
446 452
447 HDMI_WRITE(VC4_HDMI_VERTA0, verta); 453 HDMI_WRITE(VC4_HDMI_VERTA0, verta);
diff --git a/drivers/gpu/drm/vc4/vc4_regs.h b/drivers/gpu/drm/vc4/vc4_regs.h
index 0b868aafa8db..1aa44c2db556 100644
--- a/drivers/gpu/drm/vc4/vc4_regs.h
+++ b/drivers/gpu/drm/vc4/vc4_regs.h
@@ -175,6 +175,8 @@
175# define PV_CONTROL_CLR_AT_START BIT(14) 175# define PV_CONTROL_CLR_AT_START BIT(14)
176# define PV_CONTROL_TRIGGER_UNDERFLOW BIT(13) 176# define PV_CONTROL_TRIGGER_UNDERFLOW BIT(13)
177# define PV_CONTROL_WAIT_HSTART BIT(12) 177# define PV_CONTROL_WAIT_HSTART BIT(12)
178# define PV_CONTROL_PIXEL_REP_MASK VC4_MASK(5, 4)
179# define PV_CONTROL_PIXEL_REP_SHIFT 4
178# define PV_CONTROL_CLK_SELECT_DSI_VEC 0 180# define PV_CONTROL_CLK_SELECT_DSI_VEC 0
179# define PV_CONTROL_CLK_SELECT_DPI_SMI_HDMI 1 181# define PV_CONTROL_CLK_SELECT_DPI_SMI_HDMI 1
180# define PV_CONTROL_CLK_SELECT_MASK VC4_MASK(3, 2) 182# define PV_CONTROL_CLK_SELECT_MASK VC4_MASK(3, 2)