xref: /OK3568_Linux_fs/u-boot/drivers/video/drm/rockchip_connector.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
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