Skip to content

Commit 67d1c0a

Browse files
committed
Merge tag 'drm-vc4-fixes-2016-03-03' of github.com:anholt/linux into drm-next
This pull request fixes the major VC4 HDMI modesetting bugs found when the first wave of users showed up in Raspbian. * tag 'drm-vc4-fixes-2016-03-03' of github.com:anholt/linux: drm/vc4: Initialize scaler DISPBKGND on modeset. drm/vc4: Fix setting of vertical timings in the CRTC. drm/vc4: Fix the name of the VSYNCD_EVEN register. drm/vc4: Add another reg to HDMI debug dumping. drm/vc4: Bring HDMI up from power off if necessary. drm/vc4: Fix a framebuffer reference leak on async flip interrupt.
2 parents c3d7a1d + 6a60920 commit 67d1c0a

File tree

3 files changed

+64
-3
lines changed

3 files changed

+64
-3
lines changed

drivers/gpu/drm/vc4/vc4_crtc.c

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ static const struct {
8888
} crtc_regs[] = {
8989
CRTC_REG(PV_CONTROL),
9090
CRTC_REG(PV_V_CONTROL),
91-
CRTC_REG(PV_VSYNCD),
91+
CRTC_REG(PV_VSYNCD_EVEN),
9292
CRTC_REG(PV_HORZA),
9393
CRTC_REG(PV_HORZB),
9494
CRTC_REG(PV_VERTA),
@@ -188,6 +188,8 @@ static int vc4_get_clock_select(struct drm_crtc *crtc)
188188

189189
static void vc4_crtc_mode_set_nofb(struct drm_crtc *crtc)
190190
{
191+
struct drm_device *dev = crtc->dev;
192+
struct vc4_dev *vc4 = to_vc4_dev(dev);
191193
struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc);
192194
struct drm_crtc_state *state = crtc->state;
193195
struct drm_display_mode *mode = &state->adjusted_mode;
@@ -217,6 +219,16 @@ static void vc4_crtc_mode_set_nofb(struct drm_crtc *crtc)
217219
PV_HORZB_HFP) |
218220
VC4_SET_FIELD(mode->hdisplay, PV_HORZB_HACTIVE));
219221

