Commit dfccd937 authored by Eric Anholt's avatar Eric Anholt

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: default avatarEric Anholt <eric@anholt.net>
parent 21317b3f
...@@ -378,6 +378,7 @@ static void vc4_crtc_mode_set_nofb(struct drm_crtc *crtc) ...@@ -378,6 +378,7 @@ static void vc4_crtc_mode_set_nofb(struct drm_crtc *crtc)
struct drm_crtc_state *state = crtc->state; struct drm_crtc_state *state = crtc->state;
struct drm_display_mode *mode = &state->adjusted_mode; struct drm_display_mode *mode = &state->adjusted_mode;
bool interlace = mode->flags & DRM_MODE_FLAG_INTERLACE; 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; u32 format = PV_CONTROL_FORMAT_24;
bool debug_dump_regs = false; bool debug_dump_regs = false;
int clock_select = vc4_get_clock_select(crtc); int clock_select = vc4_get_clock_select(crtc);
...@@ -393,14 +394,17 @@ static void vc4_crtc_mode_set_nofb(struct drm_crtc *crtc) ...@@ -393,14 +394,17 @@ static void vc4_crtc_mode_set_nofb(struct drm_crtc *crtc)
CRTC_WRITE(PV_CONTROL, 0); CRTC_WRITE(PV_CONTROL, 0);
CRTC_WRITE(PV_HORZA, 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) | 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)); PV_HORZA_HSYNC));
CRTC_WRITE(PV_HORZB, 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) | 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, CRTC_WRITE(PV_VERTA,
VC4_SET_FIELD(mode->crtc_vtotal - mode->crtc_vsync_end, 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,20 +438,21 @@ static void vc4_crtc_mode_set_nofb(struct drm_crtc *crtc)
CRTC_WRITE(PV_V_CONTROL, CRTC_WRITE(PV_V_CONTROL,
PV_VCONTROL_CONTINUOUS | PV_VCONTROL_CONTINUOUS |
PV_VCONTROL_INTERLACE | PV_VCONTROL_INTERLACE |
VC4_SET_FIELD(mode->htotal / 2, VC4_SET_FIELD(mode->htotal * pixel_rep / 2,
PV_VCONTROL_ODD_DELAY)); PV_VCONTROL_ODD_DELAY));
CRTC_WRITE(PV_VSYNCD_EVEN, 0); CRTC_WRITE(PV_VSYNCD_EVEN, 0);
} else { } else {
CRTC_WRITE(PV_V_CONTROL, PV_VCONTROL_CONTINUOUS); 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, CRTC_WRITE(PV_CONTROL,
VC4_SET_FIELD(format, PV_CONTROL_FORMAT) | VC4_SET_FIELD(format, PV_CONTROL_FORMAT) |
VC4_SET_FIELD(vc4_get_fifo_full_level(format), VC4_SET_FIELD(vc4_get_fifo_full_level(format),
PV_CONTROL_FIFO_LEVEL) | PV_CONTROL_FIFO_LEVEL) |
VC4_SET_FIELD(pixel_rep - 1, PV_CONTROL_PIXEL_REP) |
PV_CONTROL_CLR_AT_START | PV_CONTROL_CLR_AT_START |
PV_CONTROL_TRIGGER_UNDERFLOW | PV_CONTROL_TRIGGER_UNDERFLOW |
PV_CONTROL_WAIT_HSTART | PV_CONTROL_WAIT_HSTART |
......
...@@ -402,6 +402,7 @@ static void vc4_hdmi_encoder_mode_set(struct drm_encoder *encoder, ...@@ -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 hsync_pos = mode->flags & DRM_MODE_FLAG_PHSYNC;
bool vsync_pos = mode->flags & DRM_MODE_FLAG_PVSYNC; bool vsync_pos = mode->flags & DRM_MODE_FLAG_PVSYNC;
bool interlaced = mode->flags & DRM_MODE_FLAG_INTERLACE; 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, u32 verta = (VC4_SET_FIELD(mode->crtc_vsync_end - mode->crtc_vsync_start,
VC4_HDMI_VERTA_VSP) | VC4_HDMI_VERTA_VSP) |
VC4_SET_FIELD(mode->crtc_vsync_start - mode->crtc_vdisplay, 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,7 +425,8 @@ static void vc4_hdmi_encoder_mode_set(struct drm_encoder *encoder,
HD_WRITE(VC4_HD_VID_CTL, 0); 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_WRITE(VC4_HDMI_SCHEDULER_CONTROL,
HDMI_READ(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, ...@@ -434,14 +436,18 @@ static void vc4_hdmi_encoder_mode_set(struct drm_encoder *encoder,
HDMI_WRITE(VC4_HDMI_HORZA, HDMI_WRITE(VC4_HDMI_HORZA,
(vsync_pos ? VC4_HDMI_HORZA_VPOS : 0) | (vsync_pos ? VC4_HDMI_HORZA_VPOS : 0) |
(hsync_pos ? VC4_HDMI_HORZA_HPOS : 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, 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_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_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)); VC4_HDMI_HORZB_HFP));
HDMI_WRITE(VC4_HDMI_VERTA0, verta); HDMI_WRITE(VC4_HDMI_VERTA0, verta);
......
...@@ -175,6 +175,8 @@ ...@@ -175,6 +175,8 @@
# define PV_CONTROL_CLR_AT_START BIT(14) # define PV_CONTROL_CLR_AT_START BIT(14)
# define PV_CONTROL_TRIGGER_UNDERFLOW BIT(13) # define PV_CONTROL_TRIGGER_UNDERFLOW BIT(13)
# define PV_CONTROL_WAIT_HSTART BIT(12) # 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_DSI_VEC 0
# define PV_CONTROL_CLK_SELECT_DPI_SMI_HDMI 1 # define PV_CONTROL_CLK_SELECT_DPI_SMI_HDMI 1
# define PV_CONTROL_CLK_SELECT_MASK VC4_MASK(3, 2) # define PV_CONTROL_CLK_SELECT_MASK VC4_MASK(3, 2)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment