1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3 * Rockchip Connector Helper Function
4 *
5 * Copyright (C) 2021 Rockchip Electronics Co., Ltd
6 */
7
8 #include <dm/device.h>
9 #include <dm/read.h>
10 #include <linux/compat.h>
11 #include <linux/list.h>
12
13 #include "rockchip_display.h"
14 #include "rockchip_crtc.h"
15 #include "rockchip_connector.h"
16 #include "rockchip_phy.h"
17
18 #ifdef CONFIG_SPL_BUILD
rockchip_connector_bind(struct rockchip_connector * conn,struct udevice * dev,int id,const struct rockchip_connector_funcs * funcs,void * data,int type)19 int rockchip_connector_bind(struct rockchip_connector *conn, struct udevice *dev, int id,
20 const struct rockchip_connector_funcs *funcs, void *data, int type)
21 {
22 conn->id = id;
23 conn->funcs = funcs;
24 conn->data = data;
25 conn->type = type;
26
27 return 0;
28 }
29
30 #else
31 static LIST_HEAD(rockchip_connector_list);
32
rockchip_connector_bind(struct rockchip_connector * conn,struct udevice * dev,int id,const struct rockchip_connector_funcs * funcs,void * data,int type)33 int rockchip_connector_bind(struct rockchip_connector *conn, struct udevice *dev, int id,
34 const struct rockchip_connector_funcs *funcs, void *data, int type)
35 {
36 conn->id = id;
37 conn->dev = dev;
38 conn->funcs = funcs;
39 conn->data = data;
40 conn->type = type;
41 list_add_tail(&conn->head, &rockchip_connector_list);
42
43 return 0;
44 }
45
get_rockchip_connector_by_device(struct udevice * dev)46 struct rockchip_connector *get_rockchip_connector_by_device(struct udevice *dev)
47 {
48 struct rockchip_connector *conn;
49
50 list_for_each_entry(conn, &rockchip_connector_list, head) {
51 if (conn->dev == dev)
52 return conn;
53 }
54
55 return NULL;
56 }
57
rockchip_connector_pre_init(struct display_state * state)58 int rockchip_connector_pre_init(struct display_state *state)
59 {
60 int ret = 0;
61 struct rockchip_connector *conn;
62
63 conn = state->conn_state.connector;
64 if (conn->funcs->pre_init) {
65 ret = conn->funcs->pre_init(conn, state);
66 if (ret)
67 return ret;
68 if (state->conn_state.secondary) {
69 conn = state->conn_state.connector;
70 ret = conn->funcs->pre_init(conn, state);
71 if (ret)
72 return ret;
73 }
74 }
75
76 return ret;
77 }
78
rockchip_connector_path_init(struct rockchip_connector * conn,struct display_state * state)79 static int rockchip_connector_path_init(struct rockchip_connector *conn,
80 struct display_state *state)
81 {
82 int ret = 0;
83
84 if (conn->panel)
85 rockchip_panel_init(conn->panel, conn, state);
86
87 if (conn->bridge)
88 rockchip_bridge_init(conn->bridge, conn, state);
89
90 if (conn->funcs->init) {
91 ret = conn->funcs->init(conn, state);
92 if (ret)
93 return ret;
94 }
95
96 if (conn->phy)
97 rockchip_phy_init(conn->phy);
98
99 return ret;
100 }
101
rockchip_connector_init(struct display_state * state)102 int rockchip_connector_init(struct display_state *state)
103 {
104 int ret = 0;
105 struct rockchip_connector *conn;
106
107 conn = state->conn_state.connector;
108 ret = rockchip_connector_path_init(conn, state);
109 if (ret)
110 return ret;
111 if (state->conn_state.secondary) {
112 conn = state->conn_state.secondary;
113 ret = rockchip_connector_path_init(conn, state);
114 if (ret)
115 return ret;
116 }
117
118 return ret;
119 }
120
121
rockchip_connector_path_detect(struct rockchip_connector * conn,struct display_state * state)122 static bool rockchip_connector_path_detect(struct rockchip_connector *conn,
123 struct display_state *state)
124 {
125 int ret;
126
127 if (conn->funcs->detect) {
128 ret = conn->funcs->detect(conn, state);
129 if (!ret) {
130 printf("%s disconnected\n", conn->dev->name);
131 return false;
132 }
133 }
134
135 if (conn->bridge) {
136 ret = rockchip_bridge_detect(conn->bridge);
137 if (!ret) {
138 printf("%s disconnected\n",
139 dev_np(conn->bridge->dev)->full_name);
140 return false;
141 }
142 }
143
144 return true;
145 }
146
rockchip_connector_detect(struct display_state * state)147 bool rockchip_connector_detect(struct display_state *state)
148 {
149 bool ret;
150 struct rockchip_connector *conn;
151
152 conn = state->conn_state.connector;
153 ret = rockchip_connector_path_detect(conn, state);
154 if (!ret)
155 return false;
156 if (state->conn_state.secondary) {
157 conn = state->conn_state.secondary;
158 ret = rockchip_connector_path_detect(conn, state);
159 if (!ret)
160 return false;
161 }
162
163 return true;
164 }
165
rockchip_connector_get_timing(struct display_state * state)166 int rockchip_connector_get_timing(struct display_state *state)
167 {
168 int ret = 0;
169 struct rockchip_connector *conn;
170
171 conn = state->conn_state.connector;
172 if (conn->funcs->get_timing) {
173 ret = conn->funcs->get_timing(conn, state);
174 if (ret)
175 return ret;
176 if (state->conn_state.secondary) {
177 conn = state->conn_state.secondary;
178 ret = conn->funcs->get_timing(conn, state);
179 if (ret)
180 return ret;
181 }
182 }
183
184 return ret;
185 }
186
rockchip_connector_get_edid(struct display_state * state)187 int rockchip_connector_get_edid(struct display_state *state)
188 {
189 int ret = 0;
190 struct rockchip_connector *conn;
191
192 conn = state->conn_state.connector;
193 if (conn->funcs->get_edid) {
194 ret = conn->funcs->get_edid(conn, state);
195 if (ret)
196 return ret;
197 if (state->conn_state.secondary) {
198 conn = state->conn_state.secondary;
199 ret = conn->funcs->get_edid(conn, state);
200 if (ret)
201 return ret;
202 }
203 }
204
205 return ret;
206 }
207
rockchip_connector_path_pre_enable(struct rockchip_connector * conn,struct display_state * state)208 static int rockchip_connector_path_pre_enable(struct rockchip_connector *conn,
209 struct display_state *state)
210 {
211 if (conn->funcs->prepare)
212 conn->funcs->prepare(conn, state);
213
214 if (conn->bridge)
215 rockchip_bridge_pre_enable(conn->bridge);
216
217 if (conn->panel)
218 rockchip_panel_prepare(conn->panel);
219
220 return 0;
221 }
222
rockchip_connector_pre_enable(struct display_state * state)223 int rockchip_connector_pre_enable(struct display_state *state)
224 {
225 struct rockchip_connector *conn;
226
227 conn = state->conn_state.connector;
228 rockchip_connector_path_pre_enable(conn, state);
229 if (state->conn_state.secondary) {
230 conn = state->conn_state.secondary;
231 rockchip_connector_path_pre_enable(conn, state);
232 }
233
234 return 0;
235 }
236
rockchip_connector_path_enable(struct rockchip_connector * conn,struct display_state * state)237 static int rockchip_connector_path_enable(struct rockchip_connector *conn,
238 struct display_state *state)
239 {
240 if (conn->funcs->enable)
241 conn->funcs->enable(conn, state);
242
243 if (conn->bridge)
244 rockchip_bridge_enable(conn->bridge);
245
246 if (conn->panel)
247 rockchip_panel_enable(conn->panel);
248
249 return 0;
250 }
251
rockchip_connector_enable(struct display_state * state)252 int rockchip_connector_enable(struct display_state *state)
253 {
254 struct rockchip_connector *conn;
255
256 conn = state->conn_state.connector;
257 rockchip_connector_path_enable(conn, state);
258 if (state->conn_state.secondary) {
259 conn = state->conn_state.secondary;
260 rockchip_connector_path_enable(conn, state);
261 }
262
263 return 0;
264 }
265
rockchip_connector_path_disable(struct rockchip_connector * conn,struct display_state * state)266 static int rockchip_connector_path_disable(struct rockchip_connector *conn,
267 struct display_state *state)
268 {
269 if (conn->panel)
270 rockchip_panel_disable(conn->panel);
271
272 if (conn->bridge)
273 rockchip_bridge_disable(conn->bridge);
274
275 if (conn->funcs->disable)
276 conn->funcs->disable(conn, state);
277
278 return 0;
279 }
280
rockchip_connector_disable(struct display_state * state)281 int rockchip_connector_disable(struct display_state *state)
282 {
283 struct rockchip_connector *conn;
284
285 conn = state->conn_state.connector;
286 rockchip_connector_path_disable(conn, state);
287 if (state->conn_state.secondary) {
288 conn = state->conn_state.secondary;
289 rockchip_connector_path_disable(conn, state);
290 }
291
292 return 0;
293 }
294
rockchip_connector_path_post_disable(struct rockchip_connector * conn,struct display_state * state)295 static int rockchip_connector_path_post_disable(struct rockchip_connector *conn,
296 struct display_state *state)
297 {
298 if (conn->panel)
299 rockchip_panel_unprepare(conn->panel);
300
301 if (conn->bridge)
302 rockchip_bridge_post_disable(conn->bridge);
303
304 if (conn->funcs->unprepare)
305 conn->funcs->unprepare(conn, state);
306
307 return 0;
308 }
309
rockchip_connector_post_disable(struct display_state * state)310 int rockchip_connector_post_disable(struct display_state *state)
311 {
312 struct rockchip_connector *conn;
313
314 conn = state->conn_state.connector;
315 rockchip_connector_path_post_disable(conn, state);
316 if (state->conn_state.secondary) {
317 conn = state->conn_state.secondary;
318 rockchip_connector_path_post_disable(conn, state);
319 }
320
321 return 0;
322 }
323 #endif
324
rockchip_connector_deinit(struct display_state * state)325 int rockchip_connector_deinit(struct display_state *state)
326 {
327 struct rockchip_connector *conn;
328
329 conn = state->conn_state.connector;
330 if (conn->funcs->deinit) {
331 conn->funcs->deinit(conn, state);
332 if (state->conn_state.secondary) {
333 conn = state->conn_state.secondary;
334 conn->funcs->deinit(conn, state);
335 }
336 }
337
338 return 0;
339 }
340