Skip to content

Commit c6a27fa

Browse files
author
Laurent Pinchart
committed
drm: rcar-du: Convert LVDS encoder code to bridge driver
The LVDS encoders used to be described in DT as part of the DU. They now have their own DT node, linked to the DU using the OF graph bindings. This allows moving internal LVDS encoder support to a separate driver modelled as a DRM bridge. Backward compatibility is retained as legacy DT is patched live to move to the new bindings. Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com> Reviewed-by: Niklas Söderlund <niklas.soderlund+renesas@ragnatech.se>
1 parent 81c0e3d commit c6a27fa

File tree

12 files changed

+561
-616
lines changed

12 files changed

+561
-616
lines changed

drivers/gpu/drm/rcar-du/Kconfig

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,8 @@ config DRM_RCAR_DW_HDMI
1919
Enable support for R-Car Gen3 internal HDMI encoder.
2020

2121
config DRM_RCAR_LVDS
22-
bool "R-Car DU LVDS Encoder Support"
23-
depends on DRM_RCAR_DU
22+
tristate "R-Car DU LVDS Encoder Support"
23+
depends on DRM && DRM_BRIDGE && OF
2424
select DRM_PANEL
2525
select OF_FLATTREE
2626
select OF_OVERLAY

drivers/gpu/drm/rcar-du/Makefile

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,8 @@ rcar-du-drm-y := rcar_du_crtc.o \
44
rcar_du_encoder.o \
55
rcar_du_group.o \
66
rcar_du_kms.o \
7-
rcar_du_lvdscon.o \
87
rcar_du_plane.o
98

10-
rcar-du-drm-$(CONFIG_DRM_RCAR_LVDS) += rcar_du_lvdsenc.o
119
rcar-du-drm-$(CONFIG_DRM_RCAR_LVDS) += rcar_du_of.o \
1210
rcar_du_of_lvds_r8a7790.dtb.o \
1311
rcar_du_of_lvds_r8a7791.dtb.o \
@@ -18,3 +16,4 @@ rcar-du-drm-$(CONFIG_DRM_RCAR_VSP) += rcar_du_vsp.o
1816

1917
obj-$(CONFIG_DRM_RCAR_DU) += rcar-du-drm.o
2018
obj-$(CONFIG_DRM_RCAR_DW_HDMI) += rcar_dw_hdmi.o
19+
obj-$(CONFIG_DRM_RCAR_LVDS) += rcar_lvds.o

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

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929

3030
#include "rcar_du_drv.h"
3131
#include "rcar_du_kms.h"
32+
#include "rcar_du_of.h"
3233
#include "rcar_du_regs.h"
3334

