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