10594ce39SZhang Yubing // SPDX-License-Identifier: GPL-2.0-or-later
20594ce39SZhang Yubing /*
30594ce39SZhang Yubing * Rockchip Connector Helper Function
40594ce39SZhang Yubing *
50594ce39SZhang Yubing * Copyright (C) 2021 Rockchip Electronics Co., Ltd
60594ce39SZhang Yubing */
70594ce39SZhang Yubing
80594ce39SZhang Yubing #include <dm/device.h>
90594ce39SZhang Yubing #include <dm/read.h>
100594ce39SZhang Yubing #include <linux/compat.h>
110594ce39SZhang Yubing #include <linux/list.h>
120594ce39SZhang Yubing
130594ce39SZhang Yubing #include "rockchip_display.h"
140594ce39SZhang Yubing #include "rockchip_crtc.h"
150594ce39SZhang Yubing #include "rockchip_connector.h"
160594ce39SZhang Yubing #include "rockchip_phy.h"
170594ce39SZhang Yubing
18*690e9ed1SSandy Huang #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*690e9ed1SSandy Huang int rockchip_connector_bind(struct rockchip_connector *conn, struct udevice *dev, int id,
20*690e9ed1SSandy Huang const struct rockchip_connector_funcs *funcs, void *data, int type)
21*690e9ed1SSandy Huang {
22*690e9ed1SSandy Huang conn->id = id;
23*690e9ed1SSandy Huang conn->funcs = funcs;
24*690e9ed1SSandy Huang conn->data = data;
25*690e9ed1SSandy Huang conn->type = type;
26*690e9ed1SSandy Huang
27*690e9ed1SSandy Huang return 0;
28*690e9ed1SSandy Huang }
29*690e9ed1SSandy Huang
30*690e9ed1SSandy Huang #else
310594ce39SZhang Yubing static LIST_HEAD(rockchip_connector_list);
320594ce39SZhang Yubing
rockchip_connector_bind(struct rockchip_connector * conn,struct udevice * dev,int id,const struct rockchip_connector_funcs * funcs,void * data,int type)330594ce39SZhang Yubing int rockchip_connector_bind(struct rockchip_connector *conn, struct udevice *dev, int id,
340594ce39SZhang Yubing const struct rockchip_connector_funcs *funcs, void *data, int type)
350594ce39SZhang Yubing {
360594ce39SZhang Yubing conn->id = id;
370594ce39SZhang Yubing conn->dev = dev;
380594ce39SZhang Yubing conn->funcs = funcs;
390594ce39SZhang Yubing conn->data = data;
400594ce39SZhang Yubing conn->type = type;
410594ce39SZhang Yubing list_add_tail(&conn->head, &rockchip_connector_list);
420594ce39SZhang Yubing
430594ce39SZhang Yubing return 0;
440594ce39SZhang Yubing }
450594ce39SZhang Yubing
get_rockchip_connector_by_device(struct udevice * dev)460594ce39SZhang Yubing struct rockchip_connector *get_rockchip_connector_by_device(struct udevice *dev)
470594ce39SZhang Yubing {
480594ce39SZhang Yubing struct rockchip_connector *conn;
490594ce39SZhang Yubing
500594ce39SZhang Yubing list_for_each_entry(conn, &rockchip_connector_list, head) {
510594ce39SZhang Yubing if (conn->dev == dev)
520594ce39SZhang Yubing return conn;
530594ce39SZhang Yubing }
540594ce39SZhang Yubing
550594ce39SZhang Yubing return NULL;
560594ce39SZhang Yubing }
570594ce39SZhang Yubing
rockchip_connector_pre_init(struct display_state * state)580594ce39SZhang Yubing int rockchip_connector_pre_init(struct display_state *state)
590594ce39SZhang Yubing {
600594ce39SZhang Yubing int ret = 0;
610594ce39SZhang Yubing struct rockchip_connector *conn;
620594ce39SZhang Yubing
630594ce39SZhang Yubing conn = state->conn_state.connector;
640594ce39SZhang Yubing if (conn->funcs->pre_init) {
650594ce39SZhang Yubing ret = conn->funcs->pre_init(conn, state);
660594ce39SZhang Yubing if (ret)
670594ce39SZhang Yubing return ret;
680594ce39SZhang Yubing if (state->conn_state.secondary) {
690594ce39SZhang Yubing conn = state->conn_state.connector;
700594ce39SZhang Yubing ret = conn->funcs->pre_init(conn, state);
710594ce39SZhang Yubing if (ret)
720594ce39SZhang Yubing return ret;
730594ce39SZhang Yubing }
740594ce39SZhang Yubing }
750594ce39SZhang Yubing
760594ce39SZhang Yubing return ret;
770594ce39SZhang Yubing }
780594ce39SZhang Yubing
rockchip_connector_path_init(struct rockchip_connector * conn,struct display_state * state)790594ce39SZhang Yubing static int rockchip_connector_path_init(struct rockchip_connector *conn,
800594ce39SZhang Yubing struct display_state *state)
810594ce39SZhang Yubing {
820594ce39SZhang Yubing int ret = 0;
830594ce39SZhang Yubing
840594ce39SZhang Yubing if (conn->panel)
850594ce39SZhang Yubing rockchip_panel_init(conn->panel, conn, state);
860594ce39SZhang Yubing
870594ce39SZhang Yubing if (conn->bridge)
880594ce39SZhang Yubing rockchip_bridge_init(conn->bridge, conn, state);
890594ce39SZhang Yubing
900594ce39SZhang Yubing if (conn->funcs->init) {
910594ce39SZhang Yubing ret = conn->funcs->init(conn, state);
920594ce39SZhang Yubing if (ret)
930594ce39SZhang Yubing return ret;
940594ce39SZhang Yubing }
950594ce39SZhang Yubing
960594ce39SZhang Yubing if (conn->phy)
970594ce39SZhang Yubing rockchip_phy_init(conn->phy);
980594ce39SZhang Yubing
990594ce39SZhang Yubing return ret;
1000594ce39SZhang Yubing }
1010594ce39SZhang Yubing
rockchip_connector_init(struct display_state * state)1020594ce39SZhang Yubing int rockchip_connector_init(struct display_state *state)
1030594ce39SZhang Yubing {
1040594ce39SZhang Yubing int ret = 0;
1050594ce39SZhang Yubing struct rockchip_connector *conn;
1060594ce39SZhang Yubing
1070594ce39SZhang Yubing conn = state->conn_state.connector;
1080594ce39SZhang Yubing ret = rockchip_connector_path_init(conn, state);
1090594ce39SZhang Yubing if (ret)
1100594ce39SZhang Yubing return ret;
1110594ce39SZhang Yubing if (state->conn_state.secondary) {
1120594ce39SZhang Yubing conn = state->conn_state.secondary;
1130594ce39SZhang Yubing ret = rockchip_connector_path_init(conn, state);
1140594ce39SZhang Yubing if (ret)
1150594ce39SZhang Yubing return ret;
1160594ce39SZhang Yubing }
1170594ce39SZhang Yubing
1180594ce39SZhang Yubing return ret;
1190594ce39SZhang Yubing }
1200594ce39SZhang Yubing
1210594ce39SZhang Yubing
rockchip_connector_path_detect(struct rockchip_connector * conn,struct display_state * state)1220594ce39SZhang Yubing static bool rockchip_connector_path_detect(struct rockchip_connector *conn,
1230594ce39SZhang Yubing struct display_state *state)
1240594ce39SZhang Yubing {
1250594ce39SZhang Yubing int ret;
1260594ce39SZhang Yubing
1270594ce39SZhang Yubing if (conn->funcs->detect) {
1280594ce39SZhang Yubing ret = conn->funcs->detect(conn, state);
1290594ce39SZhang Yubing if (!ret) {
1300594ce39SZhang Yubing printf("%s disconnected\n", conn->dev->name);
1310594ce39SZhang Yubing return false;
1320594ce39SZhang Yubing }
1330594ce39SZhang Yubing }
1340594ce39SZhang Yubing
1350594ce39SZhang Yubing if (conn->bridge) {
1360594ce39SZhang Yubing ret = rockchip_bridge_detect(conn->bridge);
1370594ce39SZhang Yubing if (!ret) {
1380594ce39SZhang Yubing printf("%s disconnected\n",
1390594ce39SZhang Yubing dev_np(conn->bridge->dev)->full_name);
1400594ce39SZhang Yubing return false;
1410594ce39SZhang Yubing }
1420594ce39SZhang Yubing }
1430594ce39SZhang Yubing
1440594ce39SZhang Yubing return true;
1450594ce39SZhang Yubing }
1460594ce39SZhang Yubing
rockchip_connector_detect(struct display_state * state)1470594ce39SZhang Yubing bool rockchip_connector_detect(struct display_state *state)
1480594ce39SZhang Yubing {
1490594ce39SZhang Yubing bool ret;
1500594ce39SZhang Yubing struct rockchip_connector *conn;
1510594ce39SZhang Yubing
1520594ce39SZhang Yubing conn = state->conn_state.connector;
1530594ce39SZhang Yubing ret = rockchip_connector_path_detect(conn, state);
1540594ce39SZhang Yubing if (!ret)
1550594ce39SZhang Yubing return false;
1560594ce39SZhang Yubing if (state->conn_state.secondary) {
1570594ce39SZhang Yubing conn = state->conn_state.secondary;
1580594ce39SZhang Yubing ret = rockchip_connector_path_detect(conn, state);
1590594ce39SZhang Yubing if (!ret)
1600594ce39SZhang Yubing return false;
1610594ce39SZhang Yubing }
1620594ce39SZhang Yubing
1630594ce39SZhang Yubing return true;
1640594ce39SZhang Yubing }
1650594ce39SZhang Yubing
rockchip_connector_get_timing(struct display_state * state)1660594ce39SZhang Yubing int rockchip_connector_get_timing(struct display_state *state)
1670594ce39SZhang Yubing {
1680594ce39SZhang Yubing int ret = 0;
1690594ce39SZhang Yubing struct rockchip_connector *conn;
1700594ce39SZhang Yubing
1710594ce39SZhang Yubing conn = state->conn_state.connector;
1720594ce39SZhang Yubing if (conn->funcs->get_timing) {
1730594ce39SZhang Yubing ret = conn->funcs->get_timing(conn, state);
1740594ce39SZhang Yubing if (ret)
1750594ce39SZhang Yubing return ret;
1760594ce39SZhang Yubing if (state->conn_state.secondary) {
1770594ce39SZhang Yubing conn = state->conn_state.secondary;
1780594ce39SZhang Yubing ret = conn->funcs->get_timing(conn, state);
1790594ce39SZhang Yubing if (ret)
1800594ce39SZhang Yubing return ret;
1810594ce39SZhang Yubing }
1820594ce39SZhang Yubing }
1830594ce39SZhang Yubing
1840594ce39SZhang Yubing return ret;
1850594ce39SZhang Yubing }
1860594ce39SZhang Yubing
rockchip_connector_get_edid(struct display_state * state)1870594ce39SZhang Yubing int rockchip_connector_get_edid(struct display_state *state)
1880594ce39SZhang Yubing {
1890594ce39SZhang Yubing int ret = 0;
1900594ce39SZhang Yubing struct rockchip_connector *conn;
1910594ce39SZhang Yubing
1920594ce39SZhang Yubing conn = state->conn_state.connector;
1930594ce39SZhang Yubing if (conn->funcs->get_edid) {
1940594ce39SZhang Yubing ret = conn->funcs->get_edid(conn, state);
1950594ce39SZhang Yubing if (ret)
1960594ce39SZhang Yubing return ret;
1970594ce39SZhang Yubing if (state->conn_state.secondary) {
1980594ce39SZhang Yubing conn = state->conn_state.secondary;
1990594ce39SZhang Yubing ret = conn->funcs->get_edid(conn, state);
2000594ce39SZhang Yubing if (ret)
2010594ce39SZhang Yubing return ret;
2020594ce39SZhang Yubing }
2030594ce39SZhang Yubing }
2040594ce39SZhang Yubing
2050594ce39SZhang Yubing return ret;
2060594ce39SZhang Yubing }
2070594ce39SZhang Yubing
rockchip_connector_path_pre_enable(struct rockchip_connector * conn,struct display_state * state)2080594ce39SZhang Yubing static int rockchip_connector_path_pre_enable(struct rockchip_connector *conn,
2090594ce39SZhang Yubing struct display_state *state)
2100594ce39SZhang Yubing {
2110594ce39SZhang Yubing if (conn->funcs->prepare)
2120594ce39SZhang Yubing conn->funcs->prepare(conn, state);
2130594ce39SZhang Yubing
2140594ce39SZhang Yubing if (conn->bridge)
2150594ce39SZhang Yubing rockchip_bridge_pre_enable(conn->bridge);
2160594ce39SZhang Yubing
2170594ce39SZhang Yubing if (conn->panel)
2180594ce39SZhang Yubing rockchip_panel_prepare(conn->panel);
2190594ce39SZhang Yubing
2200594ce39SZhang Yubing return 0;
2210594ce39SZhang Yubing }
2220594ce39SZhang Yubing
rockchip_connector_pre_enable(struct display_state * state)2230594ce39SZhang Yubing int rockchip_connector_pre_enable(struct display_state *state)
2240594ce39SZhang Yubing {
2250594ce39SZhang Yubing struct rockchip_connector *conn;
2260594ce39SZhang Yubing
2270594ce39SZhang Yubing conn = state->conn_state.connector;
2280594ce39SZhang Yubing rockchip_connector_path_pre_enable(conn, state);
2290594ce39SZhang Yubing if (state->conn_state.secondary) {
2300594ce39SZhang Yubing conn = state->conn_state.secondary;
2310594ce39SZhang Yubing rockchip_connector_path_pre_enable(conn, state);
2320594ce39SZhang Yubing }
2330594ce39SZhang Yubing
2340594ce39SZhang Yubing return 0;
2350594ce39SZhang Yubing }
2360594ce39SZhang Yubing
rockchip_connector_path_enable(struct rockchip_connector * conn,struct display_state * state)2370594ce39SZhang Yubing static int rockchip_connector_path_enable(struct rockchip_connector *conn,
2380594ce39SZhang Yubing struct display_state *state)
2390594ce39SZhang Yubing {
2400594ce39SZhang Yubing if (conn->funcs->enable)
2410594ce39SZhang Yubing conn->funcs->enable(conn, state);
2420594ce39SZhang Yubing
2430594ce39SZhang Yubing if (conn->bridge)
2440594ce39SZhang Yubing rockchip_bridge_enable(conn->bridge);
2450594ce39SZhang Yubing
2460594ce39SZhang Yubing if (conn->panel)
2470594ce39SZhang Yubing rockchip_panel_enable(conn->panel);
2480594ce39SZhang Yubing
2490594ce39SZhang Yubing return 0;
2500594ce39SZhang Yubing }
2510594ce39SZhang Yubing
rockchip_connector_enable(struct display_state * state)2520594ce39SZhang Yubing int rockchip_connector_enable(struct display_state *state)
2530594ce39SZhang Yubing {
2540594ce39SZhang Yubing struct rockchip_connector *conn;
2550594ce39SZhang Yubing
2560594ce39SZhang Yubing conn = state->conn_state.connector;
2570594ce39SZhang Yubing rockchip_connector_path_enable(conn, state);
2580594ce39SZhang Yubing if (state->conn_state.secondary) {
2590594ce39SZhang Yubing conn = state->conn_state.secondary;
2600594ce39SZhang Yubing rockchip_connector_path_enable(conn, state);
2610594ce39SZhang Yubing }
2620594ce39SZhang Yubing
2630594ce39SZhang Yubing return 0;
2640594ce39SZhang Yubing }
2650594ce39SZhang Yubing
rockchip_connector_path_disable(struct rockchip_connector * conn,struct display_state * state)2660594ce39SZhang Yubing static int rockchip_connector_path_disable(struct rockchip_connector *conn,
2670594ce39SZhang Yubing struct display_state *state)
2680594ce39SZhang Yubing {
2690594ce39SZhang Yubing if (conn->panel)
2700594ce39SZhang Yubing rockchip_panel_disable(conn->panel);
2710594ce39SZhang Yubing
2720594ce39SZhang Yubing if (conn->bridge)
2730594ce39SZhang Yubing rockchip_bridge_disable(conn->bridge);
2740594ce39SZhang Yubing
2750594ce39SZhang Yubing if (conn->funcs->disable)
2760594ce39SZhang Yubing conn->funcs->disable(conn, state);
2770594ce39SZhang Yubing
2780594ce39SZhang Yubing return 0;
2790594ce39SZhang Yubing }
2800594ce39SZhang Yubing
rockchip_connector_disable(struct display_state * state)2810594ce39SZhang Yubing int rockchip_connector_disable(struct display_state *state)
2820594ce39SZhang Yubing {
2830594ce39SZhang Yubing struct rockchip_connector *conn;
2840594ce39SZhang Yubing
2850594ce39SZhang Yubing conn = state->conn_state.connector;
2860594ce39SZhang Yubing rockchip_connector_path_disable(conn, state);
2870594ce39SZhang Yubing if (state->conn_state.secondary) {
2880594ce39SZhang Yubing conn = state->conn_state.secondary;
2890594ce39SZhang Yubing rockchip_connector_path_disable(conn, state);
2900594ce39SZhang Yubing }
2910594ce39SZhang Yubing
2920594ce39SZhang Yubing return 0;
2930594ce39SZhang Yubing }
2940594ce39SZhang Yubing
rockchip_connector_path_post_disable(struct rockchip_connector * conn,struct display_state * state)2950594ce39SZhang Yubing static int rockchip_connector_path_post_disable(struct rockchip_connector *conn,
2960594ce39SZhang Yubing struct display_state *state)
2970594ce39SZhang Yubing {
2980594ce39SZhang Yubing if (conn->panel)
2990594ce39SZhang Yubing rockchip_panel_unprepare(conn->panel);
3000594ce39SZhang Yubing
3010594ce39SZhang Yubing if (conn->bridge)
3020594ce39SZhang Yubing rockchip_bridge_post_disable(conn->bridge);
3030594ce39SZhang Yubing
3040594ce39SZhang Yubing if (conn->funcs->unprepare)
3050594ce39SZhang Yubing conn->funcs->unprepare(conn, state);
3060594ce39SZhang Yubing
3070594ce39SZhang Yubing return 0;
3080594ce39SZhang Yubing }
3090594ce39SZhang Yubing
rockchip_connector_post_disable(struct display_state * state)3100594ce39SZhang Yubing int rockchip_connector_post_disable(struct display_state *state)
3110594ce39SZhang Yubing {
3120594ce39SZhang Yubing struct rockchip_connector *conn;
3130594ce39SZhang Yubing
3140594ce39SZhang Yubing conn = state->conn_state.connector;
3150594ce39SZhang Yubing rockchip_connector_path_post_disable(conn, state);
3160594ce39SZhang Yubing if (state->conn_state.secondary) {
3170594ce39SZhang Yubing conn = state->conn_state.secondary;
3180594ce39SZhang Yubing rockchip_connector_path_post_disable(conn, state);
3190594ce39SZhang Yubing }
3200594ce39SZhang Yubing
3210594ce39SZhang Yubing return 0;
3220594ce39SZhang Yubing }
323*690e9ed1SSandy Huang #endif
324*690e9ed1SSandy Huang
rockchip_connector_deinit(struct display_state * state)325*690e9ed1SSandy Huang int rockchip_connector_deinit(struct display_state *state)
326*690e9ed1SSandy Huang {
327*690e9ed1SSandy Huang struct rockchip_connector *conn;
328*690e9ed1SSandy Huang
329*690e9ed1SSandy Huang conn = state->conn_state.connector;
330*690e9ed1SSandy Huang if (conn->funcs->deinit) {
331*690e9ed1SSandy Huang conn->funcs->deinit(conn, state);
332*690e9ed1SSandy Huang if (state->conn_state.secondary) {
333*690e9ed1SSandy Huang conn = state->conn_state.secondary;
334*690e9ed1SSandy Huang conn->funcs->deinit(conn, state);
335*690e9ed1SSandy Huang }
336*690e9ed1SSandy Huang }
337*690e9ed1SSandy Huang
338*690e9ed1SSandy Huang return 0;
339*690e9ed1SSandy Huang }
340