Skip to content

Commit 0320ac5

Browse files
committed
Merge tag 'du-next-20180914' of git://linuxtv.org/pinchartl/media into drm-next
R-Car DU changes for v4.20 The pull request mostly contains updates to the R-Car DU driver, notably support for interlaced modes on Gen3 hardware, support for the LVDS output on R8A77980, and a set of miscellaneous bug fixes. There are also two SPDX conversion patches for the drm shmobile and panel-lvds drivers, as well as an update to MAINTAINERS to add Kieran Bingham as a co-maintainer for the DU driver. Signed-off-by: Dave Airlie <airlied@redhat.com> From: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Link: https://patchwork.freedesktop.org/patch/msgid/3273568.LdoAI77IYW@avalon
2 parents 7952410 + 6e1637c commit 0320ac5

36 files changed

+253
-251
lines changed

Documentation/devicetree/bindings/display/bridge/renesas,lvds.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ Required properties:
1414
- "renesas,r8a7795-lvds" for R8A7795 (R-Car H3) compatible LVDS encoders
1515
- "renesas,r8a7796-lvds" for R8A7796 (R-Car M3-W) compatible LVDS encoders
1616
- "renesas,r8a77970-lvds" for R8A77970 (R-Car V3M) compatible LVDS encoders
17+
- "renesas,r8a77980-lvds" for R8A77980 (R-Car V3H) compatible LVDS encoders
1718
- "renesas,r8a77995-lvds" for R8A77995 (R-Car D3) compatible LVDS encoders
1819

1920
- reg: Base address and length for the memory-mapped registers

Documentation/devicetree/bindings/display/renesas,du.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ Required Properties:
1515
- "renesas,du-r8a7796" for R8A7796 (R-Car M3-W) compatible DU
1616
- "renesas,du-r8a77965" for R8A77965 (R-Car M3-N) compatible DU
1717
- "renesas,du-r8a77970" for R8A77970 (R-Car V3M) compatible DU
18+
- "renesas,du-r8a77980" for R8A77980 (R-Car V3H) compatible DU
1819
- "renesas,du-r8a77995" for R8A77995 (R-Car D3) compatible DU
1920

2021
- reg: the memory-mapped I/O registers base address and length
@@ -61,6 +62,7 @@ corresponding to each DU output.
6162
R8A7796 (R-Car M3-W) DPAD 0 HDMI 0 LVDS 0 -
6263
R8A77965 (R-Car M3-N) DPAD 0 HDMI 0 LVDS 0 -
6364
R8A77970 (R-Car V3M) DPAD 0 LVDS 0 - -
65+
R8A77980 (R-Car V3H) DPAD 0 LVDS 0 - -
6466
R8A77995 (R-Car D3) DPAD 0 LVDS 0 LVDS 1 -
6567

6668

MAINTAINERS

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4870,9 +4870,10 @@ F: Documentation/devicetree/bindings/display/tegra/nvidia,tegra20-host1x.txt
48704870

48714871
DRM DRIVERS FOR RENESAS
48724872
M: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
4873+
M: Kieran Bingham <kieran.bingham+renesas@ideasonboard.com>
48734874
L: dri-devel@lists.freedesktop.org
48744875
L: linux-renesas-soc@vger.kernel.org
4875-
T: git git://linuxtv.org/pinchartl/fbdev
4876+
T: git git://linuxtv.org/pinchartl/media drm/du/next
48764877
S: Supported
48774878
F: drivers/gpu/drm/rcar-du/
48784879
F: drivers/gpu/drm/shmobile/

drivers/gpu/drm/panel/panel-lvds.c

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,11 @@
1+
// SPDX-License-Identifier: GPL-2.0+
12
/*
23
* Generic LVDS panel driver
34
*
45
* Copyright (C) 2016 Laurent Pinchart
56
* Copyright (C) 2016 Renesas Electronics Corporation
67
*
78
* Contact: Laurent Pinchart (laurent.pinchart@ideasonboard.com)
8-
*
9-
* This program is free software; you can redistribute it and/or modify
10-
* it under the terms of the GNU General Public License as published by
11-
* the Free Software Foundation; either version 2 of the License, or
12-
* (at your option) any later version.
139
*/
1410

