diff options
author | Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com> | 2014-03-30 15:55:38 -0400 |
---|---|---|
committer | Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com> | 2014-11-26 13:09:38 -0500 |
commit | 637e6194e0daf76e2c06cd78528e8d0a24eca3cd (patch) | |
tree | f778c0194563c9e12899bcaa492abc91e75b429c | |
parent | 69746b4112e3c83442c1df59b7011ab3c5ed2d5a (diff) |
drm: rcar-du: Add HDMI encoder and connector support
SoCs that integrate the DU have no internal HDMI encoder, support
external encoders only.
Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
-rw-r--r-- | drivers/gpu/drm/rcar-du/Kconfig | 11 | ||||
-rw-r--r-- | drivers/gpu/drm/rcar-du/Makefile | 2 | ||||
-rw-r--r-- | drivers/gpu/drm/rcar-du/rcar_du_encoder.c | 30 | ||||
-rw-r--r-- | drivers/gpu/drm/rcar-du/rcar_du_encoder.h | 3 | ||||
-rw-r--r-- | drivers/gpu/drm/rcar-du/rcar_du_hdmicon.c | 118 | ||||
-rw-r--r-- | drivers/gpu/drm/rcar-du/rcar_du_hdmicon.h | 31 | ||||
-rw-r--r-- | drivers/gpu/drm/rcar-du/rcar_du_hdmienc.c | 151 | ||||
-rw-r--r-- | drivers/gpu/drm/rcar-du/rcar_du_hdmienc.h | 35 | ||||
-rw-r--r-- | drivers/gpu/drm/rcar-du/rcar_du_kms.c | 1 |
9 files changed, 375 insertions, 7 deletions
diff --git a/drivers/gpu/drm/rcar-du/Kconfig b/drivers/gpu/drm/rcar-du/Kconfig index c96f6089f8bf..2324a526de65 100644 --- a/drivers/gpu/drm/rcar-du/Kconfig +++ b/drivers/gpu/drm/rcar-du/Kconfig | |||
@@ -11,10 +11,17 @@ 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 | ||
14 | config DRM_RCAR_HDMI | ||
15 | bool "R-Car DU HDMI Encoder Support" | ||
16 | depends on DRM_RCAR_DU | ||
17 | depends on OF | ||
18 | help | ||
19 | Enable support for external HDMI encoders. | ||
20 | |||
14 | config DRM_RCAR_LVDS | 21 | config DRM_RCAR_LVDS |
15 | bool "R-Car DU LVDS Encoder Support" | 22 | bool "R-Car DU LVDS Encoder Support" |
16 | depends on DRM_RCAR_DU | 23 | depends on DRM_RCAR_DU |
17 | depends on ARCH_R8A7790 || ARCH_R8A7791 || COMPILE_TEST | 24 | depends on ARCH_R8A7790 || ARCH_R8A7791 || COMPILE_TEST |
18 | help | 25 | help |
19 | Enable support the R-Car Display Unit embedded LVDS encoders | 26 | Enable support for the R-Car Display Unit embedded LVDS encoders |
20 | (currently only on R8A7790). | 27 | (currently only on R8A7790 and R8A7791). |
diff --git a/drivers/gpu/drm/rcar-du/Makefile b/drivers/gpu/drm/rcar-du/Makefile index 12b8d4477835..05de1c4097af 100644 --- a/drivers/gpu/drm/rcar-du/Makefile +++ b/drivers/gpu/drm/rcar-du/Makefile | |||
@@ -7,6 +7,8 @@ rcar-du-drm-y := rcar_du_crtc.o \ | |||
7 | rcar_du_plane.o \ | 7 | rcar_du_plane.o \ |
8 | rcar_du_vgacon.o | 8 | rcar_du_vgacon.o |
9 | 9 | ||
10 | rcar-du-drm-$(CONFIG_DRM_RCAR_HDMI) += rcar_du_hdmicon.o \ | ||
11 | rcar_du_hdmienc.o | ||
10 | rcar-du-drm-$(CONFIG_DRM_RCAR_LVDS) += rcar_du_lvdsenc.o | 12 | rcar-du-drm-$(CONFIG_DRM_RCAR_LVDS) += rcar_du_lvdsenc.o |
11 | 13 | ||
12 | obj-$(CONFIG_DRM_RCAR_DU) += rcar-du-drm.o | 14 | obj-$(CONFIG_DRM_RCAR_DU) += rcar-du-drm.o |
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_encoder.c b/drivers/gpu/drm/rcar-du/rcar_du_encoder.c index e88e63b06b09..34a122a39664 100644 --- a/drivers/gpu/drm/rcar-du/rcar_du_encoder.c +++ b/drivers/gpu/drm/rcar-du/rcar_du_encoder.c | |||
@@ -19,6 +19,8 @@ | |||
19 | 19 | ||
20 | #include "rcar_du_drv.h" | 20 | #include "rcar_du_drv.h" |
21 | #include "rcar_du_encoder.h" | 21 | #include "rcar_du_encoder.h" |
22 | #include "rcar_du_hdmicon.h" | ||
23 | #include "rcar_du_hdmienc.h" | ||
22 | #include "rcar_du_kms.h" | 24 | #include "rcar_du_kms.h" |
23 | #include "rcar_du_lvdscon.h" | 25 | #include "rcar_du_lvdscon.h" |
24 | #include "rcar_du_lvdsenc.h" | 26 | #include "rcar_du_lvdsenc.h" |
@@ -177,6 +179,9 @@ int rcar_du_encoder_init(struct rcar_du_device *rcdu, | |||
177 | case RCAR_DU_ENCODER_LVDS: | 179 | case RCAR_DU_ENCODER_LVDS: |
178 | encoder_type = DRM_MODE_ENCODER_LVDS; | 180 | encoder_type = DRM_MODE_ENCODER_LVDS; |
179 | break; | 181 | break; |
182 | case RCAR_DU_ENCODER_HDMI: | ||
183 | encoder_type = DRM_MODE_ENCODER_TMDS; | ||
184 | break; | ||
180 | case RCAR_DU_ENCODER_NONE: | 185 | case RCAR_DU_ENCODER_NONE: |
181 | default: | 186 | default: |
182 | /* No external encoder, use the internal encoder type. */ | 187 | /* No external encoder, use the internal encoder type. */ |
@@ -184,12 +189,24 @@ int rcar_du_encoder_init(struct rcar_du_device *rcdu, | |||
184 | break; | 189 | break; |
185 | } | 190 | } |
186 | 191 | ||
187 | ret = drm_encoder_init(rcdu->ddev, encoder, &encoder_funcs, | 192 | if (type == RCAR_DU_ENCODER_HDMI) { |
188 | encoder_type); | 193 | if (renc->lvds) { |
189 | if (ret < 0) | 194 | dev_err(rcdu->dev, |
190 | return ret; | 195 | "Chaining LVDS and HDMI encoders not supported\n"); |
196 | return -EINVAL; | ||
197 | } | ||
191 | 198 | ||
192 | drm_encoder_helper_add(encoder, &encoder_helper_funcs); | 199 | ret = rcar_du_hdmienc_init(rcdu, renc, enc_node); |
200 | if (ret < 0) | ||
201 | return ret; | ||
202 | } else { | ||
203 | ret = drm_encoder_init(rcdu->ddev, encoder, &encoder_funcs, | ||
204 | encoder_type); | ||
205 | if (ret < 0) | ||
206 | return ret; | ||
207 | |||
208 | drm_encoder_helper_add(encoder, &encoder_helper_funcs); | ||
209 | } | ||
193 | 210 | ||
194 | switch (encoder_type) { | 211 | switch (encoder_type) { |
195 | case DRM_MODE_ENCODER_LVDS: | 212 | case DRM_MODE_ENCODER_LVDS: |
@@ -198,6 +215,9 @@ int rcar_du_encoder_init(struct rcar_du_device *rcdu, | |||
198 | case DRM_MODE_ENCODER_DAC: | 215 | case DRM_MODE_ENCODER_DAC: |
199 | return rcar_du_vga_connector_init(rcdu, renc); | 216 | return rcar_du_vga_connector_init(rcdu, renc); |
200 | 217 | ||
218 | case DRM_MODE_ENCODER_TMDS: | ||
219 | return rcar_du_hdmi_connector_init(rcdu, renc); | ||
220 | |||
201 | default: | 221 | default: |
202 | return -EINVAL; | 222 | return -EINVAL; |
203 | } | 223 | } |
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_encoder.h b/drivers/gpu/drm/rcar-du/rcar_du_encoder.h index c4dccdbcff33..719b6f2a031c 100644 --- a/drivers/gpu/drm/rcar-du/rcar_du_encoder.h +++ b/drivers/gpu/drm/rcar-du/rcar_du_encoder.h | |||
@@ -18,6 +18,7 @@ | |||
18 | #include <drm/drm_encoder_slave.h> | 18 | #include <drm/drm_encoder_slave.h> |
19 | 19 | ||
20 | struct rcar_du_device; | 20 | struct rcar_du_device; |
21 | struct rcar_du_hdmienc; | ||
21 | struct rcar_du_lvdsenc; | 22 | struct rcar_du_lvdsenc; |
22 | 23 | ||
23 | enum rcar_du_encoder_type { | 24 | enum rcar_du_encoder_type { |
@@ -25,11 +26,13 @@ enum rcar_du_encoder_type { | |||
25 | RCAR_DU_ENCODER_NONE, | 26 | RCAR_DU_ENCODER_NONE, |
26 | RCAR_DU_ENCODER_VGA, | 27 | RCAR_DU_ENCODER_VGA, |
27 | RCAR_DU_ENCODER_LVDS, | 28 | RCAR_DU_ENCODER_LVDS, |
29 | RCAR_DU_ENCODER_HDMI, | ||
28 | }; | 30 | }; |
29 | 31 | ||
30 | struct rcar_du_encoder { | 32 | struct rcar_du_encoder { |
31 | struct drm_encoder_slave slave; | 33 | struct drm_encoder_slave slave; |
32 | enum rcar_du_output output; | 34 | enum rcar_du_output output; |
35 | struct rcar_du_hdmienc *hdmi; | ||
33 | struct rcar_du_lvdsenc *lvds; | 36 | struct rcar_du_lvdsenc *lvds; |
34 | }; | 37 | }; |
35 | 38 | ||
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_hdmicon.c b/drivers/gpu/drm/rcar-du/rcar_du_hdmicon.c new file mode 100644 index 000000000000..8abaaf258f45 --- /dev/null +++ b/drivers/gpu/drm/rcar-du/rcar_du_hdmicon.c | |||
@@ -0,0 +1,118 @@ | |||
1 | /* | ||
2 | * R-Car Display Unit HDMI Connector | ||
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 <drm/drmP.h> | ||
15 | #include <drm/drm_crtc.h> | ||
16 | #include <drm/drm_crtc_helper.h> | ||
17 | #include <drm/drm_encoder_slave.h> | ||
18 | |||
19 | #include "rcar_du_drv.h" | ||
20 | #include "rcar_du_encoder.h" | ||
21 | #include "rcar_du_hdmicon.h" | ||
22 | #include "rcar_du_kms.h" | ||
23 | |||
24 | #define to_slave_funcs(e) (to_rcar_encoder(e)->slave.slave_funcs) | ||
25 | |||
26 | static int rcar_du_hdmi_connector_get_modes(struct drm_connector *connector) | ||
27 | { | ||
28 | struct drm_encoder *encoder = connector->encoder; | ||
29 | struct drm_encoder_slave_funcs *sfuncs = to_slave_funcs(encoder); | ||
30 | |||
31 | if (sfuncs->get_modes == NULL) | ||
32 | return 0; | ||
33 | |||
34 | return sfuncs->get_modes(encoder, connector); | ||
35 | } | ||
36 | |||
37 | static int rcar_du_hdmi_connector_mode_valid(struct drm_connector *connector, | ||
38 | struct drm_display_mode *mode) | ||
39 | { | ||
40 | struct drm_encoder *encoder = connector->encoder; | ||
41 | struct drm_encoder_slave_funcs *sfuncs = to_slave_funcs(encoder); | ||
42 | |||
43 | if (sfuncs->mode_valid == NULL) | ||
44 | return MODE_OK; | ||
45 | |||
46 | return sfuncs->mode_valid(encoder, mode); | ||
47 | } | ||
48 | |||
49 | static const struct drm_connector_helper_funcs connector_helper_funcs = { | ||
50 | .get_modes = rcar_du_hdmi_connector_get_modes, | ||
51 | .mode_valid = rcar_du_hdmi_connector_mode_valid, | ||
52 | .best_encoder = rcar_du_connector_best_encoder, | ||
53 | }; | ||
54 | |||
55 | static void rcar_du_hdmi_connector_destroy(struct drm_connector *connector) | ||
56 | { | ||
57 | drm_connector_unregister(connector); | ||
58 | drm_connector_cleanup(connector); | ||
59 | } | ||
60 | |||
61 | static enum drm_connector_status | ||
62 | rcar_du_hdmi_connector_detect(struct drm_connector *connector, bool force) | ||
63 | { | ||
64 | struct drm_encoder *encoder = connector->encoder; | ||
65 | struct drm_encoder_slave_funcs *sfuncs = to_slave_funcs(encoder); | ||
66 | |||
67 | if (sfuncs->detect == NULL) | ||
68 | return connector_status_unknown; | ||
69 | |||
70 | return sfuncs->detect(encoder, connector); | ||
71 | } | ||
72 | |||
73 | static const struct drm_connector_funcs connector_funcs = { | ||
74 | .dpms = drm_helper_connector_dpms, | ||
75 | .detect = rcar_du_hdmi_connector_detect, | ||
76 | .fill_modes = drm_helper_probe_single_connector_modes, | ||
77 | .destroy = rcar_du_hdmi_connector_destroy, | ||
78 | }; | ||
79 | |||
80 | int rcar_du_hdmi_connector_init(struct rcar_du_device *rcdu, | ||
81 | struct rcar_du_encoder *renc) | ||
82 | { | ||
83 | struct drm_encoder *encoder = rcar_encoder_to_drm_encoder(renc); | ||
84 | struct rcar_du_connector *rcon; | ||
85 | struct drm_connector *connector; | ||
86 | int ret; | ||
87 | |||
88 | rcon = devm_kzalloc(rcdu->dev, sizeof(*rcon), GFP_KERNEL); | ||
89 | if (rcon == NULL) | ||
90 | return -ENOMEM; | ||
91 | |||
92 | connector = &rcon->connector; | ||
93 | connector->display_info.width_mm = 0; | ||
94 | connector->display_info.height_mm = 0; | ||
95 | |||
96 | ret = drm_connector_init(rcdu->ddev, connector, &connector_funcs, | ||
97 | DRM_MODE_CONNECTOR_HDMIA); | ||
98 | if (ret < 0) | ||
99 | return ret; | ||
100 | |||
101 | drm_connector_helper_add(connector, &connector_helper_funcs); | ||
102 | ret = drm_connector_register(connector); | ||
103 | if (ret < 0) | ||
104 | return ret; | ||
105 | |||
106 | drm_helper_connector_dpms(connector, DRM_MODE_DPMS_OFF); | ||
107 | drm_object_property_set_value(&connector->base, | ||
108 | rcdu->ddev->mode_config.dpms_property, DRM_MODE_DPMS_OFF); | ||
109 | |||
110 | ret = drm_mode_connector_attach_encoder(connector, encoder); | ||
111 | if (ret < 0) | ||
112 | return ret; | ||
113 | |||
114 | connector->encoder = encoder; | ||
115 | rcon->encoder = renc; | ||
116 | |||
117 | return 0; | ||
118 | } | ||
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_hdmicon.h b/drivers/gpu/drm/rcar-du/rcar_du_hdmicon.h new file mode 100644 index 000000000000..87daa949227f --- /dev/null +++ b/drivers/gpu/drm/rcar-du/rcar_du_hdmicon.h | |||
@@ -0,0 +1,31 @@ | |||
1 | /* | ||
2 | * R-Car Display Unit HDMI Connector | ||
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_HDMICON_H__ | ||
15 | #define __RCAR_DU_HDMICON_H__ | ||
16 | |||
17 | struct rcar_du_device; | ||
18 | struct rcar_du_encoder; | ||
19 | |||
20 | #if IS_ENABLED(CONFIG_DRM_RCAR_HDMI) | ||
21 | int rcar_du_hdmi_connector_init(struct rcar_du_device *rcdu, | ||
22 | struct rcar_du_encoder *renc); | ||
23 | #else | ||
24 | static inline int rcar_du_hdmi_connector_init(struct rcar_du_device *rcdu, | ||
25 | struct rcar_du_encoder *renc) | ||
26 | { | ||
27 | return -ENOSYS; | ||
28 | } | ||
29 | #endif | ||
30 | |||
31 | #endif /* __RCAR_DU_HDMICON_H__ */ | ||
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_hdmienc.c b/drivers/gpu/drm/rcar-du/rcar_du_hdmienc.c new file mode 100644 index 000000000000..359bc999a9c8 --- /dev/null +++ b/drivers/gpu/drm/rcar-du/rcar_du_hdmienc.c | |||
@@ -0,0 +1,151 @@ | |||
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 | #include <drm/drm_encoder_slave.h> | ||
20 | |||
21 | #include "rcar_du_drv.h" | ||
22 | #include "rcar_du_encoder.h" | ||
23 | #include "rcar_du_hdmienc.h" | ||
24 | |||
25 | struct rcar_du_hdmienc { | ||
26 | struct rcar_du_encoder *renc; | ||
27 | struct device *dev; | ||
28 | int dpms; | ||
29 | }; | ||
30 | |||
31 | #define to_rcar_hdmienc(e) (to_rcar_encoder(e)->hdmi) | ||
32 | #define to_slave_funcs(e) (to_rcar_encoder(e)->slave.slave_funcs) | ||
33 | |||
34 | static void rcar_du_hdmienc_dpms(struct drm_encoder *encoder, int mode) | ||
35 | { | ||
36 | struct rcar_du_hdmienc *hdmienc = to_rcar_hdmienc(encoder); | ||
37 | struct drm_encoder_slave_funcs *sfuncs = to_slave_funcs(encoder); | ||
38 | |||
39 | if (hdmienc->dpms == mode) | ||
40 | return; | ||
41 | |||
42 | if (sfuncs->dpms) | ||
43 | sfuncs->dpms(encoder, mode); | ||
44 | |||
45 | hdmienc->dpms = mode; | ||
46 | } | ||
47 | |||
48 | static bool rcar_du_hdmienc_mode_fixup(struct drm_encoder *encoder, | ||
49 | const struct drm_display_mode *mode, | ||
50 | struct drm_display_mode *adjusted_mode) | ||
51 | { | ||
52 | struct drm_encoder_slave_funcs *sfuncs = to_slave_funcs(encoder); | ||
53 | |||
54 | if (sfuncs->mode_fixup == NULL) | ||
55 | return true; | ||
56 | |||
57 | return sfuncs->mode_fixup(encoder, mode, adjusted_mode); | ||
58 | } | ||
59 | |||
60 | static void rcar_du_hdmienc_mode_prepare(struct drm_encoder *encoder) | ||
61 | { | ||
62 | rcar_du_hdmienc_dpms(encoder, DRM_MODE_DPMS_OFF); | ||
63 | } | ||
64 | |||
65 | static void rcar_du_hdmienc_mode_commit(struct drm_encoder *encoder) | ||
66 | { | ||
67 | rcar_du_hdmienc_dpms(encoder, DRM_MODE_DPMS_ON); | ||
68 | } | ||
69 | |||
70 | static void rcar_du_hdmienc_mode_set(struct drm_encoder *encoder, | ||
71 | struct drm_display_mode *mode, | ||
72 | struct drm_display_mode *adjusted_mode) | ||
73 | { | ||
74 | struct rcar_du_hdmienc *hdmienc = to_rcar_hdmienc(encoder); | ||
75 | struct drm_encoder_slave_funcs *sfuncs = to_slave_funcs(encoder); | ||
76 | |||
77 | if (sfuncs->mode_set) | ||
78 | sfuncs->mode_set(encoder, mode, adjusted_mode); | ||
79 | |||
80 | rcar_du_crtc_route_output(encoder->crtc, hdmienc->renc->output); | ||
81 | } | ||
82 | |||
83 | static const struct drm_encoder_helper_funcs encoder_helper_funcs = { | ||
84 | .dpms = rcar_du_hdmienc_dpms, | ||
85 | .mode_fixup = rcar_du_hdmienc_mode_fixup, | ||
86 | .prepare = rcar_du_hdmienc_mode_prepare, | ||
87 | .commit = rcar_du_hdmienc_mode_commit, | ||
88 | .mode_set = rcar_du_hdmienc_mode_set, | ||
89 | }; | ||
90 | |||
91 | static void rcar_du_hdmienc_cleanup(struct drm_encoder *encoder) | ||
92 | { | ||
93 | struct rcar_du_hdmienc *hdmienc = to_rcar_hdmienc(encoder); | ||
94 | |||
95 | rcar_du_hdmienc_dpms(encoder, DRM_MODE_DPMS_OFF); | ||
96 | |||
97 | drm_encoder_cleanup(encoder); | ||
98 | put_device(hdmienc->dev); | ||
99 | } | ||
100 | |||
101 | static const struct drm_encoder_funcs encoder_funcs = { | ||
102 | .destroy = rcar_du_hdmienc_cleanup, | ||
103 | }; | ||
104 | |||
105 | int rcar_du_hdmienc_init(struct rcar_du_device *rcdu, | ||
106 | struct rcar_du_encoder *renc, struct device_node *np) | ||
107 | { | ||
108 | struct drm_encoder *encoder = rcar_encoder_to_drm_encoder(renc); | ||
109 | struct drm_i2c_encoder_driver *driver; | ||
110 | struct i2c_client *i2c_slave; | ||
111 | struct rcar_du_hdmienc *hdmienc; | ||
112 | int ret; | ||
113 | |||
114 | hdmienc = devm_kzalloc(rcdu->dev, sizeof(*hdmienc), GFP_KERNEL); | ||
115 | if (hdmienc == NULL) | ||
116 | return -ENOMEM; | ||
117 | |||
118 | /* Locate the slave I2C device and driver. */ | ||
119 | i2c_slave = of_find_i2c_device_by_node(np); | ||
120 | if (!i2c_slave || !i2c_get_clientdata(i2c_slave)) | ||
121 | return -EPROBE_DEFER; | ||
122 | |||
123 | hdmienc->dev = &i2c_slave->dev; | ||
124 | |||
125 | if (hdmienc->dev->driver == NULL) { | ||
126 | ret = -EPROBE_DEFER; | ||
127 | goto error; | ||
128 | } | ||
129 | |||
130 | /* Initialize the slave encoder. */ | ||
131 | driver = to_drm_i2c_encoder_driver(to_i2c_driver(hdmienc->dev->driver)); | ||
132 | ret = driver->encoder_init(i2c_slave, rcdu->ddev, &renc->slave); | ||
133 | if (ret < 0) | ||
134 | goto error; | ||
135 | |||
136 | ret = drm_encoder_init(rcdu->ddev, encoder, &encoder_funcs, | ||
137 | DRM_MODE_ENCODER_TMDS); | ||
138 | if (ret < 0) | ||
139 | goto error; | ||
140 | |||
141 | drm_encoder_helper_add(encoder, &encoder_helper_funcs); | ||
142 | |||
143 | renc->hdmi = hdmienc; | ||
144 | hdmienc->renc = renc; | ||
145 | |||
146 | return 0; | ||
147 | |||
148 | error: | ||
149 | put_device(hdmienc->dev); | ||
150 | return ret; | ||
151 | } | ||
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_hdmienc.h b/drivers/gpu/drm/rcar-du/rcar_du_hdmienc.h new file mode 100644 index 000000000000..2ff0128ac8e1 --- /dev/null +++ b/drivers/gpu/drm/rcar-du/rcar_du_hdmienc.h | |||
@@ -0,0 +1,35 @@ | |||
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 | |||
19 | struct device_node; | ||
20 | struct rcar_du_device; | ||
21 | struct rcar_du_encoder; | ||
22 | |||
23 | #if IS_ENABLED(CONFIG_DRM_RCAR_HDMI) | ||
24 | int rcar_du_hdmienc_init(struct rcar_du_device *rcdu, | ||
25 | struct rcar_du_encoder *renc, struct device_node *np); | ||
26 | #else | ||
27 | static 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_kms.c b/drivers/gpu/drm/rcar-du/rcar_du_kms.c index 543fa8bde616..0c5ee616b5a3 100644 --- a/drivers/gpu/drm/rcar-du/rcar_du_kms.c +++ b/drivers/gpu/drm/rcar-du/rcar_du_kms.c | |||
@@ -199,6 +199,7 @@ static int rcar_du_encoders_init_one(struct rcar_du_device *rcdu, | |||
199 | enum rcar_du_encoder_type type; | 199 | enum rcar_du_encoder_type type; |
200 | } encoders[] = { | 200 | } encoders[] = { |
201 | { "adi,adv7123", RCAR_DU_ENCODER_VGA }, | 201 | { "adi,adv7123", RCAR_DU_ENCODER_VGA }, |
202 | { "adi,adv7511w", RCAR_DU_ENCODER_HDMI }, | ||
202 | { "thine,thc63lvdm83d", RCAR_DU_ENCODER_LVDS }, | 203 | { "thine,thc63lvdm83d", RCAR_DU_ENCODER_LVDS }, |
203 | }; | 204 | }; |
204 | 205 | ||