aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDave Airlie <airlied@redhat.com>2016-03-13 19:48:04 -0400
committerDave Airlie <airlied@redhat.com>2016-03-13 19:48:04 -0400
commit67d1c0a25c05e2105d12abd9c0172d2d5c0e7654 (patch)
treeec5478f2b8e7510656a9b64d1b607a53014f1c33
parentc3d7a1d1e61e0ae94a89fbd0e2d4ad1eed9499c6 (diff)
parent6a609209865247cc748e90158c99f374f79b494c (diff)
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.
-rw-r--r--drivers/gpu/drm/vc4/vc4_crtc.c19
-rw-r--r--drivers/gpu/drm/vc4/vc4_hdmi.c30
-rw-r--r--drivers/gpu/drm/vc4/vc4_regs.h18
3 files changed, 64 insertions, 3 deletions
diff --git a/drivers/gpu/drm/vc4/vc4_crtc.c b/drivers/gpu/drm/vc4/vc4_crtc.c
index 619dc781c517..355ee4b091b3 100644
--- a/drivers/gpu/drm/vc4/vc4_crtc.c
+++ b/drivers/gpu/drm/vc4/vc4_crtc.c
@@ -88,7 +88,7 @@ static const struct {
88} crtc_regs[] = { 88} crtc_regs[] = {
89 CRTC_REG(PV_CONTROL), 89 CRTC_REG(PV_CONTROL),
90 CRTC_REG(PV_V_CONTROL), 90 CRTC_REG(PV_V_CONTROL),
91 CRTC_REG(PV_VSYNCD), 91 CRTC_REG(PV_VSYNCD_EVEN),
92 CRTC_REG(PV_HORZA), 92 CRTC_REG(PV_HORZA),
93 CRTC_REG(PV_HORZB), 93 CRTC_REG(PV_HORZB),
94 CRTC_REG(PV_VERTA), 94 CRTC_REG(PV_VERTA),
@@ -188,6 +188,8 @@ static int vc4_get_clock_select(struct drm_crtc *crtc)
188 188
189static void vc4_crtc_mode_set_nofb(struct drm_crtc *crtc) 189static void vc4_crtc_mode_set_nofb(struct drm_crtc *crtc)
190{ 190{
191 struct drm_device *dev = crtc->dev;
192 struct vc4_dev *vc4 = to_vc4_dev(dev);
191 struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc); 193 struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc);
192 struct drm_crtc_state *state = crtc->state; 194 struct drm_crtc_state *state = crtc->state;
193 struct drm_display_mode *mode = &state->adjusted_mode; 195 struct drm_display_mode *mode = &state->adjusted_mode;
@@ -217,6 +219,16 @@ static void vc4_crtc_mode_set_nofb(struct drm_crtc *crtc)
217 PV_HORZB_HFP) | 219 PV_HORZB_HFP) |
218 VC4_SET_FIELD(mode->hdisplay, PV_HORZB_HACTIVE)); 220 VC4_SET_FIELD(mode->hdisplay, PV_HORZB_HACTIVE));
219 221
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
220 if (interlace) { 232 if (interlace) {
221 CRTC_WRITE(PV_VERTA_EVEN, 233 CRTC_WRITE(PV_VERTA_EVEN,
222 VC4_SET_FIELD(mode->vtotal - mode->vsync_end - 1, 234 VC4_SET_FIELD(mode->vtotal - mode->vsync_end - 1,
@@ -246,6 +258,10 @@ static void vc4_crtc_mode_set_nofb(struct drm_crtc *crtc)
246 PV_CONTROL_FIFO_CLR | 258 PV_CONTROL_FIFO_CLR |
247 PV_CONTROL_EN); 259 PV_CONTROL_EN);
248 260
261 HVS_WRITE(SCALER_DISPBKGNDX(vc4_crtc->channel),
262 SCALER_DISPBKGND_AUTOHS |
263 (interlace ? SCALER_DISPBKGND_INTERLACE : 0));
264
249 if (debug_dump_regs) { 265 if (debug_dump_regs) {
250 DRM_INFO("CRTC %d regs after:\n", drm_crtc_index(crtc)); 266 DRM_INFO("CRTC %d regs after:\n", drm_crtc_index(crtc));
251 vc4_crtc_dump_regs(vc4_crtc); 267 vc4_crtc_dump_regs(vc4_crtc);
@@ -527,6 +543,7 @@ static int vc4_async_page_flip(struct drm_crtc *crtc,
527 /* Make sure all other async modesetes have landed. */ 543 /* Make sure all other async modesetes have landed. */
528 ret = down_interruptible(&vc4->async_modeset); 544 ret = down_interruptible(&vc4->async_modeset);
529 if (ret) { 545 if (ret) {
546 drm_framebuffer_unreference(fb);
530 kfree(flip_state); 547 kfree(flip_state);
531 return ret; 548 return ret;
532 } 549 }
diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
index c69c0460196b..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 {
95 HDMI_REG(VC4_HDMI_SW_RESET_CONTROL), 95 HDMI_REG(VC4_HDMI_SW_RESET_CONTROL),
96 HDMI_REG(VC4_HDMI_HOTPLUG_INT), 96 HDMI_REG(VC4_HDMI_HOTPLUG_INT),
97 HDMI_REG(VC4_HDMI_HOTPLUG), 97 HDMI_REG(VC4_HDMI_HOTPLUG),
98 HDMI_REG(VC4_HDMI_RAM_PACKET_CONFIG),
98 HDMI_REG(VC4_HDMI_HORZA), 99 HDMI_REG(VC4_HDMI_HORZA),
99 HDMI_REG(VC4_HDMI_HORZB), 100 HDMI_REG(VC4_HDMI_HORZB),
100 HDMI_REG(VC4_HDMI_FIFO_CTL), 101 HDMI_REG(VC4_HDMI_FIFO_CTL),
@@ -495,6 +496,16 @@ static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data)
495 goto err_put_i2c; 496 goto err_put_i2c;
496 } 497 }
497 498
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
498 ret = clk_prepare_enable(hdmi->hsm_clock); 509 ret = clk_prepare_enable(hdmi->hsm_clock);
499 if (ret) { 510 if (ret) {
500 DRM_ERROR("Failed to turn on HDMI state machine clock: %d\n", 511 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)
516 vc4->hdmi = hdmi; 527 vc4->hdmi = hdmi;
517 528
518 /* HDMI core must be enabled. */ 529 /* 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 }
520 548
521 drm_encoder_init(drm, hdmi->encoder, &vc4_hdmi_encoder_funcs, 549 drm_encoder_init(drm, hdmi->encoder, &vc4_hdmi_encoder_funcs,
522 DRM_MODE_ENCODER_TMDS, NULL); 550 DRM_MODE_ENCODER_TMDS, NULL);
diff --git a/drivers/gpu/drm/vc4/vc4_regs.h b/drivers/gpu/drm/vc4/vc4_regs.h
index 25df20ef939c..bf42a8e87111 100644
--- a/drivers/gpu/drm/vc4/vc4_regs.h
+++ b/drivers/gpu/drm/vc4/vc4_regs.h
@@ -187,7 +187,7 @@
187# define PV_VCONTROL_CONTINUOUS BIT(1) 187# define PV_VCONTROL_CONTINUOUS BIT(1)
188# define PV_VCONTROL_VIDEN BIT(0) 188# define PV_VCONTROL_VIDEN BIT(0)
189 189
190#define PV_VSYNCD 0x08 190#define PV_VSYNCD_EVEN 0x08
191 191
192#define PV_HORZA 0x0c 192#define PV_HORZA 0x0c
193# define PV_HORZA_HBP_MASK VC4_MASK(31, 16) 193# define PV_HORZA_HBP_MASK VC4_MASK(31, 16)
@@ -350,6 +350,17 @@
350# define SCALER_DISPCTRLX_HEIGHT_SHIFT 0 350# define SCALER_DISPCTRLX_HEIGHT_SHIFT 0
351 351
352#define SCALER_DISPBKGND0 0x00000044 352#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
353#define SCALER_DISPSTAT0 0x00000048 364#define SCALER_DISPSTAT0 0x00000048
354#define SCALER_DISPBASE0 0x0000004c 365#define SCALER_DISPBASE0 0x0000004c
355# define SCALER_DISPSTATX_MODE_MASK VC4_MASK(31, 30) 366# define SCALER_DISPSTATX_MODE_MASK VC4_MASK(31, 30)
@@ -362,6 +373,9 @@
362# define SCALER_DISPSTATX_EMPTY BIT(28) 373# define SCALER_DISPSTATX_EMPTY BIT(28)
363#define SCALER_DISPCTRL1 0x00000050 374#define SCALER_DISPCTRL1 0x00000050
364#define SCALER_DISPBKGND1 0x00000054 375#define SCALER_DISPBKGND1 0x00000054
376#define SCALER_DISPBKGNDX(x) (SCALER_DISPBKGND0 + \
377 (x) * (SCALER_DISPBKGND1 - \
378 SCALER_DISPBKGND0))
365#define SCALER_DISPSTAT1 0x00000058 379#define SCALER_DISPSTAT1 0x00000058
366#define SCALER_DISPSTATX(x) (SCALER_DISPSTAT0 + \ 380#define SCALER_DISPSTATX(x) (SCALER_DISPSTAT0 + \
367 (x) * (SCALER_DISPSTAT1 - \ 381 (x) * (SCALER_DISPSTAT1 - \
@@ -456,6 +470,8 @@
456#define VC4_HDMI_TX_PHY_RESET_CTL 0x2c0 470#define VC4_HDMI_TX_PHY_RESET_CTL 0x2c0
457 471
458#define VC4_HD_M_CTL 0x00c 472#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)
459# define VC4_HD_M_SW_RST BIT(2) 475# define VC4_HD_M_SW_RST BIT(2)
460# define VC4_HD_M_ENABLE BIT(0) 476# define VC4_HD_M_ENABLE BIT(0)
461 477