video/drm: Add rockchip bridge framework
The current implementation assumes that the only possible peripheral device is a panel. Using an output bridge device should also be possible. Such sequence is required by Rockchip RK618 bridge, which is a RGB peripheral bridge device. Change-Id: I3e4e5e9e23c8ed7c74ed1276946b7b54f4cd5ee8 Signed-off-by: Wyon Bi <bivvy.bi@rock-chips.com>
This commit is contained in:
parent
152682ed57
commit
1a8d717c29
|
|
@ -1,6 +1,7 @@
|
||||||
menuconfig DRM_ROCKCHIP
|
menuconfig DRM_ROCKCHIP
|
||||||
bool "Rockchip DRM Support"
|
bool "Rockchip DRM Support"
|
||||||
depends on DM_VIDEO && OF_LIVE
|
depends on DM_VIDEO && OF_LIVE
|
||||||
|
select VIDEO_BRIDGE
|
||||||
help
|
help
|
||||||
Rockchip SoCs provide video output capabilities for High-Definition
|
Rockchip SoCs provide video output capabilities for High-Definition
|
||||||
Multimedia Interface (HDMI), Low-voltage Differential Signalling
|
Multimedia Interface (HDMI), Low-voltage Differential Signalling
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@
|
||||||
# SPDX-License-Identifier: GPL-2.0+
|
# SPDX-License-Identifier: GPL-2.0+
|
||||||
#
|
#
|
||||||
|
|
||||||
obj-y += rockchip_display.o rockchip_crtc.o rockchip_phy.o \
|
obj-y += rockchip_display.o rockchip_crtc.o rockchip_phy.o rockchip_bridge.o \
|
||||||
rockchip_vop.o rockchip_vop_reg.o bmp_helper.o
|
rockchip_vop.o rockchip_vop_reg.o bmp_helper.o
|
||||||
|
|
||||||
obj-$(CONFIG_DRM_ROCKCHIP_MIPI_DSI) += rockchip_mipi_dsi.o
|
obj-$(CONFIG_DRM_ROCKCHIP_MIPI_DSI) += rockchip_mipi_dsi.o
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,42 @@
|
||||||
|
// SPDX-License-Identifier: GPL-2.0+
|
||||||
|
/*
|
||||||
|
* (C) Copyright 2008-2018 Fuzhou Rockchip Electronics Co., Ltd
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "rockchip_bridge.h"
|
||||||
|
|
||||||
|
void rockchip_bridge_pre_enable(struct rockchip_bridge *bridge)
|
||||||
|
{
|
||||||
|
if (!bridge)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (bridge->funcs && bridge->funcs->pre_enable)
|
||||||
|
bridge->funcs->pre_enable(bridge);
|
||||||
|
}
|
||||||
|
|
||||||
|
void rockchip_bridge_post_disable(struct rockchip_bridge *bridge)
|
||||||
|
{
|
||||||
|
if (!bridge)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (bridge->funcs && bridge->funcs->post_disable)
|
||||||
|
bridge->funcs->post_disable(bridge);
|
||||||
|
}
|
||||||
|
|
||||||
|
void rockchip_bridge_enable(struct rockchip_bridge *bridge)
|
||||||
|
{
|
||||||
|
if (!bridge)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (bridge->funcs && bridge->funcs->enable)
|
||||||
|
bridge->funcs->enable(bridge);
|
||||||
|
}
|
||||||
|
|
||||||
|
void rockchip_bridge_disable(struct rockchip_bridge *bridge)
|
||||||
|
{
|
||||||
|
if (!bridge)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (bridge->funcs && bridge->funcs->disable)
|
||||||
|
bridge->funcs->disable(bridge);
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,36 @@
|
||||||
|
/* SPDX-License-Identifier: GPL-2.0+ */
|
||||||
|
/*
|
||||||
|
* (C) Copyright 2008-2018 Fuzhou Rockchip Electronics Co., Ltd
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _ROCKCHIP_BRIDGE_H_
|
||||||
|
#define _ROCKCHIP_BRIDGE_H_
|
||||||
|
|
||||||
|
#include <config.h>
|
||||||
|
#include <common.h>
|
||||||
|
#include <dm/device.h>
|
||||||
|
#include <errno.h>
|
||||||
|
|
||||||
|
struct display_state;
|
||||||
|
struct rockchip_bridge;
|
||||||
|
|
||||||
|
struct rockchip_bridge_funcs {
|
||||||
|
void (*enable)(struct rockchip_bridge *bridge);
|
||||||
|
void (*disable)(struct rockchip_bridge *bridge);
|
||||||
|
void (*pre_enable)(struct rockchip_bridge *bridge);
|
||||||
|
void (*post_disable)(struct rockchip_bridge *bridge);
|
||||||
|
};
|
||||||
|
|
||||||
|
struct rockchip_bridge {
|
||||||
|
struct udevice *dev;
|
||||||
|
const struct rockchip_bridge_funcs *funcs;
|
||||||
|
|
||||||
|
struct display_state *state;
|
||||||
|
};
|
||||||
|
|
||||||
|
void rockchip_bridge_enable(struct rockchip_bridge *bridge);
|
||||||
|
void rockchip_bridge_disable(struct rockchip_bridge *bridge);
|
||||||
|
void rockchip_bridge_pre_enable(struct rockchip_bridge *bridge);
|
||||||
|
void rockchip_bridge_post_disable(struct rockchip_bridge *bridge);
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
@ -18,6 +18,7 @@
|
||||||
#include <malloc.h>
|
#include <malloc.h>
|
||||||
#include <video.h>
|
#include <video.h>
|
||||||
#include <video_rockchip.h>
|
#include <video_rockchip.h>
|
||||||
|
#include <video_bridge.h>
|
||||||
#include <dm/device.h>
|
#include <dm/device.h>
|
||||||
#include <dm/uclass-internal.h>
|
#include <dm/uclass-internal.h>
|
||||||
#include <asm/arch-rockchip/resource_img.h>
|
#include <asm/arch-rockchip/resource_img.h>
|
||||||
|
|
@ -26,6 +27,7 @@
|
||||||
#include "rockchip_display.h"
|
#include "rockchip_display.h"
|
||||||
#include "rockchip_crtc.h"
|
#include "rockchip_crtc.h"
|
||||||
#include "rockchip_connector.h"
|
#include "rockchip_connector.h"
|
||||||
|
#include "rockchip_bridge.h"
|
||||||
#include "rockchip_phy.h"
|
#include "rockchip_phy.h"
|
||||||
#include "rockchip_panel.h"
|
#include "rockchip_panel.h"
|
||||||
#include <dm.h>
|
#include <dm.h>
|
||||||
|
|
@ -169,65 +171,6 @@ static bool can_direct_logo(int bpp)
|
||||||
return bpp == 24 || bpp == 32;
|
return bpp == 24 || bpp == 32;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static struct udevice *get_panel_device(struct display_state *state, ofnode conn_node)
|
|
||||||
{
|
|
||||||
struct panel_state *panel_state = &state->panel_state;
|
|
||||||
struct udevice *dev;
|
|
||||||
struct connector_state *conn_state = &state->conn_state;
|
|
||||||
ofnode node, ports_node, port_node;
|
|
||||||
struct device_node *port, *panel, *ep;
|
|
||||||
int ph;
|
|
||||||
int ret;
|
|
||||||
|
|
||||||
node = dev_read_subnode(conn_state->dev, "panel");
|
|
||||||
if (ofnode_valid(node) &&
|
|
||||||
of_device_is_available(ofnode_to_np(node))) {
|
|
||||||
ret = uclass_get_device_by_ofnode(UCLASS_PANEL, node, &dev);
|
|
||||||
if (!ret) {
|
|
||||||
panel_state->node = node;
|
|
||||||
return dev;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* TODO: this path not tested */
|
|
||||||
ports_node = dev_read_subnode(conn_state->dev, "ports");
|
|
||||||
if (!ofnode_valid(ports_node))
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
ofnode_for_each_subnode(port_node, ports_node) {
|
|
||||||
ofnode_for_each_subnode(node, port_node) {
|
|
||||||
ph = ofnode_read_u32_default(node, "remote-endpoint", -1);
|
|
||||||
if (!ph)
|
|
||||||
continue;
|
|
||||||
ep = of_find_node_by_phandle(ph);
|
|
||||||
if (!ofnode_valid(np_to_ofnode(ep))) {
|
|
||||||
printf("Warn: can't find endpoint from phdl\n");
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
port = of_get_parent(ep);
|
|
||||||
if (!ofnode_valid(np_to_ofnode(port))) {
|
|
||||||
printf("Warn: can't find port node\n");
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
panel = of_get_parent(port);
|
|
||||||
if (!ofnode_valid(np_to_ofnode(panel))) {
|
|
||||||
printf("Warn: can't find panel node\n");
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
ret = uclass_get_device_by_ofnode(UCLASS_PANEL,
|
|
||||||
np_to_ofnode(panel),
|
|
||||||
&dev);
|
|
||||||
if (!ret) {
|
|
||||||
panel_state->node = np_to_ofnode(panel);
|
|
||||||
return dev;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int connector_phy_init(struct display_state *state,
|
static int connector_phy_init(struct display_state *state,
|
||||||
struct public_phy_data *data)
|
struct public_phy_data *data)
|
||||||
{
|
{
|
||||||
|
|
@ -292,27 +235,12 @@ static int connector_panel_init(struct display_state *state)
|
||||||
{
|
{
|
||||||
struct connector_state *conn_state = &state->conn_state;
|
struct connector_state *conn_state = &state->conn_state;
|
||||||
struct panel_state *panel_state = &state->panel_state;
|
struct panel_state *panel_state = &state->panel_state;
|
||||||
struct udevice *dev;
|
const struct rockchip_panel *panel = panel_state->panel;
|
||||||
ofnode conn_node = conn_state->node;
|
|
||||||
const struct rockchip_panel *panel;
|
|
||||||
ofnode dsp_lut_node;
|
ofnode dsp_lut_node;
|
||||||
int ret, len;
|
int ret, len;
|
||||||
|
|
||||||
dm_scan_fdt_dev(conn_state->dev);
|
if (!panel)
|
||||||
|
|
||||||
dev = get_panel_device(state, conn_node);
|
|
||||||
if (!dev) {
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
|
||||||
|
|
||||||
panel = (const struct rockchip_panel *)dev_get_driver_data(dev);
|
|
||||||
if (!panel) {
|
|
||||||
printf("failed to find panel driver\n");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
panel_state->dev = dev;
|
|
||||||
panel_state->panel = panel;
|
|
||||||
|
|
||||||
if (panel->funcs && panel->funcs->init) {
|
if (panel->funcs && panel->funcs->init) {
|
||||||
ret = panel->funcs->init(state);
|
ret = panel->funcs->init(state);
|
||||||
|
|
@ -322,7 +250,7 @@ static int connector_panel_init(struct display_state *state)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
dsp_lut_node = dev_read_subnode(dev, "dsp-lut");
|
dsp_lut_node = dev_read_subnode(panel->dev, "dsp-lut");
|
||||||
if (!ofnode_valid(dsp_lut_node)) {
|
if (!ofnode_valid(dsp_lut_node)) {
|
||||||
debug("%s can not find dsp-lut node\n", __func__);
|
debug("%s can not find dsp-lut node\n", __func__);
|
||||||
return 0;
|
return 0;
|
||||||
|
|
@ -379,6 +307,7 @@ int drm_mode_vrefresh(const struct drm_display_mode *mode)
|
||||||
static int display_get_timing_from_dts(struct panel_state *panel_state,
|
static int display_get_timing_from_dts(struct panel_state *panel_state,
|
||||||
struct drm_display_mode *mode)
|
struct drm_display_mode *mode)
|
||||||
{
|
{
|
||||||
|
struct rockchip_panel *panel = panel_state->panel;
|
||||||
int phandle;
|
int phandle;
|
||||||
int hactive, vactive, pixelclock;
|
int hactive, vactive, pixelclock;
|
||||||
int hfront_porch, hback_porch, hsync_len;
|
int hfront_porch, hback_porch, hsync_len;
|
||||||
|
|
@ -386,7 +315,7 @@ static int display_get_timing_from_dts(struct panel_state *panel_state,
|
||||||
int val, flags = 0;
|
int val, flags = 0;
|
||||||
ofnode timing, native_mode;
|
ofnode timing, native_mode;
|
||||||
|
|
||||||
timing = dev_read_subnode(panel_state->dev, "display-timings");
|
timing = dev_read_subnode(panel->dev, "display-timings");
|
||||||
if (!ofnode_valid(timing))
|
if (!ofnode_valid(timing))
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
|
|
||||||
|
|
@ -585,11 +514,10 @@ static int display_get_timing(struct display_state *state)
|
||||||
const struct drm_display_mode *m;
|
const struct drm_display_mode *m;
|
||||||
struct panel_state *panel_state = &state->panel_state;
|
struct panel_state *panel_state = &state->panel_state;
|
||||||
const struct rockchip_panel *panel = panel_state->panel;
|
const struct rockchip_panel *panel = panel_state->panel;
|
||||||
const struct rockchip_panel_funcs *panel_funcs = panel->funcs;
|
|
||||||
ofnode panel_node = panel_state->node;
|
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
if (ofnode_valid(panel_node) && !display_get_timing_from_dts(panel_state, mode)) {
|
if (dev_of_valid(panel->dev) &&
|
||||||
|
!display_get_timing_from_dts(panel_state, mode)) {
|
||||||
printf("Using display timing dts\n");
|
printf("Using display timing dts\n");
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
@ -605,8 +533,8 @@ static int display_get_timing(struct display_state *state)
|
||||||
int panel_bits_per_colourp;
|
int panel_bits_per_colourp;
|
||||||
|
|
||||||
/* In order to read EDID, the panel needs to be powered on */
|
/* In order to read EDID, the panel needs to be powered on */
|
||||||
if (panel_funcs->prepare) {
|
if (panel->funcs->prepare) {
|
||||||
ret = panel_funcs->prepare(state);
|
ret = panel->funcs->prepare(state);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
printf("failed to prepare panel\n");
|
printf("failed to prepare panel\n");
|
||||||
return ret;
|
return ret;
|
||||||
|
|
@ -620,8 +548,8 @@ static int display_get_timing(struct display_state *state)
|
||||||
edid_print_info((void *)&conn_state->edid);
|
edid_print_info((void *)&conn_state->edid);
|
||||||
goto done;
|
goto done;
|
||||||
} else {
|
} else {
|
||||||
if (panel_funcs->unprepare)
|
if (panel->funcs->unprepare)
|
||||||
panel_funcs->unprepare(state);
|
panel->funcs->unprepare(state);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -645,6 +573,7 @@ done:
|
||||||
static int display_init(struct display_state *state)
|
static int display_init(struct display_state *state)
|
||||||
{
|
{
|
||||||
struct connector_state *conn_state = &state->conn_state;
|
struct connector_state *conn_state = &state->conn_state;
|
||||||
|
struct panel_state *panel_state = &state->panel_state;
|
||||||
const struct rockchip_connector *conn = conn_state->connector;
|
const struct rockchip_connector *conn = conn_state->connector;
|
||||||
const struct rockchip_connector_funcs *conn_funcs = conn->funcs;
|
const struct rockchip_connector_funcs *conn_funcs = conn->funcs;
|
||||||
struct crtc_state *crtc_state = &state->crtc_state;
|
struct crtc_state *crtc_state = &state->crtc_state;
|
||||||
|
|
@ -698,13 +627,24 @@ static int display_init(struct display_state *state)
|
||||||
|
|
||||||
if (conn_funcs->get_timing) {
|
if (conn_funcs->get_timing) {
|
||||||
ret = conn_funcs->get_timing(state);
|
ret = conn_funcs->get_timing(state);
|
||||||
if (ret)
|
} else if (panel_state->panel) {
|
||||||
goto deinit;
|
|
||||||
} else {
|
|
||||||
ret = display_get_timing(state);
|
ret = display_get_timing(state);
|
||||||
if (ret)
|
} else if (conn_state->bridge) {
|
||||||
goto deinit;
|
int bpc;
|
||||||
|
|
||||||
|
ret = video_bridge_read_edid(conn_state->bridge->dev,
|
||||||
|
conn_state->edid, EDID_SIZE);
|
||||||
|
if (ret > 0) {
|
||||||
|
ret = edid_get_drm_mode(conn_state->edid, ret, mode,
|
||||||
|
&bpc);
|
||||||
|
if (!ret)
|
||||||
|
edid_print_info((void *)&conn_state->edid);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (ret)
|
||||||
|
goto deinit;
|
||||||
|
|
||||||
drm_mode_set_crtcinfo(mode, CRTC_INTERLACE_HALVE_V);
|
drm_mode_set_crtcinfo(mode, CRTC_INTERLACE_HALVE_V);
|
||||||
|
|
||||||
if (crtc_funcs->init) {
|
if (crtc_funcs->init) {
|
||||||
|
|
@ -842,6 +782,9 @@ static int display_enable(struct display_state *state)
|
||||||
goto unprepare_crtc;
|
goto unprepare_crtc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (conn_state->bridge)
|
||||||
|
rockchip_bridge_pre_enable(conn_state->bridge);
|
||||||
|
|
||||||
display_panel_prepare(state);
|
display_panel_prepare(state);
|
||||||
|
|
||||||
if (crtc_funcs->enable) {
|
if (crtc_funcs->enable) {
|
||||||
|
|
@ -856,6 +799,9 @@ static int display_enable(struct display_state *state)
|
||||||
goto disable_crtc;
|
goto disable_crtc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (conn_state->bridge)
|
||||||
|
rockchip_bridge_enable(conn_state->bridge);
|
||||||
|
|
||||||
display_panel_enable(state);
|
display_panel_enable(state);
|
||||||
|
|
||||||
state->is_enable = true;
|
state->is_enable = true;
|
||||||
|
|
@ -890,14 +836,20 @@ static int display_disable(struct display_state *state)
|
||||||
|
|
||||||
display_panel_disable(state);
|
display_panel_disable(state);
|
||||||
|
|
||||||
if (crtc_funcs->disable)
|
if (conn_state->bridge)
|
||||||
crtc_funcs->disable(state);
|
rockchip_bridge_disable(conn_state->bridge);
|
||||||
|
|
||||||
if (conn_funcs->disable)
|
if (conn_funcs->disable)
|
||||||
conn_funcs->disable(state);
|
conn_funcs->disable(state);
|
||||||
|
|
||||||
|
if (crtc_funcs->disable)
|
||||||
|
crtc_funcs->disable(state);
|
||||||
|
|
||||||
display_panel_unprepare(state);
|
display_panel_unprepare(state);
|
||||||
|
|
||||||
|
if (conn_state->bridge)
|
||||||
|
rockchip_bridge_post_disable(conn_state->bridge);
|
||||||
|
|
||||||
if (conn_funcs->unprepare)
|
if (conn_funcs->unprepare)
|
||||||
conn_funcs->unprepare(state);
|
conn_funcs->unprepare(state);
|
||||||
|
|
||||||
|
|
@ -1232,6 +1184,126 @@ void rockchip_show_logo(void)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
enum {
|
||||||
|
PORT_DIR_IN,
|
||||||
|
PORT_DIR_OUT,
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct rockchip_panel *rockchip_of_find_panel(struct udevice *dev)
|
||||||
|
{
|
||||||
|
ofnode panel_node, ports, port, ep;
|
||||||
|
struct udevice *panel_dev;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
panel_node = dev_read_subnode(dev, "panel");
|
||||||
|
if (ofnode_valid(panel_node) && ofnode_is_available(panel_node)) {
|
||||||
|
ret = uclass_get_device_by_ofnode(UCLASS_PANEL, panel_node,
|
||||||
|
&panel_dev);
|
||||||
|
if (!ret)
|
||||||
|
goto found;
|
||||||
|
}
|
||||||
|
|
||||||
|
ports = dev_read_subnode(dev, "ports");
|
||||||
|
if (!ofnode_valid(ports))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
ofnode_for_each_subnode(port, ports) {
|
||||||
|
u32 reg;
|
||||||
|
|
||||||
|
if (ofnode_read_u32(port, "reg", ®))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (reg != PORT_DIR_OUT)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
ofnode_for_each_subnode(ep, port) {
|
||||||
|
ofnode _ep, _port;
|
||||||
|
uint phandle;
|
||||||
|
|
||||||
|
if (ofnode_read_u32(ep, "remote-endpoint", &phandle))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
_ep = ofnode_get_by_phandle(phandle);
|
||||||
|
if (!ofnode_valid(_ep))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
_port = ofnode_get_parent(_ep);
|
||||||
|
if (!ofnode_valid(_port))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
panel_node = ofnode_get_parent(_port);
|
||||||
|
if (!ofnode_valid(panel_node))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
ret = uclass_get_device_by_ofnode(UCLASS_PANEL,
|
||||||
|
panel_node,
|
||||||
|
&panel_dev);
|
||||||
|
if (!ret)
|
||||||
|
goto found;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
found:
|
||||||
|
return (struct rockchip_panel *)dev_get_driver_data(panel_dev);
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct rockchip_bridge *rockchip_of_find_bridge(struct udevice *conn_dev)
|
||||||
|
{
|
||||||
|
ofnode node, ports, port, ep;
|
||||||
|
struct udevice *dev;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
ports = dev_read_subnode(conn_dev, "ports");
|
||||||
|
if (!ofnode_valid(ports))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
ofnode_for_each_subnode(port, ports) {
|
||||||
|
u32 reg;
|
||||||
|
|
||||||
|
if (ofnode_read_u32(port, "reg", ®))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (reg != PORT_DIR_OUT)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
ofnode_for_each_subnode(ep, port) {
|
||||||
|
ofnode _ep, _port, _ports;
|
||||||
|
uint phandle;
|
||||||
|
|
||||||
|
if (ofnode_read_u32(ep, "remote-endpoint", &phandle))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
_ep = ofnode_get_by_phandle(phandle);
|
||||||
|
if (!ofnode_valid(_ep))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
_port = ofnode_get_parent(_ep);
|
||||||
|
if (!ofnode_valid(_port))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
_ports = ofnode_get_parent(_port);
|
||||||
|
if (!ofnode_valid(_ports))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
node = ofnode_get_parent(_ports);
|
||||||
|
if (!ofnode_valid(node))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
ret = uclass_get_device_by_ofnode(UCLASS_VIDEO_BRIDGE,
|
||||||
|
node, &dev);
|
||||||
|
if (!ret)
|
||||||
|
goto found;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
found:
|
||||||
|
return (struct rockchip_bridge *)dev_get_driver_data(dev);
|
||||||
|
}
|
||||||
|
|
||||||
static struct udevice *rockchip_of_find_connector(ofnode endpoint)
|
static struct udevice *rockchip_of_find_connector(ofnode endpoint)
|
||||||
{
|
{
|
||||||
ofnode ep, port, ports, conn;
|
ofnode ep, port, ports, conn;
|
||||||
|
|
@ -1274,6 +1346,8 @@ static int rockchip_display_probe(struct udevice *dev)
|
||||||
struct udevice *crtc_dev, *conn_dev;
|
struct udevice *crtc_dev, *conn_dev;
|
||||||
struct rockchip_crtc *crtc;
|
struct rockchip_crtc *crtc;
|
||||||
const struct rockchip_connector *conn;
|
const struct rockchip_connector *conn;
|
||||||
|
struct rockchip_panel *panel = NULL;
|
||||||
|
struct rockchip_bridge *bridge = NULL;
|
||||||
struct display_state *s;
|
struct display_state *s;
|
||||||
const char *name;
|
const char *name;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
@ -1338,6 +1412,12 @@ static int rockchip_display_probe(struct udevice *dev)
|
||||||
|
|
||||||
conn = (const struct rockchip_connector *)dev_get_driver_data(conn_dev);
|
conn = (const struct rockchip_connector *)dev_get_driver_data(conn_dev);
|
||||||
|
|
||||||
|
bridge = rockchip_of_find_bridge(conn_dev);
|
||||||
|
if (bridge)
|
||||||
|
panel = rockchip_of_find_panel(bridge->dev);
|
||||||
|
else
|
||||||
|
panel = rockchip_of_find_panel(conn_dev);
|
||||||
|
|
||||||
s = malloc(sizeof(*s));
|
s = malloc(sizeof(*s));
|
||||||
if (!s)
|
if (!s)
|
||||||
continue;
|
continue;
|
||||||
|
|
@ -1363,9 +1443,11 @@ static int rockchip_display_probe(struct udevice *dev)
|
||||||
s->charge_logo_mode = ROCKCHIP_DISPLAY_CENTER;
|
s->charge_logo_mode = ROCKCHIP_DISPLAY_CENTER;
|
||||||
|
|
||||||
s->blob = blob;
|
s->blob = blob;
|
||||||
|
s->panel_state.panel = panel;
|
||||||
s->conn_state.node = conn_dev->node;
|
s->conn_state.node = conn_dev->node;
|
||||||
s->conn_state.dev = conn_dev;
|
s->conn_state.dev = conn_dev;
|
||||||
s->conn_state.connector = conn;
|
s->conn_state.connector = conn;
|
||||||
|
s->conn_state.bridge = bridge;
|
||||||
s->conn_state.overscan.left_margin = 100;
|
s->conn_state.overscan.left_margin = 100;
|
||||||
s->conn_state.overscan.right_margin = 100;
|
s->conn_state.overscan.right_margin = 100;
|
||||||
s->conn_state.overscan.top_margin = 100;
|
s->conn_state.overscan.top_margin = 100;
|
||||||
|
|
@ -1375,6 +1457,10 @@ static int rockchip_display_probe(struct udevice *dev)
|
||||||
s->crtc_state.crtc = crtc;
|
s->crtc_state.crtc = crtc;
|
||||||
s->crtc_state.crtc_id = get_crtc_id(np_to_ofnode(ep_node));
|
s->crtc_state.crtc_id = get_crtc_id(np_to_ofnode(ep_node));
|
||||||
s->node = node;
|
s->node = node;
|
||||||
|
|
||||||
|
if (bridge)
|
||||||
|
bridge->state = s;
|
||||||
|
|
||||||
get_crtc_mcu_mode(&s->crtc_state);
|
get_crtc_mcu_mode(&s->crtc_state);
|
||||||
|
|
||||||
if (connector_panel_init(s)) {
|
if (connector_panel_init(s)) {
|
||||||
|
|
|
||||||
|
|
@ -87,12 +87,9 @@ struct crtc_state {
|
||||||
};
|
};
|
||||||
|
|
||||||
struct panel_state {
|
struct panel_state {
|
||||||
struct udevice *dev;
|
struct rockchip_panel *panel;
|
||||||
ofnode node;
|
|
||||||
ofnode dsp_lut_node;
|
|
||||||
|
|
||||||
const struct rockchip_panel *panel;
|
ofnode dsp_lut_node;
|
||||||
void *private;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct overscan {
|
struct overscan {
|
||||||
|
|
@ -105,6 +102,7 @@ struct overscan {
|
||||||
struct connector_state {
|
struct connector_state {
|
||||||
struct udevice *dev;
|
struct udevice *dev;
|
||||||
const struct rockchip_connector *connector;
|
const struct rockchip_connector *connector;
|
||||||
|
struct rockchip_bridge *bridge;
|
||||||
struct udevice *phy_dev;
|
struct udevice *phy_dev;
|
||||||
struct rockchip_phy *phy;
|
struct rockchip_phy *phy;
|
||||||
ofnode node;
|
ofnode node;
|
||||||
|
|
@ -167,6 +165,13 @@ struct display_state {
|
||||||
int is_enable;
|
int is_enable;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static inline struct rockchip_panel *state_get_panel(struct display_state *s)
|
||||||
|
{
|
||||||
|
struct panel_state *panel_state = &s->panel_state;
|
||||||
|
|
||||||
|
return panel_state->panel;
|
||||||
|
}
|
||||||
|
|
||||||
int drm_mode_vrefresh(const struct drm_display_mode *mode);
|
int drm_mode_vrefresh(const struct drm_display_mode *mode);
|
||||||
int display_send_mcu_cmd(struct display_state *state, u32 type, u32 val);
|
int display_send_mcu_cmd(struct display_state *state, u32 type, u32 val);
|
||||||
bool drm_mode_is_420(const struct drm_display_info *display,
|
bool drm_mode_is_420(const struct drm_display_info *display,
|
||||||
|
|
|
||||||
|
|
@ -23,6 +23,7 @@
|
||||||
#include "rockchip_display.h"
|
#include "rockchip_display.h"
|
||||||
#include "rockchip_crtc.h"
|
#include "rockchip_crtc.h"
|
||||||
#include "rockchip_connector.h"
|
#include "rockchip_connector.h"
|
||||||
|
#include "rockchip_panel.h"
|
||||||
#include "rockchip_lvds.h"
|
#include "rockchip_lvds.h"
|
||||||
|
|
||||||
enum rockchip_lvds_sub_devtype {
|
enum rockchip_lvds_sub_devtype {
|
||||||
|
|
@ -524,8 +525,7 @@ static int rockchip_lvds_init(struct display_state *state)
|
||||||
const char *name;
|
const char *name;
|
||||||
int i, width;
|
int i, width;
|
||||||
struct resource lvds_phy, lvds_ctrl;
|
struct resource lvds_phy, lvds_ctrl;
|
||||||
struct panel_state *panel_state = &state->panel_state;
|
struct rockchip_panel *panel = state_get_panel(state);
|
||||||
ofnode panel_node = panel_state->node;
|
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
lvds = malloc(sizeof(*lvds));
|
lvds = malloc(sizeof(*lvds));
|
||||||
|
|
@ -561,7 +561,7 @@ static int rockchip_lvds_init(struct display_state *state)
|
||||||
return -ENXIO;
|
return -ENXIO;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = dev_read_string_index(panel_state->dev, "rockchip,output", 0, &name);
|
ret = dev_read_string_index(panel->dev, "rockchip,output", 0, &name);
|
||||||
if (ret)
|
if (ret)
|
||||||
/* default set it as output rgb */
|
/* default set it as output rgb */
|
||||||
lvds->output = DISPLAY_OUTPUT_RGB;
|
lvds->output = DISPLAY_OUTPUT_RGB;
|
||||||
|
|
@ -572,7 +572,8 @@ static int rockchip_lvds_init(struct display_state *state)
|
||||||
free(lvds);
|
free(lvds);
|
||||||
return lvds->output;
|
return lvds->output;
|
||||||
}
|
}
|
||||||
ret = dev_read_string_index(panel_state->dev, "rockchip,data-mapping", 0, &name);
|
ret = dev_read_string_index(panel->dev, "rockchip,data-mapping",
|
||||||
|
0, &name);
|
||||||
if (ret)
|
if (ret)
|
||||||
/* default set it as format jeida */
|
/* default set it as format jeida */
|
||||||
lvds->format = LVDS_FORMAT_JEIDA;
|
lvds->format = LVDS_FORMAT_JEIDA;
|
||||||
|
|
@ -584,7 +585,7 @@ static int rockchip_lvds_init(struct display_state *state)
|
||||||
free(lvds);
|
free(lvds);
|
||||||
return lvds->format;
|
return lvds->format;
|
||||||
}
|
}
|
||||||
width = ofnode_read_u32_default(panel_node, "rockchip,data-width", 24);
|
width = dev_read_u32_default(panel->dev, "rockchip,data-width", 24);
|
||||||
if (width == 24) {
|
if (width == 24) {
|
||||||
lvds->format |= LVDS_24BIT;
|
lvds->format |= LVDS_24BIT;
|
||||||
} else if (width == 18) {
|
} else if (width == 18) {
|
||||||
|
|
|
||||||
|
|
@ -183,8 +183,8 @@ static int rockchip_panel_send_mcu_cmds(struct display_state *state,
|
||||||
static int rockchip_panel_send_spi_cmds(struct display_state *state,
|
static int rockchip_panel_send_spi_cmds(struct display_state *state,
|
||||||
struct rockchip_panel_cmds *cmds)
|
struct rockchip_panel_cmds *cmds)
|
||||||
{
|
{
|
||||||
struct panel_state *panel_state = &state->panel_state;
|
struct rockchip_panel *panel = state_get_panel(state);
|
||||||
struct rockchip_panel_priv *priv = dev_get_priv(panel_state->dev);
|
struct rockchip_panel_priv *priv = dev_get_priv(panel->dev);
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
if (!cmds)
|
if (!cmds)
|
||||||
|
|
@ -253,9 +253,9 @@ static int rockchip_panel_send_dsi_cmds(struct display_state *state,
|
||||||
|
|
||||||
static int rockchip_panel_prepare(struct display_state *state)
|
static int rockchip_panel_prepare(struct display_state *state)
|
||||||
{
|
{
|
||||||
struct panel_state *panel_state = &state->panel_state;
|
struct rockchip_panel *panel = state_get_panel(state);
|
||||||
struct rockchip_panel_plat *plat = dev_get_platdata(panel_state->dev);
|
struct rockchip_panel_plat *plat = dev_get_platdata(panel->dev);
|
||||||
struct rockchip_panel_priv *priv = dev_get_priv(panel_state->dev);
|
struct rockchip_panel_priv *priv = dev_get_priv(panel->dev);
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
if (priv->prepared)
|
if (priv->prepared)
|
||||||
|
|
@ -299,9 +299,9 @@ static int rockchip_panel_prepare(struct display_state *state)
|
||||||
|
|
||||||
static void rockchip_panel_unprepare(struct display_state *state)
|
static void rockchip_panel_unprepare(struct display_state *state)
|
||||||
{
|
{
|
||||||
struct panel_state *panel_state = &state->panel_state;
|
struct rockchip_panel *panel = state_get_panel(state);
|
||||||
struct rockchip_panel_plat *plat = dev_get_platdata(panel_state->dev);
|
struct rockchip_panel_plat *plat = dev_get_platdata(panel->dev);
|
||||||
struct rockchip_panel_priv *priv = dev_get_priv(panel_state->dev);
|
struct rockchip_panel_priv *priv = dev_get_priv(panel->dev);
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
if (!priv->prepared)
|
if (!priv->prepared)
|
||||||
|
|
@ -338,9 +338,9 @@ static void rockchip_panel_unprepare(struct display_state *state)
|
||||||
|
|
||||||
static int rockchip_panel_enable(struct display_state *state)
|
static int rockchip_panel_enable(struct display_state *state)
|
||||||
{
|
{
|
||||||
struct panel_state *panel_state = &state->panel_state;
|
struct rockchip_panel *panel = state_get_panel(state);
|
||||||
struct rockchip_panel_plat *plat = dev_get_platdata(panel_state->dev);
|
struct rockchip_panel_plat *plat = dev_get_platdata(panel->dev);
|
||||||
struct rockchip_panel_priv *priv = dev_get_priv(panel_state->dev);
|
struct rockchip_panel_priv *priv = dev_get_priv(panel->dev);
|
||||||
|
|
||||||
if (priv->enabled)
|
if (priv->enabled)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
@ -357,9 +357,9 @@ static int rockchip_panel_enable(struct display_state *state)
|
||||||
|
|
||||||
static void rockchip_panel_disable(struct display_state *state)
|
static void rockchip_panel_disable(struct display_state *state)
|
||||||
{
|
{
|
||||||
struct panel_state *panel_state = &state->panel_state;
|
struct rockchip_panel *panel = state_get_panel(state);
|
||||||
struct rockchip_panel_plat *plat = dev_get_platdata(panel_state->dev);
|
struct rockchip_panel_plat *plat = dev_get_platdata(panel->dev);
|
||||||
struct rockchip_panel_priv *priv = dev_get_priv(panel_state->dev);
|
struct rockchip_panel_priv *priv = dev_get_priv(panel->dev);
|
||||||
|
|
||||||
if (!priv->enabled)
|
if (!priv->enabled)
|
||||||
return;
|
return;
|
||||||
|
|
@ -375,10 +375,9 @@ static void rockchip_panel_disable(struct display_state *state)
|
||||||
static int rockchip_panel_init(struct display_state *state)
|
static int rockchip_panel_init(struct display_state *state)
|
||||||
{
|
{
|
||||||
struct connector_state *conn_state = &state->conn_state;
|
struct connector_state *conn_state = &state->conn_state;
|
||||||
struct panel_state *panel_state = &state->panel_state;
|
struct rockchip_panel *panel = state_get_panel(state);
|
||||||
struct rockchip_panel_plat *plat = dev_get_platdata(panel_state->dev);
|
|
||||||
|
|
||||||
conn_state->bus_format = plat->bus_format;
|
conn_state->bus_format = panel->bus_format;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
@ -450,6 +449,9 @@ free_on_cmds:
|
||||||
static int rockchip_panel_probe(struct udevice *dev)
|
static int rockchip_panel_probe(struct udevice *dev)
|
||||||
{
|
{
|
||||||
struct rockchip_panel_priv *priv = dev_get_priv(dev);
|
struct rockchip_panel_priv *priv = dev_get_priv(dev);
|
||||||
|
struct rockchip_panel_plat *plat = dev_get_platdata(dev);
|
||||||
|
struct rockchip_panel *panel =
|
||||||
|
(struct rockchip_panel *)dev_get_driver_data(dev);
|
||||||
int ret;
|
int ret;
|
||||||
const char *cmd_type;
|
const char *cmd_type;
|
||||||
|
|
||||||
|
|
@ -515,6 +517,9 @@ static int rockchip_panel_probe(struct udevice *dev)
|
||||||
dm_gpio_set_value(&priv->reset_gpio, 0);
|
dm_gpio_set_value(&priv->reset_gpio, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
panel->dev = dev;
|
||||||
|
panel->bus_format = plat->bus_format;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -532,7 +537,7 @@ static const struct drm_display_mode auo_b125han03_mode = {
|
||||||
.flags = DRM_MODE_FLAG_NVSYNC | DRM_MODE_FLAG_NHSYNC,
|
.flags = DRM_MODE_FLAG_NVSYNC | DRM_MODE_FLAG_NHSYNC,
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct rockchip_panel auo_b125han03_data = {
|
static const struct rockchip_panel auo_b125han03_driver_data = {
|
||||||
.funcs = &rockchip_panel_funcs,
|
.funcs = &rockchip_panel_funcs,
|
||||||
.data = &auo_b125han03_mode,
|
.data = &auo_b125han03_mode,
|
||||||
};
|
};
|
||||||
|
|
@ -551,28 +556,32 @@ static const struct drm_display_mode lg_lp079qx1_sp0v_mode = {
|
||||||
.flags = DRM_MODE_FLAG_NVSYNC | DRM_MODE_FLAG_NHSYNC,
|
.flags = DRM_MODE_FLAG_NVSYNC | DRM_MODE_FLAG_NHSYNC,
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct rockchip_panel lg_lp079qx1_sp0v_data = {
|
static const struct rockchip_panel lg_lp079qx1_sp0v_driver_data = {
|
||||||
.funcs = &rockchip_panel_funcs,
|
.funcs = &rockchip_panel_funcs,
|
||||||
.data = &lg_lp079qx1_sp0v_mode,
|
.data = &lg_lp079qx1_sp0v_mode,
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct rockchip_panel rockchip_panel_data = {
|
static const struct rockchip_panel panel_simple_driver_data = {
|
||||||
|
.funcs = &rockchip_panel_funcs,
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct rockchip_panel panel_simple_dsi_driver_data = {
|
||||||
.funcs = &rockchip_panel_funcs,
|
.funcs = &rockchip_panel_funcs,
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct udevice_id rockchip_panel_ids[] = {
|
static const struct udevice_id rockchip_panel_ids[] = {
|
||||||
{
|
{
|
||||||
.compatible = "auo,b125han03",
|
.compatible = "auo,b125han03",
|
||||||
.data = (ulong)&auo_b125han03_data,
|
.data = (ulong)&auo_b125han03_driver_data,
|
||||||
}, {
|
}, {
|
||||||
.compatible = "lg,lp079qx1-sp0v",
|
.compatible = "lg,lp079qx1-sp0v",
|
||||||
.data = (ulong)&lg_lp079qx1_sp0v_data,
|
.data = (ulong)&lg_lp079qx1_sp0v_driver_data,
|
||||||
}, {
|
}, {
|
||||||
.compatible = "simple-panel",
|
.compatible = "simple-panel",
|
||||||
.data = (ulong)&rockchip_panel_data,
|
.data = (ulong)&panel_simple_driver_data,
|
||||||
}, {
|
}, {
|
||||||
.compatible = "simple-panel-dsi",
|
.compatible = "simple-panel-dsi",
|
||||||
.data = (ulong)&rockchip_panel_data,
|
.data = (ulong)&panel_simple_dsi_driver_data,
|
||||||
},
|
},
|
||||||
{}
|
{}
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,8 @@
|
||||||
#ifndef _ROCKCHIP_PANEL_H_
|
#ifndef _ROCKCHIP_PANEL_H_
|
||||||
#define _ROCKCHIP_PANEL_H_
|
#define _ROCKCHIP_PANEL_H_
|
||||||
|
|
||||||
|
struct display_state;
|
||||||
|
|
||||||
struct rockchip_panel_funcs {
|
struct rockchip_panel_funcs {
|
||||||
int (*init)(struct display_state *state);
|
int (*init)(struct display_state *state);
|
||||||
void (*deinit)(struct display_state *state);
|
void (*deinit)(struct display_state *state);
|
||||||
|
|
@ -17,6 +19,8 @@ struct rockchip_panel_funcs {
|
||||||
};
|
};
|
||||||
|
|
||||||
struct rockchip_panel {
|
struct rockchip_panel {
|
||||||
|
struct udevice *dev;
|
||||||
|
u32 bus_format;
|
||||||
const struct rockchip_panel_funcs *funcs;
|
const struct rockchip_panel_funcs *funcs;
|
||||||
const void *data;
|
const void *data;
|
||||||
};
|
};
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue