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