1
0
Fork 0
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

340 lines
7.0 KiB

// SPDX-License-Identifier: GPL-2.0-or-later
/*
* Rockchip Connector Helper Function
*
* Copyright (C) 2021 Rockchip Electronics Co., Ltd
*/
#include <dm/device.h>
#include <dm/read.h>
#include <linux/compat.h>
#include <linux/list.h>
#include "rockchip_display.h"
#include "rockchip_crtc.h"
#include "rockchip_connector.h"
#include "rockchip_phy.h"
#ifdef CONFIG_SPL_BUILD
int rockchip_connector_bind(struct rockchip_connector *conn, struct udevice *dev, int id,
const struct rockchip_connector_funcs *funcs, void *data, int type)
{
conn->id = id;
conn->funcs = funcs;
conn->data = data;
conn->type = type;
return 0;
}
#else
static LIST_HEAD(rockchip_connector_list);
int rockchip_connector_bind(struct rockchip_connector *conn, struct udevice *dev, int id,
const struct rockchip_connector_funcs *funcs, void *data, int type)
{
conn->id = id;
conn->dev = dev;
conn->funcs = funcs;
conn->data = data;
conn->type = type;
list_add_tail(&conn->head, &rockchip_connector_list);
return 0;
}
struct rockchip_connector *get_rockchip_connector_by_device(struct udevice *dev)
{
struct rockchip_connector *conn;
list_for_each_entry(conn, &rockchip_connector_list, head) {
if (conn->dev == dev)
return conn;
}
return NULL;
}
int rockchip_connector_pre_init(struct display_state *state)
{
int ret = 0;
struct rockchip_connector *conn;
conn = state->conn_state.connector;
if (conn->funcs->pre_init) {
ret = conn->funcs->pre_init(conn, state);
if (ret)
return ret;
if (state->conn_state.secondary) {
conn = state->conn_state.connector;
ret = conn->funcs->pre_init(conn, state);
if (ret)
return ret;
}
}
return ret;
}
static int rockchip_connector_path_init(struct rockchip_connector *conn,
struct display_state *state)
{
int ret = 0;
if (conn->panel)
rockchip_panel_init(conn->panel, conn, state);
if (conn->bridge)
rockchip_bridge_init(conn->bridge, conn, state);
if (conn->funcs->init) {
ret = conn->funcs->init(conn, state);
if (ret)
return ret;
}
if (conn->phy)
rockchip_phy_init(conn->phy);
return ret;
}
int rockchip_connector_init(struct display_state *state)
{
int ret = 0;
struct rockchip_connector *conn;
conn = state->conn_state.connector;
ret = rockchip_connector_path_init(conn, state);
if (ret)
return ret;
if (state->conn_state.secondary) {
conn = state->conn_state.secondary;
ret = rockchip_connector_path_init(conn, state);
if (ret)
return ret;
}
return ret;
}
static bool rockchip_connector_path_detect(struct rockchip_connector *conn,
struct display_state *state)
{
int ret;
if (conn->funcs->detect) {
ret = conn->funcs->detect(conn, state);
if (!ret) {
printf("%s disconnected\n", conn->dev->name);
return false;
}
}
if (conn->bridge) {
ret = rockchip_bridge_detect(conn->bridge);
if (!ret) {
printf("%s disconnected\n",
dev_np(conn->bridge->dev)->full_name);
return false;
}
}
return true;
}
bool rockchip_connector_detect(struct display_state *state)
{
bool ret;
struct rockchip_connector *conn;
conn = state->conn_state.connector;
ret = rockchip_connector_path_detect(conn, state);
if (!ret)
return false;
if (state->conn_state.secondary) {
conn = state->conn_state.secondary;
ret = rockchip_connector_path_detect(conn, state);
if (!ret)
return false;
}
return true;
}
int rockchip_connector_get_timing(struct display_state *state)
{
int ret = 0;
struct rockchip_connector *conn;
conn = state->conn_state.connector;
if (conn->funcs->get_timing) {
ret = conn->funcs->get_timing(conn, state);
if (ret)
return ret;
if (state->conn_state.secondary) {
conn = state->conn_state.secondary;
ret = conn->funcs->get_timing(conn, state);
if (ret)
return ret;
}
}
return ret;
}
int rockchip_connector_get_edid(struct display_state *state)
{
int ret = 0;
struct rockchip_connector *conn;
conn = state->conn_state.connector;
if (conn->funcs->get_edid) {
ret = conn->funcs->get_edid(conn, state);
if (ret)
return ret;
if (state->conn_state.secondary) {
conn = state->conn_state.secondary;
ret = conn->funcs->get_edid(conn, state);
if (ret)
return ret;
}
}
return ret;
}
static int rockchip_connector_path_pre_enable(struct rockchip_connector *conn,
struct display_state *state)
{
if (conn->funcs->prepare)
conn->funcs->prepare(conn, state);
if (conn->bridge)
rockchip_bridge_pre_enable(conn->bridge);
if (conn->panel)
rockchip_panel_prepare(conn->panel);
return 0;
}
int rockchip_connector_pre_enable(struct display_state *state)
{
struct rockchip_connector *conn;
conn = state->conn_state.connector;
rockchip_connector_path_pre_enable(conn, state);
if (state->conn_state.secondary) {
conn = state->conn_state.secondary;
rockchip_connector_path_pre_enable(conn, state);
}
return 0;
}
static int rockchip_connector_path_enable(struct rockchip_connector *conn,
struct display_state *state)
{
if (conn->funcs->enable)
conn->funcs->enable(conn, state);
if (conn->bridge)
rockchip_bridge_enable(conn->bridge);
if (conn->panel)
rockchip_panel_enable(conn->panel);
return 0;
}
int rockchip_connector_enable(struct display_state *state)
{
struct rockchip_connector *conn;
conn = state->conn_state.connector;
rockchip_connector_path_enable(conn, state);
if (state->conn_state.secondary) {
conn = state->conn_state.secondary;
rockchip_connector_path_enable(conn, state);
}
return 0;
}
static int rockchip_connector_path_disable(struct rockchip_connector *conn,
struct display_state *state)
{
if (conn->panel)
rockchip_panel_disable(conn->panel);
if (conn->bridge)
rockchip_bridge_disable(conn->bridge);
if (conn->funcs->disable)
conn->funcs->disable(conn, state);
return 0;
}
int rockchip_connector_disable(struct display_state *state)
{
struct rockchip_connector *conn;
conn = state->conn_state.connector;
rockchip_connector_path_disable(conn, state);
if (state->conn_state.secondary) {
conn = state->conn_state.secondary;
rockchip_connector_path_disable(conn, state);
}
return 0;
}
static int rockchip_connector_path_post_disable(struct rockchip_connector *conn,
struct display_state *state)
{
if (conn->panel)
rockchip_panel_unprepare(conn->panel);
if (conn->bridge)
rockchip_bridge_post_disable(conn->bridge);
if (conn->funcs->unprepare)
conn->funcs->unprepare(conn, state);
return 0;
}
int rockchip_connector_post_disable(struct display_state *state)
{
struct rockchip_connector *conn;
conn = state->conn_state.connector;
rockchip_connector_path_post_disable(conn, state);
if (state->conn_state.secondary) {
conn = state->conn_state.secondary;
rockchip_connector_path_post_disable(conn, state);
}
return 0;
}
#endif
int rockchip_connector_deinit(struct display_state *state)
{
struct rockchip_connector *conn;
conn = state->conn_state.connector;
if (conn->funcs->deinit) {
conn->funcs->deinit(conn, state);
if (state->conn_state.secondary) {
conn = state->conn_state.secondary;
conn->funcs->deinit(conn, state);
}
}
return 0;
}