drm/vc4: Add support for double-clocked modes.
authorEric Anholt <eric@anholt.net>
Thu, 29 Sep 2016 22:34:44 +0000 (15:34 -0700)
committerEric Anholt <eric@anholt.net>
Thu, 6 Oct 2016 18:58:28 +0000 (11:58 -0700)
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>
drivers/gpu/drm/vc4/vc4_crtc.c
drivers/gpu/drm/vc4/vc4_hdmi.c
drivers/gpu/drm/vc4/vc4_regs.h

index 83cafea03eff720f9f7b80f484dedf22ac7f283f..7f08d681a74b4e37529f6c09ae1d2c1a944dcabd 100644 (file)
@@ -378,6 +378,7 @@ static void vc4_crtc_mode_set_nofb(struct drm_crtc *crtc)
        struct drm_crtc_state *state = crtc->state;
        struct drm_display_mode *mode = &state->adjusted_mode;
        bool interlace = mode->flags & DRM_MODE_FLAG_INTERLACE;
+       u32 pixel_rep = (mode->flags & DRM_MODE_FLAG_DBLCLK) ? 2 : 1;
        u32 format = PV_CONTROL_FORMAT_24;
        bool debug_dump_regs = false;
        int clock_select = vc4_get_clock_select(crtc);
@@ -393,14 +394,17 @@ static void vc4_crtc_mode_set_nofb(struct drm_crtc *crtc)
        CRTC_WRITE(PV_CONTROL, 0);
 
        CRTC_WRITE(PV_HORZA,
-                  VC4_SET_FIELD(mode->htotal - mode->hsync_end,
+                  VC4_SET_FIELD((mode->htotal -
+                                 mode->hsync_end) * pixel_rep,
                                 PV_HORZA_HBP) |
-                  VC4_SET_FIELD(mode->hsync_end - mode->hsync_start,
+                  VC4_SET_FIELD((mode->hsync_end -
+                                 mode->hsync_start) * pixel_rep,
                                 PV_HORZA_HSYNC));
        CRTC_WRITE(PV_HORZB,
-                  VC4_SET_FIELD(mode->hsync_start - mode->hdisplay,
+                  VC4_SET_FIELD((mode->hsync_start -
+                                 mode->hdisplay) * pixel_rep,
                                 PV_HORZB_HFP) |
-                  VC4_SET_FIELD(mode->hdisplay, PV_HORZB_HACTIVE));
+                  VC4_SET_FIELD(mode->hdisplay * pixel_rep, PV_HORZB_HACTIVE));
 
        CRTC_WRITE(PV_VERTA,
                   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)
                CRTC_WRITE(PV_V_CONTROL,
                           PV_VCONTROL_CONTINUOUS |
                           PV_VCONTROL_INTERLACE |
-                          VC4_SET_FIELD(mode->htotal / 2,
+                          VC4_SET_FIELD(mode->htotal * pixel_rep / 2,
                                         PV_VCONTROL_ODD_DELAY));
                CRTC_WRITE(PV_VSYNCD_EVEN, 0);
        } else {
                CRTC_WRITE(PV_V_CONTROL, PV_VCONTROL_CONTINUOUS);
        }
 
-       CRTC_WRITE(PV_HACT_ACT, mode->hdisplay);
+       CRTC_WRITE(PV_HACT_ACT, mode->hdisplay * pixel_rep);
 
 
        CRTC_WRITE(PV_CONTROL,
                   VC4_SET_FIELD(format, PV_CONTROL_FORMAT) |
                   VC4_SET_FIELD(vc4_get_fifo_full_level(format),
                                 PV_CONTROL_FIFO_LEVEL) |
+                  VC4_SET_FIELD(pixel_rep - 1, PV_CONTROL_PIXEL_REP) |
                   PV_CONTROL_CLR_AT_START |
                   PV_CONTROL_TRIGGER_UNDERFLOW |
                   PV_CONTROL_WAIT_HSTART |
index d6b54b905beeec33eee8a763969ffa9568cfa745..c4cb2e26de32f06db0abf3fd94b3117c3292eed5 100644 (file)
@@ -402,6 +402,7 @@ static void vc4_hdmi_encoder_mode_set(struct drm_encoder *encoder,
        bool hsync_pos = mode->flags & DRM_MODE_FLAG_PHSYNC;
        bool vsync_pos = mode->flags & DRM_MODE_FLAG_PVSYNC;
        bool interlaced = mode->flags & DRM_MODE_FLAG_INTERLACE;
+       u32 pixel_rep = (mode->flags & DRM_MODE_FLAG_DBLCLK) ? 2 : 1;
        u32 verta = (VC4_SET_FIELD(mode->crtc_vsync_end - mode->crtc_vsync_start,
                                   VC4_HDMI_VERTA_VSP) |
                     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,
 
        HD_WRITE(VC4_HD_VID_CTL, 0);
 
-       clk_set_rate(vc4->hdmi->pixel_clock, mode->clock * 1000);
+       clk_set_rate(vc4->hdmi->pixel_clock, mode->clock * 1000 *
+                    ((mode->flags & DRM_MODE_FLAG_DBLCLK) ? 2 : 1));
 
        HDMI_WRITE(VC4_HDMI_SCHEDULER_CONTROL,
                   HDMI_READ(VC4_HDMI_SCHEDULER_CONTROL) |
@@ -434,14 +436,18 @@ static void vc4_hdmi_encoder_mode_set(struct drm_encoder *encoder,
        HDMI_WRITE(VC4_HDMI_HORZA,
                   (vsync_pos ? VC4_HDMI_HORZA_VPOS : 0) |
                   (hsync_pos ? VC4_HDMI_HORZA_HPOS : 0) |
-                  VC4_SET_FIELD(mode->hdisplay, VC4_HDMI_HORZA_HAP));
+                  VC4_SET_FIELD(mode->hdisplay * pixel_rep,
+                                VC4_HDMI_HORZA_HAP));
 
        HDMI_WRITE(VC4_HDMI_HORZB,
-                  VC4_SET_FIELD(mode->htotal - mode->hsync_end,
+                  VC4_SET_FIELD((mode->htotal -
+                                 mode->hsync_end) * pixel_rep,
                                 VC4_HDMI_HORZB_HBP) |
-                  VC4_SET_FIELD(mode->hsync_end - mode->hsync_start,
+                  VC4_SET_FIELD((mode->hsync_end -
+                                 mode->hsync_start) * pixel_rep,
                                 VC4_HDMI_HORZB_HSP) |
-                  VC4_SET_FIELD(mode->hsync_start - mode->hdisplay,
+                  VC4_SET_FIELD((mode->hsync_start -
+                                 mode->hdisplay) * pixel_rep,
                                 VC4_HDMI_HORZB_HFP));
 
        HDMI_WRITE(VC4_HDMI_VERTA0, verta);
index 0b868aafa8db69b0a08fe9cbf293263a0a7c5bed..1aa44c2db5565ba126d2ceb65495a6c98c555860 100644 (file)
 # define PV_CONTROL_CLR_AT_START               BIT(14)
 # define PV_CONTROL_TRIGGER_UNDERFLOW          BIT(13)
 # define PV_CONTROL_WAIT_HSTART                        BIT(12)
+# define PV_CONTROL_PIXEL_REP_MASK             VC4_MASK(5, 4)
+# define PV_CONTROL_PIXEL_REP_SHIFT            4
 # define PV_CONTROL_CLK_SELECT_DSI_VEC         0
 # define PV_CONTROL_CLK_SELECT_DPI_SMI_HDMI    1
 # define PV_CONTROL_CLK_SELECT_MASK            VC4_MASK(3, 2)