222+
CRTC_WRITE(PV_VERTA,
223+
VC4_SET_FIELD(mode->vtotal - mode->vsync_end,
224+
PV_VERTA_VBP) |
225+
VC4_SET_FIELD(mode->vsync_end - mode->vsync_start,
226+
PV_VERTA_VSYNC));
227+
CRTC_WRITE(PV_VERTB,
228+
VC4_SET_FIELD(mode->vsync_start - mode->vdisplay,
229+
PV_VERTB_VFP) |
230+
VC4_SET_FIELD(vactive, PV_VERTB_VACTIVE));
231+
220232
if (interlace) {
221233
CRTC_WRITE(PV_VERTA_EVEN,
222234
VC4_SET_FIELD(mode->vtotal - mode->vsync_end - 1,
@@ -246,6 +258,10 @@ static void vc4_crtc_mode_set_nofb(struct drm_crtc *crtc)
246258
PV_CONTROL_FIFO_CLR |
247259
PV_CONTROL_EN);
248260

261+
HVS_WRITE(SCALER_DISPBKGNDX(vc4_crtc->channel),
262+
SCALER_DISPBKGND_AUTOHS |
263+
(interlace ? SCALER_DISPBKGND_INTERLACE : 0));
264+
249265
if (debug_dump_regs) {
250266
DRM_INFO("CRTC %d regs after:\n", drm_crtc_index(crtc));
251267
vc4_crtc_dump_regs(vc4_crtc);
@@ -527,6 +543,7 @@ static int vc4_async_page_flip(struct drm_crtc *crtc,
527543
/* Make sure all other async modesetes have landed. */
528544
ret = down_interruptible(&vc4->async_modeset);
529545
if (ret) {
546+
drm_framebuffer_unreference(fb);
530547
kfree(flip_state);
531548
return ret;
532549
}

drivers/gpu/drm/vc4/vc4_hdmi.c

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,7 @@ static const struct {
9595
HDMI_REG(VC4_HDMI_SW_RESET_CONTROL),
9696
HDMI_REG(VC4_HDMI_HOTPLUG_INT),
9797
HDMI_REG(VC4_HDMI_HOTPLUG),
98+
HDMI_REG(VC4_HDMI_RAM_PACKET_CONFIG),
9899
HDMI_REG(VC4_HDMI_HORZA),
99100
HDMI_REG(VC4_HDMI_HORZB),
100101
HDMI_REG(VC4_HDMI_FIFO_CTL),
@@ -495,6 +496,16 @@ static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data)
495496
goto err_put_i2c;
496497
}
497498

499+
/* This is the rate that is set by the firmware. The number
500+
* needs to be a bit higher than the pixel clock rate
501+
* (generally 148.5Mhz).
502+
*/
503+
ret = clk_set_rate(hdmi->hsm_clock, 163682864);
504+
if (ret) {
505+
DRM_ERROR("Failed to set HSM clock rate: %d\n", ret);
506+
goto err_unprepare_pix;
507+
}
508+
498509
ret = clk_prepare_enable(hdmi->hsm_clock);
499510
if (ret) {
500511
DRM_ERROR("Failed to turn on HDMI state machine clock: %d\n",
@@ -516,7 +527,24 @@ static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data)
516527
vc4->hdmi = hdmi;
517528

518529
/* HDMI core must be enabled. */
519-
WARN_ON_ONCE((HD_READ(VC4_HD_M_CTL) & VC4_HD_M_ENABLE) == 0);
530+
if (!(HD_READ(VC4_HD_M_CTL) & VC4_HD_M_ENABLE)) {
531+
HD_WRITE(VC4_HD_M_CTL, VC4_HD_M_SW_RST);
532+
udelay(1);
533+
HD_WRITE(VC4_HD_M_CTL, 0);
534+
535+
HD_WRITE(VC4_HD_M_CTL, VC4_HD_M_ENABLE);
536+
537+
HDMI_WRITE(VC4_HDMI_SW_RESET_CONTROL,
538+
VC4_HDMI_SW_RESET_HDMI |
539+
VC4_HDMI_SW_RESET_FORMAT_DETECT);
540+
541+
HDMI_WRITE(VC4_HDMI_SW_RESET_CONTROL, 0);
542+
543+
/* PHY should be in reset, like
544+
* vc4_hdmi_encoder_disable() does.
545+
*/
546+
HDMI_WRITE(VC4_HDMI_TX_PHY_RESET_CTL, 0xf << 16);
547+
}
520548

521549
drm_encoder_init(drm, hdmi->encoder, &vc4_hdmi_encoder_funcs,
522550
DRM_MODE_ENCODER_TMDS, NULL);

drivers/gpu/drm/vc4/vc4_regs.h

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -187,7 +187,7 @@
187187
# define PV_VCONTROL_CONTINUOUS BIT(1)
188188
# define PV_VCONTROL_VIDEN BIT(0)
189189

190-
#define PV_VSYNCD 0x08
190+
#define PV_VSYNCD_EVEN 0x08
191191

192192
#define PV_HORZA 0x0c
193193
# define PV_HORZA_HBP_MASK VC4_MASK(31, 16)
@@ -350,6 +350,17 @@
350350
# define SCALER_DISPCTRLX_HEIGHT_SHIFT 0
351351

352352
#define SCALER_DISPBKGND0 0x00000044
353+
# define SCALER_DISPBKGND_AUTOHS BIT(31)
354+
# define SCALER_DISPBKGND_INTERLACE BIT(30)
355+
# define SCALER_DISPBKGND_GAMMA BIT(29)
356+
# define SCALER_DISPBKGND_TESTMODE_MASK VC4_MASK(28, 25)
357+
# define SCALER_DISPBKGND_TESTMODE_SHIFT 25
358+
/* Enables filling the scaler line with the RGB value in the low 24
359+
* bits before compositing. Costs cycles, so should be skipped if
360+
* opaque display planes will cover everything.
361+
*/
362+
# define SCALER_DISPBKGND_FILL BIT(24)
363+
353364
#define SCALER_DISPSTAT0 0x00000048
354365
#define SCALER_DISPBASE0 0x0000004c
355366
# define SCALER_DISPSTATX_MODE_MASK VC4_MASK(31, 30)
@@ -362,6 +373,9 @@
362373
# define SCALER_DISPSTATX_EMPTY BIT(28)
363374
#define SCALER_DISPCTRL1 0x00000050
364375
#define SCALER_DISPBKGND1 0x00000054
376+
#define SCALER_DISPBKGNDX(x) (SCALER_DISPBKGND0 + \
377+
(x) * (SCALER_DISPBKGND1 - \
378+
SCALER_DISPBKGND0))
365379
#define SCALER_DISPSTAT1 0x00000058
366380
#define SCALER_DISPSTATX(x) (SCALER_DISPSTAT0 + \
367381
(x) * (SCALER_DISPSTAT1 - \
@@ -456,6 +470,8 @@
456470
#define VC4_HDMI_TX_PHY_RESET_CTL 0x2c0
457471

458472
#define VC4_HD_M_CTL 0x00c
473+
# define VC4_HD_M_REGISTER_FILE_STANDBY (3 << 6)
474+
# define VC4_HD_M_RAM_STANDBY (3 << 4)
459475
# define VC4_HD_M_SW_RST BIT(2)
460476
# define VC4_HD_M_ENABLE BIT(0)
461477

0 commit comments

Comments
 (0)