From 48627eb8dc55c60d35794105f6f79fb627347dbd Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Fri, 5 Feb 2016 15:06:15 -0800 Subject: [PATCH 1/6] drm/vc4: Fix a framebuffer reference leak on async flip interrupt. We'd need X to queue up an async pageflip while another is outstanding, and then take a SIGIO. I think X actually avoids sending out the next pageflip while one's already queued, but I'm not sure. Signed-off-by: Eric Anholt --- drivers/gpu/drm/vc4/vc4_crtc.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/gpu/drm/vc4/vc4_crtc.c b/drivers/gpu/drm/vc4/vc4_crtc.c index 018145e0b87d..989ee728e2b0 100644 --- a/drivers/gpu/drm/vc4/vc4_crtc.c +++ b/drivers/gpu/drm/vc4/vc4_crtc.c @@ -544,6 +544,7 @@ static int vc4_async_page_flip(struct drm_crtc *crtc, /* Make sure all other async modesetes have landed. */ ret = down_interruptible(&vc4->async_modeset); if (ret) { + drm_framebuffer_unreference(fb); kfree(flip_state); return ret; } From 851479ad5927b7b1aa141ca9dedb897a7bce2b1d Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Fri, 12 Feb 2016 14:15:14 -0800 Subject: [PATCH 2/6] drm/vc4: Bring HDMI up from power off if necessary. If the firmware hadn't brought up HDMI for us, we need to do its power-on reset sequence (reset HD and and clear its STANDBY bits, reset HDMI, and leave the PHY disabled). Signed-off-by: Eric Anholt --- drivers/gpu/drm/vc4/vc4_hdmi.c | 29 ++++++++++++++++++++++++++++- drivers/gpu/drm/vc4/vc4_regs.h | 2 ++ 2 files changed, 30 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c index c69c0460196b..6e55760511bf 100644 --- a/drivers/gpu/drm/vc4/vc4_hdmi.c +++ b/drivers/gpu/drm/vc4/vc4_hdmi.c @@ -495,6 +495,16 @@ static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data) goto err_put_i2c; } + /* This is the rate that is set by the firmware. The number + * needs to be a bit higher than the pixel clock rate + * (generally 148.5Mhz). + */ + ret = clk_set_rate(hdmi->hsm_clock, 163682864); + if (ret) { + DRM_ERROR("Failed to set HSM clock rate: %d\n", ret); + goto err_unprepare_pix; + } + ret = clk_prepare_enable(hdmi->hsm_clock); if (ret) { DRM_ERROR("Failed to turn on HDMI state machine clock: %d\n", @@ -516,7 +526,24 @@ static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data) vc4->hdmi = hdmi; /* HDMI core must be enabled. */ - WARN_ON_ONCE((HD_READ(VC4_HD_M_CTL) & VC4_HD_M_ENABLE) == 0); + if (!(HD_READ(VC4_HD_M_CTL) & VC4_HD_M_ENABLE)) { + HD_WRITE(VC4_HD_M_CTL, VC4_HD_M_SW_RST); + udelay(1); + HD_WRITE(VC4_HD_M_CTL, 0); + + HD_WRITE(VC4_HD_M_CTL, VC4_HD_M_ENABLE); + + HDMI_WRITE(VC4_HDMI_SW_RESET_CONTROL, + VC4_HDMI_SW_RESET_HDMI | + VC4_HDMI_SW_RESET_FORMAT_DETECT); + + HDMI_WRITE(VC4_HDMI_SW_RESET_CONTROL, 0); + + /* PHY should be in reset, like + * vc4_hdmi_encoder_disable() does. + */ + HDMI_WRITE(VC4_HDMI_TX_PHY_RESET_CTL, 0xf << 16); + } drm_encoder_init(drm, hdmi->encoder, &vc4_hdmi_encoder_funcs, DRM_MODE_ENCODER_TMDS, NULL); diff --git a/drivers/gpu/drm/vc4/vc4_regs.h b/drivers/gpu/drm/vc4/vc4_regs.h index 4e52a0a88551..85c36d238669 100644 --- a/drivers/gpu/drm/vc4/vc4_regs.h +++ b/drivers/gpu/drm/vc4/vc4_regs.h @@ -456,6 +456,8 @@ #define VC4_HDMI_TX_PHY_RESET_CTL 0x2c0 #define VC4_HD_M_CTL 0x00c +# define VC4_HD_M_REGISTER_FILE_STANDBY (3 << 6) +# define VC4_HD_M_RAM_STANDBY (3 << 4) # define VC4_HD_M_SW_RST BIT(2) # define VC4_HD_M_ENABLE BIT(0) From 936f1a53f32148cc6164fad7c9a26ebf144e5ffb Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Fri, 12 Feb 2016 15:16:56 -0800 Subject: [PATCH 3/6] drm/vc4: Add another reg to HDMI debug dumping. This is also involved in the HDMI setup sequence so it's nice to see it. Signed-off-by: Eric Anholt --- drivers/gpu/drm/vc4/vc4_hdmi.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c index 6e55760511bf..56272ca98ab7 100644 --- a/drivers/gpu/drm/vc4/vc4_hdmi.c +++ b/drivers/gpu/drm/vc4/vc4_hdmi.c @@ -95,6 +95,7 @@ static const struct { HDMI_REG(VC4_HDMI_SW_RESET_CONTROL), HDMI_REG(VC4_HDMI_HOTPLUG_INT), HDMI_REG(VC4_HDMI_HOTPLUG), + HDMI_REG(VC4_HDMI_RAM_PACKET_CONFIG), HDMI_REG(VC4_HDMI_HORZA), HDMI_REG(VC4_HDMI_HORZB), HDMI_REG(VC4_HDMI_FIFO_CTL), From c31806fbdda910d337b60896040afa708bdfa2bd Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Mon, 15 Feb 2016 17:06:02 -0800 Subject: [PATCH 4/6] drm/vc4: Fix the name of the VSYNCD_EVEN register. It's used for delaying vsync in interlaced mode. Signed-off-by: Eric Anholt --- drivers/gpu/drm/vc4/vc4_crtc.c | 2 +- drivers/gpu/drm/vc4/vc4_regs.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/vc4/vc4_crtc.c b/drivers/gpu/drm/vc4/vc4_crtc.c index 989ee728e2b0..5e84be2e97d0 100644 --- a/drivers/gpu/drm/vc4/vc4_crtc.c +++ b/drivers/gpu/drm/vc4/vc4_crtc.c @@ -83,7 +83,7 @@ static const struct { } crtc_regs[] = { CRTC_REG(PV_CONTROL), CRTC_REG(PV_V_CONTROL), - CRTC_REG(PV_VSYNCD), + CRTC_REG(PV_VSYNCD_EVEN), CRTC_REG(PV_HORZA), CRTC_REG(PV_HORZB), CRTC_REG(PV_VERTA), diff --git a/drivers/gpu/drm/vc4/vc4_regs.h b/drivers/gpu/drm/vc4/vc4_regs.h index 85c36d238669..d529665d43cd 100644 --- a/drivers/gpu/drm/vc4/vc4_regs.h +++ b/drivers/gpu/drm/vc4/vc4_regs.h @@ -187,7 +187,7 @@ # define PV_VCONTROL_CONTINUOUS BIT(1) # define PV_VCONTROL_VIDEN BIT(0) -#define PV_VSYNCD 0x08 +#define PV_VSYNCD_EVEN 0x08 #define PV_HORZA 0x0c # define PV_HORZA_HBP_MASK VC4_MASK(31, 16) From a7c5047d1ce178dd2b1fa577fc8909ad663d56d5 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Mon, 15 Feb 2016 17:31:41 -0800 Subject: [PATCH 5/6] drm/vc4: Fix setting of vertical timings in the CRTC. It looks like when I went to add the interlaced bits, I just took the existing PV_VERT* block and indented it, instead of copy and pasting it first. Without this, changing resolution never worked. Signed-off-by: Eric Anholt --- drivers/gpu/drm/vc4/vc4_crtc.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/drivers/gpu/drm/vc4/vc4_crtc.c b/drivers/gpu/drm/vc4/vc4_crtc.c index 5e84be2e97d0..93d53c278486 100644 --- a/drivers/gpu/drm/vc4/vc4_crtc.c +++ b/drivers/gpu/drm/vc4/vc4_crtc.c @@ -212,6 +212,16 @@ static void vc4_crtc_mode_set_nofb(struct drm_crtc *crtc) PV_HORZB_HFP) | VC4_SET_FIELD(mode->hdisplay, PV_HORZB_HACTIVE)); + CRTC_WRITE(PV_VERTA, + VC4_SET_FIELD(mode->vtotal - mode->vsync_end, + PV_VERTA_VBP) | + VC4_SET_FIELD(mode->vsync_end - mode->vsync_start, + PV_VERTA_VSYNC)); + CRTC_WRITE(PV_VERTB, + VC4_SET_FIELD(mode->vsync_start - mode->vdisplay, + PV_VERTB_VFP) | + VC4_SET_FIELD(vactive, PV_VERTB_VACTIVE)); + if (interlace) { CRTC_WRITE(PV_VERTA_EVEN, VC4_SET_FIELD(mode->vtotal - mode->vsync_end - 1, From 6a609209865247cc748e90158c99f374f79b494c Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Tue, 16 Feb 2016 10:24:08 -0800 Subject: [PATCH 6/6] drm/vc4: Initialize scaler DISPBKGND on modeset. We weren't updating the interlaced bit, so we'd scan out incorrectly if the firmware had brought up the TV encoder and we were switching to HDMI. Signed-off-by: Eric Anholt --- drivers/gpu/drm/vc4/vc4_crtc.c | 6 ++++++ drivers/gpu/drm/vc4/vc4_regs.h | 14 ++++++++++++++ 2 files changed, 20 insertions(+) diff --git a/drivers/gpu/drm/vc4/vc4_crtc.c b/drivers/gpu/drm/vc4/vc4_crtc.c index 93d53c278486..6ae5abcabe62 100644 --- a/drivers/gpu/drm/vc4/vc4_crtc.c +++ b/drivers/gpu/drm/vc4/vc4_crtc.c @@ -183,6 +183,8 @@ static int vc4_get_clock_select(struct drm_crtc *crtc) static void vc4_crtc_mode_set_nofb(struct drm_crtc *crtc) { + struct drm_device *dev = crtc->dev; + struct vc4_dev *vc4 = to_vc4_dev(dev); struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc); struct drm_crtc_state *state = crtc->state; struct drm_display_mode *mode = &state->adjusted_mode; @@ -251,6 +253,10 @@ static void vc4_crtc_mode_set_nofb(struct drm_crtc *crtc) PV_CONTROL_FIFO_CLR | PV_CONTROL_EN); + HVS_WRITE(SCALER_DISPBKGNDX(vc4_crtc->channel), + SCALER_DISPBKGND_AUTOHS | + (interlace ? SCALER_DISPBKGND_INTERLACE : 0)); + if (debug_dump_regs) { DRM_INFO("CRTC %d regs after:\n", drm_crtc_index(crtc)); vc4_crtc_dump_regs(vc4_crtc); diff --git a/drivers/gpu/drm/vc4/vc4_regs.h b/drivers/gpu/drm/vc4/vc4_regs.h index d529665d43cd..7c29993a3316 100644 --- a/drivers/gpu/drm/vc4/vc4_regs.h +++ b/drivers/gpu/drm/vc4/vc4_regs.h @@ -350,6 +350,17 @@ # define SCALER_DISPCTRLX_HEIGHT_SHIFT 0 #define SCALER_DISPBKGND0 0x00000044 +# define SCALER_DISPBKGND_AUTOHS BIT(31) +# define SCALER_DISPBKGND_INTERLACE BIT(30) +# define SCALER_DISPBKGND_GAMMA BIT(29) +# define SCALER_DISPBKGND_TESTMODE_MASK VC4_MASK(28, 25) +# define SCALER_DISPBKGND_TESTMODE_SHIFT 25 +/* Enables filling the scaler line with the RGB value in the low 24 + * bits before compositing. Costs cycles, so should be skipped if + * opaque display planes will cover everything. + */ +# define SCALER_DISPBKGND_FILL BIT(24) + #define SCALER_DISPSTAT0 0x00000048 #define SCALER_DISPBASE0 0x0000004c # define SCALER_DISPSTATX_MODE_MASK VC4_MASK(31, 30) @@ -362,6 +373,9 @@ # define SCALER_DISPSTATX_EMPTY BIT(28) #define SCALER_DISPCTRL1 0x00000050 #define SCALER_DISPBKGND1 0x00000054 +#define SCALER_DISPBKGNDX(x) (SCALER_DISPBKGND0 + \ + (x) * (SCALER_DISPBKGND1 - \ + SCALER_DISPBKGND0)) #define SCALER_DISPSTAT1 0x00000058 #define SCALER_DISPSTATX(x) (SCALER_DISPSTAT0 + \ (x) * (SCALER_DISPSTAT1 - \