forked from ~ljy/RK356X_SDK_RELEASE

hc
2023-12-09 95099d4622f8cb224d94e314c7a8e0df60b13f87
kernel/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_output.c
....@@ -1,3 +1,4 @@
1
+// SPDX-License-Identifier: GPL-2.0-only
12 /*
23 * Copyright (C) 2014 Traphandler
34 * Copyright (C) 2014 Free Electrons
....@@ -5,64 +6,111 @@
56 *
67 * Author: Jean-Jacques Hiblot <jjhiblot@traphandler.com>
78 * Author: Boris BREZILLON <boris.brezillon@free-electrons.com>
8
- *
9
- * This program is free software; you can redistribute it and/or modify it
10
- * under the terms of the GNU General Public License version 2 as published by
11
- * the Free Software Foundation.
12
- *
13
- * This program is distributed in the hope that it will be useful, but WITHOUT
14
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
15
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
16
- * more details.
17
- *
18
- * You should have received a copy of the GNU General Public License along with
19
- * this program. If not, see <http://www.gnu.org/licenses/>.
209 */
2110
11
+#include <linux/media-bus-format.h>
2212 #include <linux/of_graph.h>
2313
24
-#include <drm/drmP.h>
25
-#include <drm/drm_of.h>
2614 #include <drm/drm_bridge.h>
15
+#include <drm/drm_encoder.h>
16
+#include <drm/drm_of.h>
17
+#include <drm/drm_simple_kms_helper.h>
2718
2819 #include "atmel_hlcdc_dc.h"
2920
30
-static const struct drm_encoder_funcs atmel_hlcdc_panel_encoder_funcs = {
31
- .destroy = drm_encoder_cleanup,
21
+struct atmel_hlcdc_rgb_output {
22
+ struct drm_encoder encoder;
23
+ int bus_fmt;
3224 };
25
+
26
+static struct atmel_hlcdc_rgb_output *
27
+atmel_hlcdc_encoder_to_rgb_output(struct drm_encoder *encoder)
28
+{
29
+ return container_of(encoder, struct atmel_hlcdc_rgb_output, encoder);
30
+}
31
+
32
+int atmel_hlcdc_encoder_get_bus_fmt(struct drm_encoder *encoder)
33
+{
34
+ struct atmel_hlcdc_rgb_output *output;
35
+
36
+ output = atmel_hlcdc_encoder_to_rgb_output(encoder);
37
+
38
+ return output->bus_fmt;
39
+}
40
+
41
+static int atmel_hlcdc_of_bus_fmt(const struct device_node *ep)
42
+{
43
+ u32 bus_width;
44
+ int ret;
45
+
46
+ ret = of_property_read_u32(ep, "bus-width", &bus_width);
47
+ if (ret == -EINVAL)
48
+ return 0;
49
+ if (ret)
50
+ return ret;
51
+
52
+ switch (bus_width) {
53
+ case 12:
54
+ return MEDIA_BUS_FMT_RGB444_1X12;
55
+ case 16:
56
+ return MEDIA_BUS_FMT_RGB565_1X16;
57
+ case 18:
58
+ return MEDIA_BUS_FMT_RGB666_1X18;
59
+ case 24:
60
+ return MEDIA_BUS_FMT_RGB888_1X24;
61
+ default:
62
+ return -EINVAL;
63
+ }
64
+}
3365
3466 static int atmel_hlcdc_attach_endpoint(struct drm_device *dev, int endpoint)
3567 {
36
- struct drm_encoder *encoder;
68
+ struct atmel_hlcdc_rgb_output *output;
69
+ struct device_node *ep;
3770 struct drm_panel *panel;
3871 struct drm_bridge *bridge;
3972 int ret;
4073
74
+ ep = of_graph_get_endpoint_by_regs(dev->dev->of_node, 0, endpoint);
75
+ if (!ep)
76
+ return -ENODEV;
77
+
4178 ret = drm_of_find_panel_or_bridge(dev->dev->of_node, 0, endpoint,
4279 &panel, &bridge);
43
- if (ret)
80
+ if (ret) {
81
+ of_node_put(ep);
4482 return ret;
83
+ }
4584
46
- encoder = devm_kzalloc(dev->dev, sizeof(*encoder), GFP_KERNEL);
47
- if (!encoder)
85
+ output = devm_kzalloc(dev->dev, sizeof(*output), GFP_KERNEL);
86
+ if (!output) {
87
+ of_node_put(ep);
88
+ return -ENOMEM;
89
+ }
90
+
91
+ output->bus_fmt = atmel_hlcdc_of_bus_fmt(ep);
92
+ of_node_put(ep);
93
+ if (output->bus_fmt < 0) {
94
+ dev_err(dev->dev, "endpoint %d: invalid bus width\n", endpoint);
4895 return -EINVAL;
96
+ }
4997
50
- ret = drm_encoder_init(dev, encoder,
51
- &atmel_hlcdc_panel_encoder_funcs,
52
- DRM_MODE_ENCODER_NONE, NULL);
98
+ ret = drm_simple_encoder_init(dev, &output->encoder,
99
+ DRM_MODE_ENCODER_NONE);
53100 if (ret)
54101 return ret;
55102
56
- encoder->possible_crtcs = 0x1;
103
+ output->encoder.possible_crtcs = 0x1;
57104
58105 if (panel) {
59
- bridge = drm_panel_bridge_add(panel, DRM_MODE_CONNECTOR_Unknown);
106
+ bridge = drm_panel_bridge_add_typed(panel,
107
+ DRM_MODE_CONNECTOR_Unknown);
60108 if (IS_ERR(bridge))
61109 return PTR_ERR(bridge);
62110 }
63111
64112 if (bridge) {
65
- ret = drm_bridge_attach(encoder, bridge, NULL);
113
+ ret = drm_bridge_attach(&output->encoder, bridge, NULL, 0);
66114 if (!ret)
67115 return 0;
68116
....@@ -70,7 +118,7 @@
70118 drm_panel_bridge_remove(bridge);
71119 }
72120
73
- drm_encoder_cleanup(encoder);
121
+ drm_encoder_cleanup(&output->encoder);
74122
75123 return ret;
76124 }
....@@ -78,12 +126,23 @@
78126 int atmel_hlcdc_create_outputs(struct drm_device *dev)
79127 {
80128 int endpoint, ret = 0;
129
+ int attached = 0;
81130
82
- for (endpoint = 0; !ret; endpoint++)
131
+ /*
132
+ * Always scan the first few endpoints even if we get -ENODEV,
133
+ * but keep going after that as long as we keep getting hits.
134
+ */
135
+ for (endpoint = 0; !ret || endpoint < 4; endpoint++) {
83136 ret = atmel_hlcdc_attach_endpoint(dev, endpoint);
137
+ if (ret == -ENODEV)
138
+ continue;
139
+ if (ret)
140
+ break;
141
+ attached++;
142
+ }
84143
85144 /* At least one device was successfully attached.*/
86
- if (ret == -ENODEV && endpoint)
145
+ if (ret == -ENODEV && attached)
87146 return 0;
88147
89148 return ret;