aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm
diff options
context:
space:
mode:
authorDave Airlie <airlied@redhat.com>2015-01-20 19:16:24 -0500
committerDave Airlie <airlied@redhat.com>2015-01-20 19:16:24 -0500
commitb2eb0489809cf0b824357b6fa85aab1aabe3f063 (patch)
treed6b4bf3f4bd2f63f00bbcb9afdf2c39f396504b5 /drivers/gpu/drm
parent4f4d89af78682f2ed1cf6745794804817f867bba (diff)
parent906eff7fcada4186cde54eb89572fb774ab294a0 (diff)
Merge branch 'drm/next/du' of git://linuxtv.org/pinchartl/fbdev into drm-next
* 'drm/next/du' of git://linuxtv.org/pinchartl/fbdev: drm: rcar-du: Implement support for interlaced modes drm: rcar-du: Clamp DPMS states to on and off drm: rcar-du: Enable hotplug detection on HDMI connector drm: rcar-du: Output HSYNC instead of CSYNC drm: rcar-du: Add support for external pixel clock drm: rcar-du: Refactor DEFR8 feature drm: rcar-du: Remove LVDS and HDMI encoders chaining restriction drm: rcar-du: Configure pitch for chroma plane of multiplanar formats drm: rcar-du: Don't fail probe in case of partial encoder init error drm: adv7511: Remove interlaced mode check
Diffstat (limited to 'drivers/gpu/drm')
-rw-r--r--drivers/gpu/drm/i2c/adv7511.c3
-rw-r--r--drivers/gpu/drm/rcar-du/rcar_du_crtc.c95
-rw-r--r--drivers/gpu/drm/rcar-du/rcar_du_crtc.h1
-rw-r--r--drivers/gpu/drm/rcar-du/rcar_du_drv.c6
-rw-r--r--drivers/gpu/drm/rcar-du/rcar_du_drv.h2
-rw-r--r--drivers/gpu/drm/rcar-du/rcar_du_encoder.c34
-rw-r--r--drivers/gpu/drm/rcar-du/rcar_du_group.c21
-rw-r--r--drivers/gpu/drm/rcar-du/rcar_du_hdmicon.c2
-rw-r--r--drivers/gpu/drm/rcar-du/rcar_du_hdmienc.c18
-rw-r--r--drivers/gpu/drm/rcar-du/rcar_du_kms.c15
-rw-r--r--drivers/gpu/drm/rcar-du/rcar_du_plane.c20
-rw-r--r--drivers/gpu/drm/rcar-du/rcar_du_regs.h5
-rw-r--r--drivers/gpu/drm/rcar-du/rcar_du_vgacon.c1
13 files changed, 176 insertions, 47 deletions
diff --git a/drivers/gpu/drm/i2c/adv7511.c b/drivers/gpu/drm/i2c/adv7511.c
index faf1c0c5ab2e..fa140e04d5fa 100644
--- a/drivers/gpu/drm/i2c/adv7511.c
+++ b/drivers/gpu/drm/i2c/adv7511.c
@@ -644,9 +644,6 @@ static int adv7511_encoder_mode_valid(struct drm_encoder *encoder,
644 if (mode->clock > 165000) 644 if (mode->clock > 165000)
645 return MODE_CLOCK_HIGH; 645 return MODE_CLOCK_HIGH;
646 646
647 if (mode->flags & DRM_MODE_FLAG_INTERLACE)
648 return MODE_NO_INTERLACE;
649
650 return MODE_OK; 647 return MODE_OK;
651} 648}
652 649
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c
index 23cc910951f4..25c7a998fc2c 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c
@@ -74,39 +74,77 @@ static int rcar_du_crtc_get(struct rcar_du_crtc *rcrtc)
74 if (ret < 0) 74 if (ret < 0)
75 return ret; 75 return ret;
76 76
77 ret = clk_prepare_enable(rcrtc->extclock);
78 if (ret < 0)
79 goto error_clock;
80
77 ret = rcar_du_group_get(rcrtc->group); 81 ret = rcar_du_group_get(rcrtc->group);
78 if (ret < 0) 82 if (ret < 0)
79 clk_disable_unprepare(rcrtc->clock); 83 goto error_group;
84
85 return 0;
80 86
87error_group:
88 clk_disable_unprepare(rcrtc->extclock);
89error_clock:
90 clk_disable_unprepare(rcrtc->clock);
81 return ret; 91 return ret;
82} 92}
83 93
84static void rcar_du_crtc_put(struct rcar_du_crtc *rcrtc) 94static void rcar_du_crtc_put(struct rcar_du_crtc *rcrtc)
85{ 95{
86 rcar_du_group_put(rcrtc->group); 96 rcar_du_group_put(rcrtc->group);
97
98 clk_disable_unprepare(rcrtc->extclock);
87 clk_disable_unprepare(rcrtc->clock); 99 clk_disable_unprepare(rcrtc->clock);
88} 100}
89 101
90static void rcar_du_crtc_set_display_timing(struct rcar_du_crtc *rcrtc) 102static void rcar_du_crtc_set_display_timing(struct rcar_du_crtc *rcrtc)
91{ 103{
92 const struct drm_display_mode *mode = &rcrtc->crtc.mode; 104 const struct drm_display_mode *mode = &rcrtc->crtc.mode;
105 unsigned long mode_clock = mode->clock * 1000;
93 unsigned long clk; 106 unsigned long clk;
94 u32 value; 107 u32 value;
108 u32 escr;
95 u32 div; 109 u32 div;
96 110
97 /* Dot clock */ 111 /* Compute the clock divisor and select the internal or external dot
112 * clock based on the requested frequency.
113 */
98 clk = clk_get_rate(rcrtc->clock); 114 clk = clk_get_rate(rcrtc->clock);
99 div = DIV_ROUND_CLOSEST(clk, mode->clock * 1000); 115 div = DIV_ROUND_CLOSEST(clk, mode_clock);
100 div = clamp(div, 1U, 64U) - 1; 116 div = clamp(div, 1U, 64U) - 1;
117 escr = div | ESCR_DCLKSEL_CLKS;
118
119 if (rcrtc->extclock) {
120 unsigned long extclk;
121 unsigned long extrate;
122 unsigned long rate;
123 u32 extdiv;
124
125 extclk = clk_get_rate(rcrtc->extclock);
126 extdiv = DIV_ROUND_CLOSEST(extclk, mode_clock);
127 extdiv = clamp(extdiv, 1U, 64U) - 1;
128
129 rate = clk / (div + 1);
130 extrate = extclk / (extdiv + 1);
131
132 if (abs((long)extrate - (long)mode_clock) <
133 abs((long)rate - (long)mode_clock)) {
134 dev_dbg(rcrtc->group->dev->dev,
135 "crtc%u: using external clock\n", rcrtc->index);
136 escr = extdiv | ESCR_DCLKSEL_DCLKIN;
137 }
138 }
101 139
102 rcar_du_group_write(rcrtc->group, rcrtc->index % 2 ? ESCR2 : ESCR, 140 rcar_du_group_write(rcrtc->group, rcrtc->index % 2 ? ESCR2 : ESCR,
103 ESCR_DCLKSEL_CLKS | div); 141 escr);
104 rcar_du_group_write(rcrtc->group, rcrtc->index % 2 ? OTAR2 : OTAR, 0); 142 rcar_du_group_write(rcrtc->group, rcrtc->index % 2 ? OTAR2 : OTAR, 0);
105 143
106 /* Signal polarities */ 144 /* Signal polarities */
107 value = ((mode->flags & DRM_MODE_FLAG_PVSYNC) ? 0 : DSMR_VSL) 145 value = ((mode->flags & DRM_MODE_FLAG_PVSYNC) ? 0 : DSMR_VSL)
108 | ((mode->flags & DRM_MODE_FLAG_PHSYNC) ? 0 : DSMR_HSL) 146 | ((mode->flags & DRM_MODE_FLAG_PHSYNC) ? 0 : DSMR_HSL)
109 | DSMR_DIPM_DE; 147 | DSMR_DIPM_DE | DSMR_CSPM;
110 rcar_du_crtc_write(rcrtc, DSMR, value); 148 rcar_du_crtc_write(rcrtc, DSMR, value);
111 149
112 /* Display timings */ 150 /* Display timings */
@@ -117,12 +155,15 @@ static void rcar_du_crtc_set_display_timing(struct rcar_du_crtc *rcrtc)
117 mode->hsync_start - 1); 155 mode->hsync_start - 1);
118 rcar_du_crtc_write(rcrtc, HCR, mode->htotal - 1); 156 rcar_du_crtc_write(rcrtc, HCR, mode->htotal - 1);
119 157
120 rcar_du_crtc_write(rcrtc, VDSR, mode->vtotal - mode->vsync_end - 2); 158 rcar_du_crtc_write(rcrtc, VDSR, mode->crtc_vtotal -
121 rcar_du_crtc_write(rcrtc, VDER, mode->vtotal - mode->vsync_end + 159 mode->crtc_vsync_end - 2);
122 mode->vdisplay - 2); 160 rcar_du_crtc_write(rcrtc, VDER, mode->crtc_vtotal -
123 rcar_du_crtc_write(rcrtc, VSPR, mode->vtotal - mode->vsync_end + 161 mode->crtc_vsync_end +
124 mode->vsync_start - 1); 162 mode->crtc_vdisplay - 2);
125 rcar_du_crtc_write(rcrtc, VCR, mode->vtotal - 1); 163 rcar_du_crtc_write(rcrtc, VSPR, mode->crtc_vtotal -
164 mode->crtc_vsync_end +
165 mode->crtc_vsync_start - 1);
166 rcar_du_crtc_write(rcrtc, VCR, mode->crtc_vtotal - 1);
126 167
127 rcar_du_crtc_write(rcrtc, DESR, mode->htotal - mode->hsync_start); 168 rcar_du_crtc_write(rcrtc, DESR, mode->htotal - mode->hsync_start);
128 rcar_du_crtc_write(rcrtc, DEWR, mode->hdisplay); 169 rcar_du_crtc_write(rcrtc, DEWR, mode->hdisplay);
@@ -139,9 +180,10 @@ void rcar_du_crtc_route_output(struct drm_crtc *crtc,
139 */ 180 */
140 rcrtc->outputs |= BIT(output); 181 rcrtc->outputs |= BIT(output);
141 182
142 /* Store RGB routing to DPAD0 for R8A7790. */ 183 /* Store RGB routing to DPAD0, the hardware will be configured when
143 if (rcar_du_has(rcdu, RCAR_DU_FEATURE_DEFR8) && 184 * starting the CRTC.
144 output == RCAR_DU_OUTPUT_DPAD0) 185 */
186 if (output == RCAR_DU_OUTPUT_DPAD0)
145 rcdu->dpad0_source = rcrtc->index; 187 rcdu->dpad0_source = rcrtc->index;
146} 188}
147 189
@@ -217,6 +259,7 @@ void rcar_du_crtc_update_planes(struct drm_crtc *crtc)
217static void rcar_du_crtc_start(struct rcar_du_crtc *rcrtc) 259static void rcar_du_crtc_start(struct rcar_du_crtc *rcrtc)
218{ 260{
219 struct drm_crtc *crtc = &rcrtc->crtc; 261 struct drm_crtc *crtc = &rcrtc->crtc;
262 bool interlaced;
220 unsigned int i; 263 unsigned int i;
221 264
222 if (rcrtc->started) 265 if (rcrtc->started)
@@ -252,7 +295,10 @@ static void rcar_du_crtc_start(struct rcar_du_crtc *rcrtc)
252 * sync mode (with the HSYNC and VSYNC signals configured as outputs and 295 * sync mode (with the HSYNC and VSYNC signals configured as outputs and
253 * actively driven). 296 * actively driven).
254 */ 297 */
255 rcar_du_crtc_clr_set(rcrtc, DSYSR, DSYSR_TVM_MASK, DSYSR_TVM_MASTER); 298 interlaced = rcrtc->crtc.mode.flags & DRM_MODE_FLAG_INTERLACE;
299 rcar_du_crtc_clr_set(rcrtc, DSYSR, DSYSR_TVM_MASK | DSYSR_SCM_MASK,
300 (interlaced ? DSYSR_SCM_INT_VIDEO : 0) |
301 DSYSR_TVM_MASTER);
256 302
257 rcar_du_group_start_stop(rcrtc->group, true); 303 rcar_du_group_start_stop(rcrtc->group, true);
258 304
@@ -308,6 +354,9 @@ static void rcar_du_crtc_dpms(struct drm_crtc *crtc, int mode)
308{ 354{
309 struct rcar_du_crtc *rcrtc = to_rcar_crtc(crtc); 355 struct rcar_du_crtc *rcrtc = to_rcar_crtc(crtc);
310 356
357 if (mode != DRM_MODE_DPMS_ON)
358 mode = DRM_MODE_DPMS_OFF;
359
311 if (rcrtc->dpms == mode) 360 if (rcrtc->dpms == mode)
312 return; 361 return;
313 362
@@ -486,7 +535,7 @@ static irqreturn_t rcar_du_crtc_irq(int irq, void *arg)
486 status = rcar_du_crtc_read(rcrtc, DSSR); 535 status = rcar_du_crtc_read(rcrtc, DSSR);
487 rcar_du_crtc_write(rcrtc, DSRCR, status & DSRCR_MASK); 536 rcar_du_crtc_write(rcrtc, DSRCR, status & DSRCR_MASK);
488 537
489 if (status & DSSR_VBK) { 538 if (status & DSSR_FRM) {
490 drm_handle_vblank(rcrtc->crtc.dev, rcrtc->index); 539 drm_handle_vblank(rcrtc->crtc.dev, rcrtc->index);
491 rcar_du_crtc_finish_page_flip(rcrtc); 540 rcar_du_crtc_finish_page_flip(rcrtc);
492 ret = IRQ_HANDLED; 541 ret = IRQ_HANDLED;
@@ -542,12 +591,13 @@ int rcar_du_crtc_create(struct rcar_du_group *rgrp, unsigned int index)
542 struct rcar_du_crtc *rcrtc = &rcdu->crtcs[index]; 591 struct rcar_du_crtc *rcrtc = &rcdu->crtcs[index];
543 struct drm_crtc *crtc = &rcrtc->crtc; 592 struct drm_crtc *crtc = &rcrtc->crtc;
544 unsigned int irqflags; 593 unsigned int irqflags;
545 char clk_name[5]; 594 struct clk *clk;
595 char clk_name[9];
546 char *name; 596 char *name;
547 int irq; 597 int irq;
548 int ret; 598 int ret;
549 599
550 /* Get the CRTC clock. */ 600 /* Get the CRTC clock and the optional external clock. */
551 if (rcar_du_has(rcdu, RCAR_DU_FEATURE_CRTC_IRQ_CLOCK)) { 601 if (rcar_du_has(rcdu, RCAR_DU_FEATURE_CRTC_IRQ_CLOCK)) {
552 sprintf(clk_name, "du.%u", index); 602 sprintf(clk_name, "du.%u", index);
553 name = clk_name; 603 name = clk_name;
@@ -561,6 +611,15 @@ int rcar_du_crtc_create(struct rcar_du_group *rgrp, unsigned int index)
561 return PTR_ERR(rcrtc->clock); 611 return PTR_ERR(rcrtc->clock);
562 } 612 }
563 613
614 sprintf(clk_name, "dclkin.%u", index);
615 clk = devm_clk_get(rcdu->dev, clk_name);
616 if (!IS_ERR(clk)) {
617 rcrtc->extclock = clk;
618 } else if (PTR_ERR(rcrtc->clock) == -EPROBE_DEFER) {
619 dev_info(rcdu->dev, "can't get external clock %u\n", index);
620 return -EPROBE_DEFER;
621 }
622
564 rcrtc->group = rgrp; 623 rcrtc->group = rgrp;
565 rcrtc->mmio_offset = mmio_offsets[index]; 624 rcrtc->mmio_offset = mmio_offsets[index];
566 rcrtc->index = index; 625 rcrtc->index = index;
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_crtc.h b/drivers/gpu/drm/rcar-du/rcar_du_crtc.h
index 984e6083699f..d2f89f7d2e5e 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_crtc.h
+++ b/drivers/gpu/drm/rcar-du/rcar_du_crtc.h
@@ -26,6 +26,7 @@ struct rcar_du_crtc {
26 struct drm_crtc crtc; 26 struct drm_crtc crtc;
27 27
28 struct clk *clock; 28 struct clk *clock;
29 struct clk *extclock;
29 unsigned int mmio_offset; 30 unsigned int mmio_offset;
30 unsigned int index; 31 unsigned int index;
31 bool started; 32 bool started;
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_drv.c b/drivers/gpu/drm/rcar-du/rcar_du_drv.c
index 7bfa09cf18d5..e0d74f821416 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_drv.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_drv.c
@@ -56,7 +56,8 @@ static const struct rcar_du_device_info rcar_du_r8a7779_info = {
56}; 56};
57 57
58static const struct rcar_du_device_info rcar_du_r8a7790_info = { 58static const struct rcar_du_device_info rcar_du_r8a7790_info = {
59 .features = RCAR_DU_FEATURE_CRTC_IRQ_CLOCK | RCAR_DU_FEATURE_DEFR8, 59 .features = RCAR_DU_FEATURE_CRTC_IRQ_CLOCK
60 | RCAR_DU_FEATURE_EXT_CTRL_REGS,
60 .quirks = RCAR_DU_QUIRK_ALIGN_128B | RCAR_DU_QUIRK_LVDS_LANES, 61 .quirks = RCAR_DU_QUIRK_ALIGN_128B | RCAR_DU_QUIRK_LVDS_LANES,
61 .num_crtcs = 3, 62 .num_crtcs = 3,
62 .routes = { 63 .routes = {
@@ -83,7 +84,8 @@ static const struct rcar_du_device_info rcar_du_r8a7790_info = {
83}; 84};
84 85
85static const struct rcar_du_device_info rcar_du_r8a7791_info = { 86static const struct rcar_du_device_info rcar_du_r8a7791_info = {
86 .features = RCAR_DU_FEATURE_CRTC_IRQ_CLOCK | RCAR_DU_FEATURE_DEFR8, 87 .features = RCAR_DU_FEATURE_CRTC_IRQ_CLOCK
88 | RCAR_DU_FEATURE_EXT_CTRL_REGS,
87 .num_crtcs = 2, 89 .num_crtcs = 2,
88 .routes = { 90 .routes = {
89 /* R8A7791 has one RGB output, one LVDS output and one 91 /* R8A7791 has one RGB output, one LVDS output and one
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_drv.h b/drivers/gpu/drm/rcar-du/rcar_du_drv.h
index 0a724669f02d..c5b9ea6a7eaa 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_drv.h
+++ b/drivers/gpu/drm/rcar-du/rcar_du_drv.h
@@ -27,7 +27,7 @@ struct rcar_du_device;
27struct rcar_du_lvdsenc; 27struct rcar_du_lvdsenc;
28 28
29#define RCAR_DU_FEATURE_CRTC_IRQ_CLOCK (1 << 0) /* Per-CRTC IRQ and clock */ 29#define RCAR_DU_FEATURE_CRTC_IRQ_CLOCK (1 << 0) /* Per-CRTC IRQ and clock */
30#define RCAR_DU_FEATURE_DEFR8 (1 << 1) /* Has DEFR8 register */ 30#define RCAR_DU_FEATURE_EXT_CTRL_REGS (1 << 1) /* Has extended control registers */
31 31
32#define RCAR_DU_QUIRK_ALIGN_128B (1 << 0) /* Align pitches to 128 bytes */ 32#define RCAR_DU_QUIRK_ALIGN_128B (1 << 0) /* Align pitches to 128 bytes */
33#define RCAR_DU_QUIRK_LVDS_LANES (1 << 1) /* LVDS lanes 1 and 3 inverted */ 33#define RCAR_DU_QUIRK_LVDS_LANES (1 << 1) /* LVDS lanes 1 and 3 inverted */
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_encoder.c b/drivers/gpu/drm/rcar-du/rcar_du_encoder.c
index 34a122a39664..279167f783f6 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_encoder.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_encoder.c
@@ -46,6 +46,9 @@ static void rcar_du_encoder_dpms(struct drm_encoder *encoder, int mode)
46{ 46{
47 struct rcar_du_encoder *renc = to_rcar_encoder(encoder); 47 struct rcar_du_encoder *renc = to_rcar_encoder(encoder);
48 48
49 if (mode != DRM_MODE_DPMS_ON)
50 mode = DRM_MODE_DPMS_OFF;
51
49 if (renc->lvds) 52 if (renc->lvds)
50 rcar_du_lvdsenc_dpms(renc->lvds, encoder->crtc, mode); 53 rcar_du_lvdsenc_dpms(renc->lvds, encoder->crtc, mode);
51} 54}
@@ -190,35 +193,42 @@ int rcar_du_encoder_init(struct rcar_du_device *rcdu,
190 } 193 }
191 194
192 if (type == RCAR_DU_ENCODER_HDMI) { 195 if (type == RCAR_DU_ENCODER_HDMI) {
193 if (renc->lvds) {
194 dev_err(rcdu->dev,
195 "Chaining LVDS and HDMI encoders not supported\n");
196 return -EINVAL;
197 }
198
199 ret = rcar_du_hdmienc_init(rcdu, renc, enc_node); 196 ret = rcar_du_hdmienc_init(rcdu, renc, enc_node);
200 if (ret < 0) 197 if (ret < 0)
201 return ret; 198 goto done;
202 } else { 199 } else {
203 ret = drm_encoder_init(rcdu->ddev, encoder, &encoder_funcs, 200 ret = drm_encoder_init(rcdu->ddev, encoder, &encoder_funcs,
204 encoder_type); 201 encoder_type);
205 if (ret < 0) 202 if (ret < 0)
206 return ret; 203 goto done;
207 204
208 drm_encoder_helper_add(encoder, &encoder_helper_funcs); 205 drm_encoder_helper_add(encoder, &encoder_helper_funcs);
209 } 206 }
210 207
211 switch (encoder_type) { 208 switch (encoder_type) {
212 case DRM_MODE_ENCODER_LVDS: 209 case DRM_MODE_ENCODER_LVDS:
213 return rcar_du_lvds_connector_init(rcdu, renc, con_node); 210 ret = rcar_du_lvds_connector_init(rcdu, renc, con_node);
211 break;
214 212
215 case DRM_MODE_ENCODER_DAC: 213 case DRM_MODE_ENCODER_DAC:
216 return rcar_du_vga_connector_init(rcdu, renc); 214 ret = rcar_du_vga_connector_init(rcdu, renc);
215 break;
217 216
218 case DRM_MODE_ENCODER_TMDS: 217 case DRM_MODE_ENCODER_TMDS:
219 return rcar_du_hdmi_connector_init(rcdu, renc); 218 ret = rcar_du_hdmi_connector_init(rcdu, renc);
219 break;
220 220
221 default: 221 default:
222 return -EINVAL; 222 ret = -EINVAL;
223 break;
223 } 224 }
225
226done:
227 if (ret < 0) {
228 if (encoder->name)
229 encoder->funcs->destroy(encoder);
230 devm_kfree(rcdu->dev, renc);
231 }
232
233 return ret;
224} 234}
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_group.c b/drivers/gpu/drm/rcar-du/rcar_du_group.c
index 4e7614b145db..1bdc0ee0c248 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_group.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_group.c
@@ -48,9 +48,6 @@ static void rcar_du_group_setup_defr8(struct rcar_du_group *rgrp)
48{ 48{
49 u32 defr8 = DEFR8_CODE | DEFR8_DEFE8; 49 u32 defr8 = DEFR8_CODE | DEFR8_DEFE8;
50 50
51 if (!rcar_du_has(rgrp->dev, RCAR_DU_FEATURE_DEFR8))
52 return;
53
54 /* The DEFR8 register for the first group also controls RGB output 51 /* The DEFR8 register for the first group also controls RGB output
55 * routing to DPAD0 52 * routing to DPAD0
56 */ 53 */
@@ -69,7 +66,20 @@ static void rcar_du_group_setup(struct rcar_du_group *rgrp)
69 rcar_du_group_write(rgrp, DEFR4, DEFR4_CODE); 66 rcar_du_group_write(rgrp, DEFR4, DEFR4_CODE);
70 rcar_du_group_write(rgrp, DEFR5, DEFR5_CODE | DEFR5_DEFE5); 67 rcar_du_group_write(rgrp, DEFR5, DEFR5_CODE | DEFR5_DEFE5);
71 68
72 rcar_du_group_setup_defr8(rgrp); 69 if (rcar_du_has(rgrp->dev, RCAR_DU_FEATURE_EXT_CTRL_REGS)) {
70 rcar_du_group_setup_defr8(rgrp);
71
72 /* Configure input dot clock routing. We currently hardcode the
73 * configuration to routing DOTCLKINn to DUn.
74 */
75 rcar_du_group_write(rgrp, DIDSR, DIDSR_CODE |
76 DIDSR_LCDS_DCLKIN(2) |
77 DIDSR_LCDS_DCLKIN(1) |
78 DIDSR_LCDS_DCLKIN(0) |
79 DIDSR_PDCS_CLK(2, 0) |
80 DIDSR_PDCS_CLK(1, 0) |
81 DIDSR_PDCS_CLK(0, 0));
82 }
73 83
74 /* Use DS1PR and DS2PR to configure planes priorities and connects the 84 /* Use DS1PR and DS2PR to configure planes priorities and connects the
75 * superposition 0 to DU0 pins. DU1 pins will be configured dynamically. 85 * superposition 0 to DU0 pins. DU1 pins will be configured dynamically.
@@ -149,6 +159,9 @@ static int rcar_du_set_dpad0_routing(struct rcar_du_device *rcdu)
149{ 159{
150 int ret; 160 int ret;
151 161
162 if (!rcar_du_has(rcdu, RCAR_DU_FEATURE_EXT_CTRL_REGS))
163 return 0;
164
152 /* RGB output routing to DPAD0 is configured in the DEFR8 register of 165 /* RGB output routing to DPAD0 is configured in the DEFR8 register of
153 * the first group. As this function can be called with the DU0 and DU1 166 * the first group. As this function can be called with the DU0 and DU1
154 * CRTCs disabled, we need to enable the first group clock before 167 * CRTCs disabled, we need to enable the first group clock before
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_hdmicon.c b/drivers/gpu/drm/rcar-du/rcar_du_hdmicon.c
index 4d7d4dd46d26..ca94b029ac80 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_hdmicon.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_hdmicon.c
@@ -95,6 +95,8 @@ int rcar_du_hdmi_connector_init(struct rcar_du_device *rcdu,
95 connector = &rcon->connector; 95 connector = &rcon->connector;
96 connector->display_info.width_mm = 0; 96 connector->display_info.width_mm = 0;
97 connector->display_info.height_mm = 0; 97 connector->display_info.height_mm = 0;
98 connector->interlace_allowed = true;
99 connector->polled = DRM_CONNECTOR_POLL_HPD;
98 100
99 ret = drm_connector_init(rcdu->ddev, connector, &connector_funcs, 101 ret = drm_connector_init(rcdu->ddev, connector, &connector_funcs,
100 DRM_MODE_CONNECTOR_HDMIA); 102 DRM_MODE_CONNECTOR_HDMIA);
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_hdmienc.c b/drivers/gpu/drm/rcar-du/rcar_du_hdmienc.c
index 359bc999a9c8..221f0a17fd6a 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_hdmienc.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_hdmienc.c
@@ -21,6 +21,7 @@
21#include "rcar_du_drv.h" 21#include "rcar_du_drv.h"
22#include "rcar_du_encoder.h" 22#include "rcar_du_encoder.h"
23#include "rcar_du_hdmienc.h" 23#include "rcar_du_hdmienc.h"
24#include "rcar_du_lvdsenc.h"
24 25
25struct rcar_du_hdmienc { 26struct rcar_du_hdmienc {
26 struct rcar_du_encoder *renc; 27 struct rcar_du_encoder *renc;
@@ -36,12 +37,21 @@ static void rcar_du_hdmienc_dpms(struct drm_encoder *encoder, int mode)
36 struct rcar_du_hdmienc *hdmienc = to_rcar_hdmienc(encoder); 37 struct rcar_du_hdmienc *hdmienc = to_rcar_hdmienc(encoder);
37 struct drm_encoder_slave_funcs *sfuncs = to_slave_funcs(encoder); 38 struct drm_encoder_slave_funcs *sfuncs = to_slave_funcs(encoder);
38 39
40 if (mode != DRM_MODE_DPMS_ON)
41 mode = DRM_MODE_DPMS_OFF;
42
39 if (hdmienc->dpms == mode) 43 if (hdmienc->dpms == mode)
40 return; 44 return;
41 45
46 if (mode == DRM_MODE_DPMS_ON && hdmienc->renc->lvds)
47 rcar_du_lvdsenc_dpms(hdmienc->renc->lvds, encoder->crtc, mode);
48
42 if (sfuncs->dpms) 49 if (sfuncs->dpms)
43 sfuncs->dpms(encoder, mode); 50 sfuncs->dpms(encoder, mode);
44 51
52 if (mode != DRM_MODE_DPMS_ON && hdmienc->renc->lvds)
53 rcar_du_lvdsenc_dpms(hdmienc->renc->lvds, encoder->crtc, mode);
54
45 hdmienc->dpms = mode; 55 hdmienc->dpms = mode;
46} 56}
47 57
@@ -49,8 +59,16 @@ static bool rcar_du_hdmienc_mode_fixup(struct drm_encoder *encoder,
49 const struct drm_display_mode *mode, 59 const struct drm_display_mode *mode,
50 struct drm_display_mode *adjusted_mode) 60 struct drm_display_mode *adjusted_mode)
51{ 61{
62 struct rcar_du_hdmienc *hdmienc = to_rcar_hdmienc(encoder);
52 struct drm_encoder_slave_funcs *sfuncs = to_slave_funcs(encoder); 63 struct drm_encoder_slave_funcs *sfuncs = to_slave_funcs(encoder);
53 64
65 /* The internal LVDS encoder has a clock frequency operating range of
66 * 30MHz to 150MHz. Clamp the clock accordingly.
67 */
68 if (hdmienc->renc->lvds)
69 adjusted_mode->clock = clamp(adjusted_mode->clock,
70 30000, 150000);
71
54 if (sfuncs->mode_fixup == NULL) 72 if (sfuncs->mode_fixup == NULL)
55 return true; 73 return true;
56 74
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_kms.c b/drivers/gpu/drm/rcar-du/rcar_du_kms.c
index 0c5ee616b5a3..cc9136e8ee9c 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_kms.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_kms.c
@@ -346,8 +346,14 @@ static int rcar_du_encoders_init(struct rcar_du_device *rcdu)
346 /* Process the output pipeline. */ 346 /* Process the output pipeline. */
347 ret = rcar_du_encoders_init_one(rcdu, output, &ep); 347 ret = rcar_du_encoders_init_one(rcdu, output, &ep);
348 if (ret < 0) { 348 if (ret < 0) {
349 of_node_put(ep_node); 349 if (ret == -EPROBE_DEFER) {
350 return ret; 350 of_node_put(ep_node);
351 return ret;
352 }
353
354 dev_info(rcdu->dev,
355 "encoder initialization failed, skipping\n");
356 continue;
351 } 357 }
352 358
353 num_encoders += ret; 359 num_encoders += ret;
@@ -413,6 +419,11 @@ int rcar_du_modeset_init(struct rcar_du_device *rcdu)
413 if (ret < 0) 419 if (ret < 0)
414 return ret; 420 return ret;
415 421
422 if (ret == 0) {
423 dev_err(rcdu->dev, "error: no encoder could be initialized\n");
424 return -EINVAL;
425 }
426
416 num_encoders = ret; 427 num_encoders = ret;
417 428
418 /* Set the possible CRTCs and possible clones. There's always at least 429 /* Set the possible CRTCs and possible clones. There's always at least
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_plane.c b/drivers/gpu/drm/rcar-du/rcar_du_plane.c
index 72a7cb47bd9f..50f2f2b20d39 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_plane.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_plane.c
@@ -104,14 +104,22 @@ void rcar_du_plane_update_base(struct rcar_du_plane *plane)
104{ 104{
105 struct rcar_du_group *rgrp = plane->group; 105 struct rcar_du_group *rgrp = plane->group;
106 unsigned int index = plane->hwindex; 106 unsigned int index = plane->hwindex;
107 bool interlaced;
107 u32 mwr; 108 u32 mwr;
108 109
109 /* Memory pitch (expressed in pixels) */ 110 interlaced = plane->crtc->mode.flags & DRM_MODE_FLAG_INTERLACE;
111
112 /* Memory pitch (expressed in pixels). Must be doubled for interlaced
113 * operation with 32bpp formats.
114 */
110 if (plane->format->planes == 2) 115 if (plane->format->planes == 2)
111 mwr = plane->pitch; 116 mwr = plane->pitch;
112 else 117 else
113 mwr = plane->pitch * 8 / plane->format->bpp; 118 mwr = plane->pitch * 8 / plane->format->bpp;
114 119
120 if (interlaced && plane->format->bpp == 32)
121 mwr *= 2;
122
115 rcar_du_plane_write(rgrp, index, PnMWR, mwr); 123 rcar_du_plane_write(rgrp, index, PnMWR, mwr);
116 124
117 /* The Y position is expressed in raster line units and must be doubled 125 /* The Y position is expressed in raster line units and must be doubled
@@ -119,17 +127,23 @@ void rcar_du_plane_update_base(struct rcar_du_plane *plane)
119 * doubling the Y position is found in the R8A7779 datasheet, but the 127 * doubling the Y position is found in the R8A7779 datasheet, but the
120 * rule seems to apply there as well. 128 * rule seems to apply there as well.
121 * 129 *
130 * Despite not being documented, doubling seem not to be needed when
131 * operating in interlaced mode.
132 *
122 * Similarly, for the second plane, NV12 and NV21 formats seem to 133 * Similarly, for the second plane, NV12 and NV21 formats seem to
123 * require a halved Y position value. 134 * require a halved Y position value, in both progressive and interlaced
135 * modes.
124 */ 136 */
125 rcar_du_plane_write(rgrp, index, PnSPXR, plane->src_x); 137 rcar_du_plane_write(rgrp, index, PnSPXR, plane->src_x);
126 rcar_du_plane_write(rgrp, index, PnSPYR, plane->src_y * 138 rcar_du_plane_write(rgrp, index, PnSPYR, plane->src_y *
127 (plane->format->bpp == 32 ? 2 : 1)); 139 (!interlaced && plane->format->bpp == 32 ? 2 : 1));
128 rcar_du_plane_write(rgrp, index, PnDSA0R, plane->dma[0]); 140 rcar_du_plane_write(rgrp, index, PnDSA0R, plane->dma[0]);
129 141
130 if (plane->format->planes == 2) { 142 if (plane->format->planes == 2) {
131 index = (index + 1) % 8; 143 index = (index + 1) % 8;
132 144
145 rcar_du_plane_write(rgrp, index, PnMWR, plane->pitch);
146
133 rcar_du_plane_write(rgrp, index, PnSPXR, plane->src_x); 147 rcar_du_plane_write(rgrp, index, PnSPXR, plane->src_x);
134 rcar_du_plane_write(rgrp, index, PnSPYR, plane->src_y * 148 rcar_du_plane_write(rgrp, index, PnSPYR, plane->src_y *
135 (plane->format->bpp == 16 ? 2 : 1) / 2); 149 (plane->format->bpp == 16 ? 2 : 1) / 2);
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_regs.h b/drivers/gpu/drm/rcar-du/rcar_du_regs.h
index 73f7347f740b..70fcbc471ebd 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_regs.h
+++ b/drivers/gpu/drm/rcar-du/rcar_du_regs.h
@@ -34,6 +34,7 @@
34#define DSYSR_SCM_INT_NONE (0 << 4) 34#define DSYSR_SCM_INT_NONE (0 << 4)
35#define DSYSR_SCM_INT_SYNC (2 << 4) 35#define DSYSR_SCM_INT_SYNC (2 << 4)
36#define DSYSR_SCM_INT_VIDEO (3 << 4) 36#define DSYSR_SCM_INT_VIDEO (3 << 4)
37#define DSYSR_SCM_MASK (3 << 4)
37 38
38#define DSMR 0x00004 39#define DSMR 0x00004
39#define DSMR_VSPM (1 << 28) 40#define DSMR_VSPM (1 << 28)
@@ -256,8 +257,8 @@
256#define DIDSR_LCDS_LVDS0(n) (2 << (8 + (n) * 2)) 257#define DIDSR_LCDS_LVDS0(n) (2 << (8 + (n) * 2))
257#define DIDSR_LCDS_LVDS1(n) (3 << (8 + (n) * 2)) 258#define DIDSR_LCDS_LVDS1(n) (3 << (8 + (n) * 2))
258#define DIDSR_LCDS_MASK(n) (3 << (8 + (n) * 2)) 259#define DIDSR_LCDS_MASK(n) (3 << (8 + (n) * 2))
259#define DIDSR_PCDS_CLK(n, clk) (clk << ((n) * 2)) 260#define DIDSR_PDCS_CLK(n, clk) (clk << ((n) * 2))
260#define DIDSR_PCDS_MASK(n) (3 << ((n) * 2)) 261#define DIDSR_PDCS_MASK(n) (3 << ((n) * 2))
261 262
262/* ----------------------------------------------------------------------------- 263/* -----------------------------------------------------------------------------
263 * Display Timing Generation Registers 264 * Display Timing Generation Registers
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_vgacon.c b/drivers/gpu/drm/rcar-du/rcar_du_vgacon.c
index 752747a5e920..9d4879921cc7 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_vgacon.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_vgacon.c
@@ -64,6 +64,7 @@ int rcar_du_vga_connector_init(struct rcar_du_device *rcdu,
64 connector = &rcon->connector; 64 connector = &rcon->connector;
65 connector->display_info.width_mm = 0; 65 connector->display_info.width_mm = 0;
66 connector->display_info.height_mm = 0; 66 connector->display_info.height_mm = 0;
67 connector->interlace_allowed = true;
67 68
68 ret = drm_connector_init(rcdu->ddev, connector, &connector_funcs, 69 ret = drm_connector_init(rcdu->ddev, connector, &connector_funcs,
69 DRM_MODE_CONNECTOR_VGA); 70 DRM_MODE_CONNECTOR_VGA);