3435
/* -----------------------------------------------------------------------------
@@ -74,7 +75,6 @@ static const struct rcar_du_device_info rzg1_du_r8a7745_info = {
7475
.port = 1,
7576
},
7677
},
77-
.num_lvds = 0,
7878
};
7979

8080
static const struct rcar_du_device_info rcar_du_r8a7779_info = {
@@ -95,14 +95,13 @@ static const struct rcar_du_device_info rcar_du_r8a7779_info = {
9595
.port = 1,
9696
},
9797
},
98-
.num_lvds = 0,
9998
};
10099

101100
static const struct rcar_du_device_info rcar_du_r8a7790_info = {
102101
.gen = 2,
103102
.features = RCAR_DU_FEATURE_CRTC_IRQ_CLOCK
104103
| RCAR_DU_FEATURE_EXT_CTRL_REGS,
105-
.quirks = RCAR_DU_QUIRK_ALIGN_128B | RCAR_DU_QUIRK_LVDS_LANES,
104+
.quirks = RCAR_DU_QUIRK_ALIGN_128B,
106105
.num_crtcs = 3,
107106
.routes = {
108107
/*
@@ -164,7 +163,6 @@ static const struct rcar_du_device_info rcar_du_r8a7792_info = {
164163
.port = 1,
165164
},
166165
},
167-
.num_lvds = 0,
168166
};
169167

170168
static const struct rcar_du_device_info rcar_du_r8a7794_info = {
@@ -186,7 +184,6 @@ static const struct rcar_du_device_info rcar_du_r8a7794_info = {
186184
.port = 1,
187185
},
188186
},
189-
.num_lvds = 0,
190187
};
191188

192189
static const struct rcar_du_device_info rcar_du_r8a7795_info = {
@@ -434,7 +431,19 @@ static struct platform_driver rcar_du_platform_driver = {
434431
},
435432
};
436433

437-
module_platform_driver(rcar_du_platform_driver);
434+
static int __init rcar_du_init(void)
435+
{
436+
rcar_du_of_init(rcar_du_of_table);
437+
438+
return platform_driver_register(&rcar_du_platform_driver);
439+
}
440+
module_init(rcar_du_init);
441+
442+
static void __exit rcar_du_exit(void)
443+
{
444+
platform_driver_unregister(&rcar_du_platform_driver);
445+
}
446+
module_exit(rcar_du_exit);
438447

439448
MODULE_AUTHOR("Laurent Pinchart <laurent.pinchart@ideasonboard.com>");
440449
MODULE_DESCRIPTION("Renesas R-Car Display Unit DRM Driver");

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

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -26,14 +26,12 @@ struct device;
2626
struct drm_device;
2727
struct drm_fbdev_cma;
2828
struct rcar_du_device;
29-
struct rcar_du_lvdsenc;
3029

3130
#define RCAR_DU_FEATURE_CRTC_IRQ_CLOCK (1 << 0) /* Per-CRTC IRQ and clock */
3231
#define RCAR_DU_FEATURE_EXT_CTRL_REGS (1 << 1) /* Has extended control registers */
3332
#define RCAR_DU_FEATURE_VSP1_SOURCE (1 << 2) /* Has inputs from VSP1 */
3433

3534
#define RCAR_DU_QUIRK_ALIGN_128B (1 << 0) /* Align pitches to 128 bytes */
36-
#define RCAR_DU_QUIRK_LVDS_LANES (1 << 1) /* LVDS lanes 1 and 3 inverted */
3735

3836
/*
3937
* struct rcar_du_output_routing - Output routing specification
@@ -70,7 +68,6 @@ struct rcar_du_device_info {
7068

7169
#define RCAR_DU_MAX_CRTCS 4
7270
#define RCAR_DU_MAX_GROUPS DIV_ROUND_UP(RCAR_DU_MAX_CRTCS, 2)
73-
#define RCAR_DU_MAX_LVDS 2
7471
#define RCAR_DU_MAX_VSPS 4
7572

7673
struct rcar_du_device {
@@ -96,8 +93,6 @@ struct rcar_du_device {
9693

9794
unsigned int dpad0_source;
9895
unsigned int vspd1_sink;
99-
100-
struct rcar_du_lvdsenc *lvds[RCAR_DU_MAX_LVDS];
10196
};
10297

10398
static inline bool rcar_du_has(struct rcar_du_device *rcdu,

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

Lines changed: 15 additions & 160 deletions
Original file line numberDiff line numberDiff line change
@@ -21,134 +21,22 @@
2121
#include "rcar_du_drv.h"
2222
#include "rcar_du_encoder.h"
2323
#include "rcar_du_kms.h"
24-
#include "rcar_du_lvdscon.h"
25-
#include "rcar_du_lvdsenc.h"
2624

2725
/* -----------------------------------------------------------------------------
2826
* Encoder
2927
*/
3028