1511
#include <linux/backlight.h>

drivers/gpu/drm/rcar-du/Kconfig

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
# SPDX-License-Identifier: GPL-2.0
12
config DRM_RCAR_DU
23
tristate "DRM Support for R-Car Display Unit"
34
depends on DRM && OF

drivers/gpu/drm/rcar-du/rcar_du_crtc.c

Lines changed: 113 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,10 @@
1+
// SPDX-License-Identifier: GPL-2.0+
12
/*
23
* rcar_du_crtc.c -- R-Car Display Unit CRTCs
34
*
45
* Copyright (C) 2013-2015 Renesas Electronics Corporation
56
*
67
* Contact: Laurent Pinchart (laurent.pinchart@ideasonboard.com)
7-
*
8-
* This program is free software; you can redistribute it and/or modify
9-
* it under the terms of the GNU General Public License as published by
10-
* the Free Software Foundation; either version 2 of the License, or
11-
* (at your option) any later version.
128
*/
139

1410
#include <linux/clk.h>
@@ -198,6 +194,47 @@ static void rcar_du_dpll_divider(struct rcar_du_crtc *rcrtc,
198194
best_diff);
199195
}
200196

197+
struct du_clk_params {
198+
struct clk *clk;
199+
unsigned long rate;
200+
unsigned long diff;
201+
u32 escr;
202+
};
203+
204+
static void rcar_du_escr_divider(struct clk *clk, unsigned long target,
205+
u32 escr, struct du_clk_params *params)
206+
{
207+
unsigned long rate;
208+
unsigned long diff;
209+
u32 div;
210+
211+
/*
212+
* If the target rate has already been achieved perfectly we can't do
213+
* better.
214+
*/
215+
if (params->diff == 0)
216+
return;
217+
218+
/*
219+
* Compute the input clock rate and internal divisor values to obtain
220+
* the clock rate closest to the target frequency.
221+
*/
222+
rate = clk_round_rate(clk, target);
223+
div = clamp(DIV_ROUND_CLOSEST(rate, target), 1UL, 64UL) - 1;
224+
diff = abs(rate / (div + 1) - target);
225+
226+
/*
227+
* Store the parameters if the resulting frequency is better than any
228+
* previously calculated value.
229+
*/
230+
if (diff < params->diff) {
231+
params->clk = clk;
232+
params->rate = rate;
233+
params->diff = diff;
234+
params->escr = escr | div;
235+
}
236+
}
237+
201238
static const struct soc_device_attribute rcar_du_r8a7795_es1[] = {
202239
{ .soc_id = "r8a7795", .revision = "ES1.*" },
203240
{ /* sentinel */ }
@@ -208,89 +245,83 @@ static void rcar_du_crtc_set_display_timing(struct rcar_du_crtc *rcrtc)
208245
const struct drm_display_mode *mode = &rcrtc->crtc.state->adjusted_mode;
209246
struct rcar_du_device *rcdu = rcrtc->group->dev;
210247
unsigned long mode_clock = mode->clock * 1000;
211-
unsigned long clk;
212-
u32 value;
248+
u32 dsmr;
213249
u32 escr;
214-
u32 div;
215250

216-
/*
217-
* Compute the clock divisor and select the internal or external dot
218-
* clock based on the requested frequency.
219-
*/
220-
clk = clk_get_rate(rcrtc->clock);
221-
div = DIV_ROUND_CLOSEST(clk, mode_clock);
222-
div = clamp(div, 1U, 64U) - 1;
223-
escr = div | ESCR_DCLKSEL_CLKS;
224-
225-
if (rcrtc->extclock) {
251+
if (rcdu->info->dpll_mask & (1 << rcrtc->index)) {
252+
unsigned long target = mode_clock;
226253
struct dpll_info dpll = { 0 };
227254
unsigned long extclk;
228-
unsigned long extrate;
229-
unsigned long rate;
230-
u32 extdiv;
255+
u32 dpllcr;
256+
u32 div = 0;
231257

232-
extclk = clk_get_rate(rcrtc->extclock);
233-
if (rcdu->info->dpll_ch & (1 << rcrtc->index)) {
234-
unsigned long target = mode_clock;
258+
/*
259+
* DU channels that have a display PLL can't use the internal
260+
* system clock, and have no internal clock divider.
261+
*/
235262

236-
/*
237-
* The H3 ES1.x exhibits dot clock duty cycle stability
238-
* issues. We can work around them by configuring the
239-
* DPLL to twice the desired frequency, coupled with a
240-
* /2 post-divider. This isn't needed on other SoCs and
241-
* breaks HDMI output on M3-W for a currently unknown
242-
* reason, so restrict the workaround to H3 ES1.x.
243-
*/
244-
if (soc_device_match(rcar_du_r8a7795_es1))
245-
target *= 2;
263+
if (WARN_ON(!rcrtc->extclock))
264+
return;
246265

247-
rcar_du_dpll_divider(rcrtc, &dpll, extclk, target);
248-
extclk = dpll.output;
266+
/*
267+
* The H3 ES1.x exhibits dot clock duty cycle stability issues.
268+
* We can work around them by configuring the DPLL to twice the
269+
* desired frequency, coupled with a /2 post-divider. Restrict
270+
* the workaround to H3 ES1.x as ES2.0 and all other SoCs have
271+
* no post-divider when a display PLL is present (as shown by
272+
* the workaround breaking HDMI output on M3-W during testing).
273+
*/
274+
if (soc_device_match(rcar_du_r8a7795_es1)) {
275+
target *= 2;
276+
div = 1;
249277
}
250278

251-
extdiv = DIV_ROUND_CLOSEST(extclk, mode_clock);
252-
extdiv = clamp(extdiv, 1U, 64U) - 1;
279+
extclk = clk_get_rate(rcrtc->extclock);
280+
rcar_du_dpll_divider(rcrtc, &dpll, extclk, target);
253281

254-
rate = clk / (div + 1);
255-
extrate = extclk / (extdiv + 1);
282+
dpllcr = DPLLCR_CODE | DPLLCR_CLKE
283+
| DPLLCR_FDPLL(dpll.fdpll)
284+
| DPLLCR_N(dpll.n) | DPLLCR_M(dpll.m)
285+
| DPLLCR_STBY;
256286

257-
if (abs((long)extrate - (long)mode_clock) <
258-
abs((long)rate - (long)mode_clock)) {
287+
if (rcrtc->index == 1)
288+
dpllcr |= DPLLCR_PLCS1
289+
| DPLLCR_INCS_DOTCLKIN1;
290+
else
291+
dpllcr |= DPLLCR_PLCS0
292+
| DPLLCR_INCS_DOTCLKIN0;
259293

260-
if (rcdu->info->dpll_ch & (1 << rcrtc->index)) {
261-
u32 dpllcr = DPLLCR_CODE | DPLLCR_CLKE
262-
| DPLLCR_FDPLL(dpll.fdpll)
263-
| DPLLCR_N(dpll.n) | DPLLCR_M(dpll.m)
264-
| DPLLCR_STBY;
294+
rcar_du_group_write(rcrtc->group, DPLLCR, dpllcr);
265295

266-
if (rcrtc->index == 1)
267-
dpllcr |= DPLLCR_PLCS1
268-
| DPLLCR_INCS_DOTCLKIN1;
269-
else
270-
dpllcr |= DPLLCR_PLCS0
271-
| DPLLCR_INCS_DOTCLKIN0;
296+
escr = ESCR_DCLKSEL_DCLKIN | div;
297+
} else {
298+
struct du_clk_params params = { .diff = (unsigned long)-1 };
272299

273-
rcar_du_group_write(rcrtc->group, DPLLCR,
274-
dpllcr);
275-
}
300+
rcar_du_escr_divider(rcrtc->clock, mode_clock,
301+
ESCR_DCLKSEL_CLKS, &params);
302+
if (rcrtc->extclock)
303+
rcar_du_escr_divider(rcrtc->extclock, mode_clock,
304+
ESCR_DCLKSEL_DCLKIN, &params);
276305

277-
escr = ESCR_DCLKSEL_DCLKIN | extdiv;
278-
}
306+
dev_dbg(rcrtc->group->dev->dev, "mode clock %lu %s rate %lu\n",
307+
mode_clock, params.clk == rcrtc->clock ? "cpg" : "ext",
308+
params.rate);
279309

280-
dev_dbg(rcrtc->group->dev->dev,
281-
"mode clock %lu extrate %lu rate %lu ESCR 0x%08x\n",
282-
mode_clock, extrate, rate, escr);
310+
clk_set_rate(params.clk, params.rate);
311+
escr = params.escr;
283312
}
284313

285-
rcar_du_group_write(rcrtc->group, rcrtc->index % 2 ? ESCR2 : ESCR,
286-
escr);
287-
rcar_du_group_write(rcrtc->group, rcrtc->index % 2 ? OTAR2 : OTAR, 0);
314+
dev_dbg(rcrtc->group->dev->dev, "%s: ESCR 0x%08x\n", __func__, escr);
315+
316+
rcar_du_crtc_write(rcrtc, rcrtc->index % 2 ? ESCR13 : ESCR02, escr);
317+
rcar_du_crtc_write(rcrtc, rcrtc->index % 2 ? OTAR13 : OTAR02, 0);
288318

289319
/* Signal polarities */
290-
value = ((mode->flags & DRM_MODE_FLAG_PVSYNC) ? DSMR_VSL : 0)
291-
| ((mode->flags & DRM_MODE_FLAG_PHSYNC) ? DSMR_HSL : 0)
292-
| DSMR_DIPM_DISP | DSMR_CSPM;
293-
rcar_du_crtc_write(rcrtc, DSMR, value);
320+
dsmr = ((mode->flags & DRM_MODE_FLAG_PVSYNC) ? DSMR_VSL : 0)
321+
| ((mode->flags & DRM_MODE_FLAG_PHSYNC) ? DSMR_HSL : 0)
322+
| ((mode->flags & DRM_MODE_FLAG_INTERLACE) ? DSMR_ODEV : 0)
323+
| DSMR_DIPM_DISP | DSMR_CSPM;
324+
rcar_du_crtc_write(rcrtc, DSMR, dsmr);
294325

295326
/* Display timings */
296327
rcar_du_crtc_write(rcrtc, HDSR, mode->htotal - mode->hsync_start - 19);
@@ -684,11 +715,25 @@ static void rcar_du_crtc_atomic_flush(struct drm_crtc *crtc,
684715
rcar_du_vsp_atomic_flush(rcrtc);
685716
}
686717

718+
enum drm_mode_status rcar_du_crtc_mode_valid(struct drm_crtc *crtc,
719+
const struct drm_display_mode *mode)
720+
{
721+
struct rcar_du_crtc *rcrtc = to_rcar_crtc(crtc);
722+
struct rcar_du_device *rcdu = rcrtc->group->dev;
723+
bool interlaced = mode->flags & DRM_MODE_FLAG_INTERLACE;
724+
725+
if (interlaced && !rcar_du_has(rcdu, RCAR_DU_FEATURE_INTERLACED))
726+
return MODE_NO_INTERLACE;
727+
728+
return MODE_OK;
729+
}
730+
687731
static const struct drm_crtc_helper_funcs crtc_helper_funcs = {
688732
.atomic_begin = rcar_du_crtc_atomic_begin,
689733
.atomic_flush = rcar_du_crtc_atomic_flush,
690734
.atomic_enable = rcar_du_crtc_atomic_enable,
691735
.atomic_disable = rcar_du_crtc_atomic_disable,
736+
.mode_valid = rcar_du_crtc_mode_valid,
692737
};
693738

694739
static void rcar_du_crtc_crc_init(struct rcar_du_crtc *rcrtc)

drivers/gpu/drm/rcar-du/rcar_du_crtc.h

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,10 @@
1+
/* SPDX-License-Identifier: GPL-2.0+ */
12
/*
23
* rcar_du_crtc.h -- R-Car Display Unit CRTCs
34
*
45
* Copyright (C) 2013-2015 Renesas Electronics Corporation
56
*
67
* Contact: Laurent Pinchart (laurent.pinchart@ideasonboard.com)
7-
*
8-
* This program is free software; you can redistribute it and/or modify
9-
* it under the terms of the GNU General Public License as published by
10-
* the Free Software Foundation; either version 2 of the License, or
11-
* (at your option) any later version.
128
*/
139

1410
#ifndef __RCAR_DU_CRTC_H__

0 commit comments

Comments
 (0)