aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLaurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>2016-10-07 09:01:41 -0400
committerLaurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>2017-04-04 10:04:02 -0400
commit5c602531feb3db3926cdd76dda89314f0634c9e7 (patch)
tree2029942a4c0980756e42506be3a730cca3e3b6a6
parente947eccbeba45268bf3b5f4e30185d9bb87a293d (diff)
drm: rcar-du: Replace manual bridge implementation with DRM bridge
The rcar-du driver contains a manual implementation of HDMI and VGA bridges. Use DRM bridges to replace it. Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
-rw-r--r--drivers/gpu/drm/rcar-du/Kconfig6
-rw-r--r--drivers/gpu/drm/rcar-du/Makefile5
-rw-r--r--drivers/gpu/drm/rcar-du/rcar_du_encoder.c104
-rw-r--r--drivers/gpu/drm/rcar-du/rcar_du_encoder.h2
-rw-r--r--drivers/gpu/drm/rcar-du/rcar_du_hdmienc.c134
-rw-r--r--drivers/gpu/drm/rcar-du/rcar_du_hdmienc.h35
-rw-r--r--drivers/gpu/drm/rcar-du/rcar_du_vgacon.c82
-rw-r--r--drivers/gpu/drm/rcar-du/rcar_du_vgacon.h23
8 files changed, 60 insertions, 331 deletions
diff --git a/drivers/gpu/drm/rcar-du/Kconfig b/drivers/gpu/drm/rcar-du/Kconfig
index 2bab449add76..06121eeba9e5 100644
--- a/drivers/gpu/drm/rcar-du/Kconfig
+++ b/drivers/gpu/drm/rcar-du/Kconfig
@@ -11,12 +11,6 @@ config DRM_RCAR_DU
11 Choose this option if you have an R-Car chipset. 11 Choose this option if you have an R-Car chipset.
12 If M is selected the module will be called rcar-du-drm. 12 If M is selected the module will be called rcar-du-drm.
13 13
14config DRM_RCAR_HDMI
15 bool "R-Car DU HDMI Encoder Support"
16 depends on DRM_RCAR_DU
17 help
18 Enable support for external HDMI encoders.
19
20config DRM_RCAR_LVDS 14config DRM_RCAR_LVDS
21 bool "R-Car DU LVDS Encoder Support" 15 bool "R-Car DU LVDS Encoder Support"
22 depends on DRM_RCAR_DU 16 depends on DRM_RCAR_DU
diff --git a/drivers/gpu/drm/rcar-du/Makefile b/drivers/gpu/drm/rcar-du/Makefile
index d3b44651061a..a492e6858691 100644
--- a/drivers/gpu/drm/rcar-du/Makefile
+++ b/drivers/gpu/drm/rcar-du/Makefile
@@ -4,10 +4,7 @@ rcar-du-drm-y := rcar_du_crtc.o \
4 rcar_du_group.o \ 4 rcar_du_group.o \
5 rcar_du_kms.o \ 5 rcar_du_kms.o \
6 rcar_du_lvdscon.o \ 6 rcar_du_lvdscon.o \
7 rcar_du_plane.o \ 7 rcar_du_plane.o
8 rcar_du_vgacon.o
9
10rcar-du-drm-$(CONFIG_DRM_RCAR_HDMI) += rcar_du_hdmienc.o
11 8
12rcar-du-drm-$(CONFIG_DRM_RCAR_LVDS) += rcar_du_lvdsenc.o 9rcar-du-drm-$(CONFIG_DRM_RCAR_LVDS) += rcar_du_lvdsenc.o
13 10
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_encoder.c b/drivers/gpu/drm/rcar-du/rcar_du_encoder.c
index 3a3c9374794e..92a0405c2fb2 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_encoder.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_encoder.c
@@ -20,11 +20,9 @@
20 20
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"
24#include "rcar_du_kms.h" 23#include "rcar_du_kms.h"
25#include "rcar_du_lvdscon.h" 24#include "rcar_du_lvdscon.h"
26#include "rcar_du_lvdsenc.h" 25#include "rcar_du_lvdsenc.h"
27#include "rcar_du_vgacon.h"
28 26
29/* ----------------------------------------------------------------------------- 27/* -----------------------------------------------------------------------------
30 * Encoder 28 * Encoder
@@ -63,29 +61,35 @@ static int rcar_du_encoder_atomic_check(struct drm_encoder *encoder,
63 struct rcar_du_encoder *renc = to_rcar_encoder(encoder); 61 struct rcar_du_encoder *renc = to_rcar_encoder(encoder);
64 struct drm_display_mode *adjusted_mode = &crtc_state->adjusted_mode; 62 struct drm_display_mode *adjusted_mode = &crtc_state->adjusted_mode;
65 const struct drm_display_mode *mode = &crtc_state->mode; 63 const struct drm_display_mode *mode = &crtc_state->mode;
66 const struct drm_display_mode *panel_mode;
67 struct drm_connector *connector = conn_state->connector; 64 struct drm_connector *connector = conn_state->connector;
68 struct drm_device *dev = encoder->dev; 65 struct drm_device *dev = encoder->dev;
69 66
70 /* DAC encoders have currently no restriction on the mode. */ 67 /*
71 if (encoder->encoder_type == DRM_MODE_ENCODER_DAC) 68 * Only panel-related encoder types require validation here, everything
72 return 0; 69 * else is handled by the bridge drivers.
70 */
71 if (encoder->encoder_type == DRM_MODE_ENCODER_LVDS) {
72 const struct drm_display_mode *panel_mode;
73 73
74 if (list_empty(&connector->modes)) { 74 if (list_empty(&connector->modes)) {
75 dev_dbg(dev->dev, "encoder: empty modes list\n"); 75 dev_dbg(dev->dev, "encoder: empty modes list\n");
76 return -EINVAL; 76 return -EINVAL;
77 } 77 }
78 78
79 panel_mode = list_first_entry(&connector->modes, 79 panel_mode = list_first_entry(&connector->modes,
80 struct drm_display_mode, head); 80 struct drm_display_mode, head);
81 81
82 /* We're not allowed to modify the resolution. */ 82 /* We're not allowed to modify the resolution. */
83 if (mode->hdisplay != panel_mode->hdisplay || 83 if (mode->hdisplay != panel_mode->hdisplay ||
84 mode->vdisplay != panel_mode->vdisplay) 84 mode->vdisplay != panel_mode->vdisplay)
85 return -EINVAL; 85 return -EINVAL;
86 86
87 /* The flat panel mode is fixed, just copy it to the adjusted mode. */ 87 /*
88 drm_mode_copy(adjusted_mode, panel_mode); 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 }
89 93
90 if (renc->lvds) 94 if (renc->lvds)
91 rcar_du_lvdsenc_atomic_check(renc->lvds, adjusted_mode); 95 rcar_du_lvdsenc_atomic_check(renc->lvds, adjusted_mode);
@@ -159,6 +163,7 @@ int rcar_du_encoder_init(struct rcar_du_device *rcdu,
159{ 163{
160 struct rcar_du_encoder *renc; 164 struct rcar_du_encoder *renc;
161 struct drm_encoder *encoder; 165 struct drm_encoder *encoder;
166 struct drm_bridge *bridge = NULL;
162 unsigned int encoder_type; 167 unsigned int encoder_type;
163 int ret; 168 int ret;
164 169
@@ -182,6 +187,15 @@ int rcar_du_encoder_init(struct rcar_du_device *rcdu,
182 break; 187 break;
183 } 188 }
184 189
190 if (enc_node) {
191 /* Locate the DRM bridge from the encoder DT node. */
192 bridge = of_drm_find_bridge(enc_node);
193 if (!bridge) {
194 ret = -EPROBE_DEFER;
195 goto done;
196 }
197 }
198
185 switch (type) { 199 switch (type) {
186 case RCAR_DU_ENCODER_VGA: 200 case RCAR_DU_ENCODER_VGA:
187 encoder_type = DRM_MODE_ENCODER_DAC; 201 encoder_type = DRM_MODE_ENCODER_DAC;
@@ -199,35 +213,35 @@ int rcar_du_encoder_init(struct rcar_du_device *rcdu,
199 break; 213 break;
200 } 214 }
201 215
202 if (type == RCAR_DU_ENCODER_HDMI) { 216 ret = drm_encoder_init(rcdu->ddev, encoder, &encoder_funcs,
203 ret = rcar_du_hdmienc_init(rcdu, renc, enc_node); 217 encoder_type, NULL);
204 if (ret < 0) 218 if (ret < 0)
205 goto done; 219 goto done;
206 } else {
207 ret = drm_encoder_init(rcdu->ddev, encoder, &encoder_funcs,
208 encoder_type, NULL);
209 if (ret < 0)
210 goto done;
211
212 drm_encoder_helper_add(encoder, &encoder_helper_funcs);
213 }
214
215 switch (encoder_type) {
216 case DRM_MODE_ENCODER_LVDS:
217 ret = rcar_du_lvds_connector_init(rcdu, renc, con_node);
218 break;
219
220 case DRM_MODE_ENCODER_DAC:
221 ret = rcar_du_vga_connector_init(rcdu, renc);
222 break;
223 220
224 case DRM_MODE_ENCODER_TMDS: 221 drm_encoder_helper_add(encoder, &encoder_helper_funcs);
225 /* connector managed by the bridge driver */
226 break;
227 222
228 default: 223 if (bridge) {
229 ret = -EINVAL; 224 /*
230 break; 225 * Attach the bridge to the encoder. The bridge will create the
226 * connector.
227 */
228 ret = drm_bridge_attach(encoder, bridge, NULL);
229 if (ret) {
230 drm_encoder_cleanup(encoder);
231 return ret;
232 }
233 } else {
234 /* There's no bridge, create the connector manually. */
235 switch (output) {
236 case RCAR_DU_OUTPUT_LVDS0:
237 case RCAR_DU_OUTPUT_LVDS1:
238 ret = rcar_du_lvds_connector_init(rcdu, renc, con_node);
239 break;
240
241 default:
242 ret = -EINVAL;
243 break;
244 }
231 } 245 }
232 246
233done: 247done:
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_encoder.h b/drivers/gpu/drm/rcar-du/rcar_du_encoder.h
index b79b2f075a74..c1cfbe0d54ce 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_encoder.h
+++ b/drivers/gpu/drm/rcar-du/rcar_du_encoder.h
@@ -19,7 +19,6 @@
19 19
20struct drm_panel; 20struct drm_panel;
21struct rcar_du_device; 21struct rcar_du_device;
22struct rcar_du_hdmienc;
23struct rcar_du_lvdsenc; 22struct rcar_du_lvdsenc;
24 23
25enum rcar_du_encoder_type { 24enum rcar_du_encoder_type {
@@ -34,7 +33,6 @@ struct rcar_du_encoder {
34 struct drm_encoder base; 33 struct drm_encoder base;
35 enum rcar_du_output output; 34 enum rcar_du_output output;
36 struct rcar_du_connector *connector; 35 struct rcar_du_connector *connector;
37 struct rcar_du_hdmienc *hdmi;
38 struct rcar_du_lvdsenc *lvds; 36 struct rcar_du_lvdsenc *lvds;
39}; 37};
40 38
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_hdmienc.c b/drivers/gpu/drm/rcar-du/rcar_du_hdmienc.c
deleted file mode 100644
index 933a2547798e..000000000000
--- a/drivers/gpu/drm/rcar-du/rcar_du_hdmienc.c
+++ /dev/null
@@ -1,134 +0,0 @@
1/*
2 * R-Car Display Unit HDMI Encoder
3 *
4 * Copyright (C) 2014 Renesas Electronics Corporation
5 *
6 * 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.
12 */
13
14#include <linux/slab.h>
15
16#include <drm/drmP.h>
17#include <drm/drm_crtc.h>
18#include <drm/drm_crtc_helper.h>
19
20#include "rcar_du_drv.h"
21#include "rcar_du_encoder.h"
22#include "rcar_du_hdmienc.h"
23#include "rcar_du_lvdsenc.h"
24
25struct rcar_du_hdmienc {
26 struct rcar_du_encoder *renc;
27 bool enabled;
28};
29
30#define to_rcar_hdmienc(e) (to_rcar_encoder(e)->hdmi)
31
32static void rcar_du_hdmienc_disable(struct drm_encoder *encoder)
33{
34 struct rcar_du_hdmienc *hdmienc = to_rcar_hdmienc(encoder);
35
36 if (hdmienc->renc->lvds)
37 rcar_du_lvdsenc_enable(hdmienc->renc->lvds, encoder->crtc,
38 false);
39
40 hdmienc->enabled = false;
41}
42
43static void rcar_du_hdmienc_enable(struct drm_encoder *encoder)
44{
45 struct rcar_du_hdmienc *hdmienc = to_rcar_hdmienc(encoder);
46
47 if (hdmienc->renc->lvds)
48 rcar_du_lvdsenc_enable(hdmienc->renc->lvds, encoder->crtc,
49 true);
50
51 hdmienc->enabled = true;
52}
53
54static int rcar_du_hdmienc_atomic_check(struct drm_encoder *encoder,
55 struct drm_crtc_state *crtc_state,
56 struct drm_connector_state *conn_state)
57{
58 struct rcar_du_hdmienc *hdmienc = to_rcar_hdmienc(encoder);
59 struct drm_display_mode *adjusted_mode = &crtc_state->adjusted_mode;
60
61 if (hdmienc->renc->lvds)
62 rcar_du_lvdsenc_atomic_check(hdmienc->renc->lvds,
63 adjusted_mode);
64
65 return 0;
66}
67
68
69static void rcar_du_hdmienc_mode_set(struct drm_encoder *encoder,
70 struct drm_crtc_state *crtc_state,
71 struct drm_connector_state *conn_state)
72{
73 struct rcar_du_hdmienc *hdmienc = to_rcar_hdmienc(encoder);
74
75 rcar_du_crtc_route_output(crtc_state->crtc, hdmienc->renc->output);
76}
77
78static const struct drm_encoder_helper_funcs encoder_helper_funcs = {
79 .atomic_mode_set = rcar_du_hdmienc_mode_set,
80 .disable = rcar_du_hdmienc_disable,
81 .enable = rcar_du_hdmienc_enable,
82 .atomic_check = rcar_du_hdmienc_atomic_check,
83};
84
85static void rcar_du_hdmienc_cleanup(struct drm_encoder *encoder)
86{
87 struct rcar_du_hdmienc *hdmienc = to_rcar_hdmienc(encoder);
88
89 if (hdmienc->enabled)
90 rcar_du_hdmienc_disable(encoder);
91
92 drm_encoder_cleanup(encoder);
93}
94
95static const struct drm_encoder_funcs encoder_funcs = {
96 .destroy = rcar_du_hdmienc_cleanup,
97};
98
99int rcar_du_hdmienc_init(struct rcar_du_device *rcdu,
100 struct rcar_du_encoder *renc, struct device_node *np)
101{
102 struct drm_encoder *encoder = rcar_encoder_to_drm_encoder(renc);
103 struct drm_bridge *bridge;
104 struct rcar_du_hdmienc *hdmienc;
105 int ret;
106
107 hdmienc = devm_kzalloc(rcdu->dev, sizeof(*hdmienc), GFP_KERNEL);
108 if (hdmienc == NULL)
109 return -ENOMEM;
110
111 /* Locate the DRM bridge from the HDMI encoder DT node. */
112 bridge = of_drm_find_bridge(np);
113 if (!bridge)
114 return -EPROBE_DEFER;
115
116 ret = drm_encoder_init(rcdu->ddev, encoder, &encoder_funcs,
117 DRM_MODE_ENCODER_TMDS, NULL);
118 if (ret < 0)
119 return ret;
120
121 drm_encoder_helper_add(encoder, &encoder_helper_funcs);
122
123 renc->hdmi = hdmienc;
124 hdmienc->renc = renc;
125
126 /* Link the bridge to the encoder. */
127 ret = drm_bridge_attach(encoder, bridge, NULL);
128 if (ret) {
129 drm_encoder_cleanup(encoder);
130 return ret;
131 }
132
133 return 0;
134}
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_hdmienc.h b/drivers/gpu/drm/rcar-du/rcar_du_hdmienc.h
deleted file mode 100644
index 2ff0128ac8e1..000000000000
--- a/drivers/gpu/drm/rcar-du/rcar_du_hdmienc.h
+++ /dev/null
@@ -1,35 +0,0 @@
1/*
2 * R-Car Display Unit HDMI Encoder
3 *
4 * Copyright (C) 2014 Renesas Electronics Corporation
5 *
6 * 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.
12 */
13
14#ifndef __RCAR_DU_HDMIENC_H__
15#define __RCAR_DU_HDMIENC_H__
16
17#include <linux/module.h>
18
19struct device_node;
20struct rcar_du_device;
21struct rcar_du_encoder;
22
23#if IS_ENABLED(CONFIG_DRM_RCAR_HDMI)
24int rcar_du_hdmienc_init(struct rcar_du_device *rcdu,
25 struct rcar_du_encoder *renc, struct device_node *np);
26#else
27static inline int rcar_du_hdmienc_init(struct rcar_du_device *rcdu,
28 struct rcar_du_encoder *renc,
29 struct device_node *np)
30{
31 return -ENOSYS;
32}
33#endif
34
35#endif /* __RCAR_DU_HDMIENC_H__ */
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_vgacon.c b/drivers/gpu/drm/rcar-du/rcar_du_vgacon.c
deleted file mode 100644
index 8d6125c1c0f9..000000000000
--- a/drivers/gpu/drm/rcar-du/rcar_du_vgacon.c
+++ /dev/null
@@ -1,82 +0,0 @@
1/*
2 * rcar_du_vgacon.c -- R-Car Display Unit VGA Connector
3 *
4 * Copyright (C) 2013-2014 Renesas Electronics Corporation
5 *
6 * 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.
12 */
13
14#include <drm/drmP.h>
15#include <drm/drm_atomic_helper.h>
16#include <drm/drm_crtc.h>
17#include <drm/drm_crtc_helper.h>
18
19#include "rcar_du_drv.h"
20#include "rcar_du_encoder.h"
21#include "rcar_du_kms.h"
22#include "rcar_du_vgacon.h"
23
24static int rcar_du_vga_connector_get_modes(struct drm_connector *connector)
25{
26 return 0;
27}
28
29static const struct drm_connector_helper_funcs connector_helper_funcs = {
30 .get_modes = rcar_du_vga_connector_get_modes,
31};
32
33static enum drm_connector_status
34rcar_du_vga_connector_detect(struct drm_connector *connector, bool force)
35{
36 return connector_status_connected;
37}
38
39static const struct drm_connector_funcs connector_funcs = {
40 .dpms = drm_atomic_helper_connector_dpms,
41 .reset = drm_atomic_helper_connector_reset,
42 .detect = rcar_du_vga_connector_detect,
43 .fill_modes = drm_helper_probe_single_connector_modes,
44 .destroy = drm_connector_cleanup,
45 .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
46 .atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
47};
48
49int rcar_du_vga_connector_init(struct rcar_du_device *rcdu,
50 struct rcar_du_encoder *renc)
51{
52 struct drm_encoder *encoder = rcar_encoder_to_drm_encoder(renc);
53 struct rcar_du_connector *rcon;
54 struct drm_connector *connector;
55 int ret;
56
57 rcon = devm_kzalloc(rcdu->dev, sizeof(*rcon), GFP_KERNEL);
58 if (rcon == NULL)
59 return -ENOMEM;
60
61 connector = &rcon->connector;
62 connector->display_info.width_mm = 0;
63 connector->display_info.height_mm = 0;
64 connector->interlace_allowed = true;
65
66 ret = drm_connector_init(rcdu->ddev, connector, &connector_funcs,
67 DRM_MODE_CONNECTOR_VGA);
68 if (ret < 0)
69 return ret;
70
71 drm_connector_helper_add(connector, &connector_helper_funcs);
72
73 connector->dpms = DRM_MODE_DPMS_OFF;
74 drm_object_property_set_value(&connector->base,
75 rcdu->ddev->mode_config.dpms_property, DRM_MODE_DPMS_OFF);
76
77 ret = drm_mode_connector_attach_encoder(connector, encoder);
78 if (ret < 0)
79 return ret;
80
81 return 0;
82}
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_vgacon.h b/drivers/gpu/drm/rcar-du/rcar_du_vgacon.h
deleted file mode 100644
index 112f50316e01..000000000000
--- a/drivers/gpu/drm/rcar-du/rcar_du_vgacon.h
+++ /dev/null
@@ -1,23 +0,0 @@
1/*
2 * rcar_du_vgacon.h -- R-Car Display Unit VGA Connector
3 *
4 * Copyright (C) 2013-2014 Renesas Electronics Corporation
5 *
6 * 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.
12 */
13
14#ifndef __RCAR_DU_VGACON_H__
15#define __RCAR_DU_VGACON_H__
16
17struct rcar_du_device;
18struct rcar_du_encoder;
19
20int rcar_du_vga_connector_init(struct rcar_du_device *rcdu,
21 struct rcar_du_encoder *renc);
22
23#endif /* __RCAR_DU_VGACON_H__ */