31-
static void rcar_du_encoder_disable(struct drm_encoder *encoder)
32-
{
33-
struct rcar_du_encoder *renc = to_rcar_encoder(encoder);
34-
35-
if (renc->connector && renc->connector->panel) {
36-
drm_panel_disable(renc->connector->panel);
37-
drm_panel_unprepare(renc->connector->panel);
38-
}
39-
40-
if (renc->lvds)
41-
rcar_du_lvdsenc_enable(renc->lvds, encoder->crtc, false);
42-
}
43-
44-
static void rcar_du_encoder_enable(struct drm_encoder *encoder)
45-
{
46-
struct rcar_du_encoder *renc = to_rcar_encoder(encoder);
47-
48-
if (renc->lvds)
49-
rcar_du_lvdsenc_enable(renc->lvds, encoder->crtc, true);
50-
51-
if (renc->connector && renc->connector->panel) {
52-
drm_panel_prepare(renc->connector->panel);
53-
drm_panel_enable(renc->connector->panel);
54-
}
55-
}
56-
57-
static int rcar_du_encoder_atomic_check(struct drm_encoder *encoder,
58-
struct drm_crtc_state *crtc_state,
59-
struct drm_connector_state *conn_state)
60-
{
61-
struct rcar_du_encoder *renc = to_rcar_encoder(encoder);
62-
struct drm_display_mode *adjusted_mode = &crtc_state->adjusted_mode;
63-
const struct drm_display_mode *mode = &crtc_state->mode;
64-
struct drm_connector *connector = conn_state->connector;
65-
struct drm_device *dev = encoder->dev;
66-
67-
/*
68-
* Only panel-related encoder types require validation here, everything
69-
* else is handled by the bridge drivers.
70-
*/
71-
if (connector->connector_type == DRM_MODE_CONNECTOR_LVDS) {
72-
const struct drm_display_mode *panel_mode;
73-
74-
if (list_empty(&connector->modes)) {
75-
dev_dbg(dev->dev, "encoder: empty modes list\n");
76-
return -EINVAL;
77-
}
78-
79-
panel_mode = list_first_entry(&connector->modes,
80-
struct drm_display_mode, head);
81-
82-
/* We're not allowed to modify the resolution. */
83-
if (mode->hdisplay != panel_mode->hdisplay ||
84-
mode->vdisplay != panel_mode->vdisplay)
85-
return -EINVAL;
86-
87-
/*
88-
* The flat panel mode is fixed, just copy it to the adjusted
89-
* mode.
90-
*/
91-
drm_mode_copy(adjusted_mode, panel_mode);
92-
}
93-
94-
if (renc->lvds)
95-
rcar_du_lvdsenc_atomic_check(renc->lvds, adjusted_mode);
96-
97-
return 0;
98-
}
99-
10029
static void rcar_du_encoder_mode_set(struct drm_encoder *encoder,
10130
struct drm_crtc_state *crtc_state,
10231
struct drm_connector_state *conn_state)
10332
{
10433
struct rcar_du_encoder *renc = to_rcar_encoder(encoder);
105-
struct drm_display_info *info = &conn_state->connector->display_info;
106-
enum rcar_lvds_mode mode;
10734

10835
rcar_du_crtc_route_output(crtc_state->crtc, renc->output);
109-
110-
if (!renc->lvds) {
111-
/*
112-
* The DU driver creates connectors only for the outputs of the
113-
* internal LVDS encoders.
114-
*/
115-
renc->connector = NULL;
116-
return;
117-
}
118-
119-
renc->connector = to_rcar_connector(conn_state->connector);
120-
121-
if (!info->num_bus_formats || !info->bus_formats) {
122-
dev_err(encoder->dev->dev, "no LVDS bus format reported\n");
123-
return;
124-
}
125-
126-
switch (info->bus_formats[0]) {
127-
case MEDIA_BUS_FMT_RGB666_1X7X3_SPWG:
128-
case MEDIA_BUS_FMT_RGB888_1X7X4_JEIDA:
129-
mode = RCAR_LVDS_MODE_JEIDA;
130-
break;
131-
case MEDIA_BUS_FMT_RGB888_1X7X4_SPWG:
132-
mode = RCAR_LVDS_MODE_VESA;
133-
break;
134-
default:
135-
dev_err(encoder->dev->dev,
136-
"unsupported LVDS bus format 0x%04x\n",
137-
info->bus_formats[0]);
138-
return;
139-
}
140-
141-
if (info->bus_flags & DRM_BUS_FLAG_DATA_LSB_TO_MSB)
142-
mode |= RCAR_LVDS_MODE_MIRROR;
143-
144-
rcar_du_lvdsenc_set_mode(renc->lvds, mode);
14536
}
14637

14738
static const struct drm_encoder_helper_funcs encoder_helper_funcs = {
14839
.atomic_mode_set = rcar_du_encoder_mode_set,
149-
.disable = rcar_du_encoder_disable,
150-
.enable = rcar_du_encoder_enable,
151-
.atomic_check = rcar_du_encoder_atomic_check,
15240
};
15341

15442
static const struct drm_encoder_funcs encoder_funcs = {
@@ -172,33 +60,14 @@ int rcar_du_encoder_init(struct rcar_du_device *rcdu,
17260
renc->output = output;
17361
encoder = rcar_encoder_to_drm_encoder(renc);
17462

175-
switch (output) {
176-
case RCAR_DU_OUTPUT_LVDS0:
177-
renc->lvds = rcdu->lvds[0];
178-
break;
63+
dev_dbg(rcdu->dev, "initializing encoder %pOF for output %u\n",
64+
enc_node, output);
17965

180-
case RCAR_DU_OUTPUT_LVDS1:
181-
renc->lvds = rcdu->lvds[1];
182-
break;
183-
184-
default:
185-
break;
186-
}
187-
188-
if (enc_node) {
189-
dev_dbg(rcdu->dev, "initializing encoder %pOF for output %u\n",
190-
enc_node, output);
191-
192-
/* Locate the DRM bridge from the encoder DT node. */
193-
bridge = of_drm_find_bridge(enc_node);
194-
if (!bridge) {
195-
ret = -EPROBE_DEFER;
196-
goto done;
197-
}
198-
} else {
199-
dev_dbg(rcdu->dev,
200-
"initializing internal encoder for output %u\n",
201-
output);
66+
/* Locate the DRM bridge from the encoder DT node. */
67+
bridge = of_drm_find_bridge(enc_node);
68+
if (!bridge) {
69+
ret = -EPROBE_DEFER;
70+
goto done;
20271
}
20372

20473
ret = drm_encoder_init(rcdu->ddev, encoder, &encoder_funcs,
@@ -208,28 +77,14 @@ int rcar_du_encoder_init(struct rcar_du_device *rcdu,
20877

20978
drm_encoder_helper_add(encoder, &encoder_helper_funcs);
21079

211-
if (bridge) {
212-
/*
213-
* Attach the bridge to the encoder. The bridge will create the
214-
* connector.
215-
*/
216-
ret = drm_bridge_attach(encoder, bridge, NULL);
217-
if (ret) {
218-
drm_encoder_cleanup(encoder);
219-
return ret;
220-
}
221-
} else {
222-
/* There's no bridge, create the connector manually. */
223-
switch (output) {
224-
case RCAR_DU_OUTPUT_LVDS0:
225-
case RCAR_DU_OUTPUT_LVDS1:
226-
ret = rcar_du_lvds_connector_init(rcdu, renc, con_node);
227-
break;
228-
229-
default:
230-
ret = -EINVAL;
231-
break;
232-
}
80+
/*
81+
* Attach the bridge to the encoder. The bridge will create the
82+
* connector.
83+
*/
84+
ret = drm_bridge_attach(encoder, bridge, NULL);
85+
if (ret) {
86+
drm_encoder_cleanup(encoder);
87+
return ret;
23388
}
23489

23590
done:

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

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -19,29 +19,17 @@
1919

2020
struct drm_panel;
2121
struct rcar_du_device;
22-
struct rcar_du_lvdsenc;
2322

2423
struct rcar_du_encoder {
2524
struct drm_encoder base;
2625
enum rcar_du_output output;
27-
struct rcar_du_connector *connector;
28-
struct rcar_du_lvdsenc *lvds;
2926
};
3027

3128
#define to_rcar_encoder(e) \
3229
container_of(e, struct rcar_du_encoder, base)
3330

3431
#define rcar_encoder_to_drm_encoder(e) (&(e)->base)
3532

36-
struct rcar_du_connector {
37-
struct drm_connector connector;
38-
struct rcar_du_encoder *encoder;
39-
struct drm_panel *panel;
40-
};
41-
42-
#define to_rcar_connector(c) \
43-
container_of(c, struct rcar_du_connector, connector)
44-
4533
int rcar_du_encoder_init(struct rcar_du_device *rcdu,
4634
enum rcar_du_output output,
4735
struct device_node *enc_node,

0 commit comments

Comments
 (0)