This commit is contained in:
Tom Rini 2025-03-12 07:55:47 -06:00
commit cf1c0f3963
18 changed files with 744 additions and 11 deletions

View file

@ -77,7 +77,7 @@ config SANDBOX_BITS_PER_LONG
config SYS_FDT_LOAD_ADDR
hex "Address at which to load devicetree"
default 0x100
default 0x1000
help
With sandbox the devicetree is loaded into the emulated RAM. This sets
the address that is used. There must be enough space at this address

View file

@ -1047,6 +1047,31 @@
};
};
lvds-encoder {
compatible = "lvds-encoder";
ports {
#address-cells = <1>;
#size-cells = <0>;
port@0 {
reg = <0>;
bridge_input: endpoint {
/* link to output */
};
};
port@1 {
reg = <1>;
bridge_output: endpoint {
remote-endpoint = <&panel_input>;
};
};
};
};
wdt-gpio-toggle {
gpios = <&gpio_a 8 0>;
compatible = "linux,wdt-gpio";
@ -1402,6 +1427,27 @@
panel {
compatible = "simple-panel";
backlight = <&backlight 0 100>;
display-timings {
timing@0 {
/* 1280x800@60Hz */
clock-frequency = <68000000>;
hactive = <1280>;
hfront-porch = <48>;
hback-porch = <18>;
hsync-len = <30>;
vactive = <800>;
vfront-porch = <3>;
vback-porch = <12>;
vsync-len = <5>;
};
};
port {
panel_input: endpoint {
remote-endpoint = <&bridge_output>;
};
};
};
scsi {
@ -2048,6 +2094,61 @@
sandbox,err-step-size = <512>;
};
};
graph1 {
ports {
#address-cells = <1>;
#size-cells = <0>;
port@0 {
#address-cells = <1>;
#size-cells = <0>;
reg = <0>;
endpoint@0 {
reg = <0>;
};
endpoint@1 {
reg = <1>;
};
};
port@1 {
reg = <1>;
endpoint {
test-property-0;
};
};
port@2 {
#address-cells = <1>;
#size-cells = <0>;
reg = <2>;
graph2_link: endpoint@0 {
reg = <0>;
test-property-1;
remote-endpoint = <&graph1_link>;
};
endpoint@1 {
reg = <1>;
};
};
};
};
graph2 {
port {
graph1_link: endpoint {
remote-endpoint = <&graph2_link>;
};
};
};
};
#include "sandbox_pmic.dtsi"

View file

@ -1080,7 +1080,7 @@ endchoice
config BLOBLIST_ADDR
hex "Address of bloblist"
default 0xb000 if SANDBOX
default 0x100 if SANDBOX
depends on BLOBLIST_FIXED
help
Sets the address of the bloblist, set up by the first part of U-Boot

View file

@ -328,6 +328,8 @@ CONFIG_USB_ETH_CDC=y
CONFIG_VIDEO=y
CONFIG_VIDEO_FONT_SUN12X22=y
CONFIG_VIDEO_COPY=y
CONFIG_VIDEO_BRIDGE=y
CONFIG_VIDEO_BRIDGE_LVDS_CODEC=y
CONFIG_CONSOLE_ROTATION=y
CONFIG_CONSOLE_TRUETYPE=y
CONFIG_CONSOLE_TRUETYPE_CANTORAONE=y

View file

@ -658,10 +658,10 @@ that are mapped into that memory:
======== ======================== ===============================
Addr Config Usage
======== ======================== ===============================
100 CONFIG_SYS_FDT_LOAD_ADDR Device tree
b000 CONFIG_BLOBLIST_ADDR Blob list
10000 CFG_MALLOC_F_ADDR Early memory allocation
100 CONFIG_BLOBLIST_ADDR Blob list
1000 CONFIG_SYS_FDT_LOAD_ADDR Device tree
f0000 CONFIG_PRE_CON_BUF_ADDR Pre-console buffer
f4000 CFG_MALLOC_F_ADDR Early memory allocation
100000 TCG Event log TCG Event Log
200000 CONFIG_TRACE_EARLY_ADDR Early trace buffer (if enabled). Also used
400000 CONFIG_TEXT_BASE Load buffer for U-Boot (sandbox_spl only)

View file

@ -16,6 +16,6 @@ ifndef CONFIG_DM_DEV_READ_INLINE
obj-$(CONFIG_OF_CONTROL) += read.o
endif
obj-$(CONFIG_$(XPL_)OF_PLATDATA) += read.o
obj-$(CONFIG_OF_CONTROL) += of_extra.o ofnode.o read_extra.o
obj-$(CONFIG_OF_CONTROL) += of_extra.o ofnode.o read_extra.o ofnode_graph.o
ccflags-$(CONFIG_DM_DEBUG) += -DDEBUG

217
drivers/core/ofnode_graph.c Normal file
View file

@ -0,0 +1,217 @@
// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright (c) 2025 Svyatoslav Ryhel <clamor95@gmail.com>
*/
#define LOG_CATEGORY LOGC_DT
#include <dm.h>
#include <log.h>
#include <dm/ofnode.h>
#include <linux/err.h>
/**
* ofnode_graph_get_endpoint_count() - get the number of endpoints in a device ofnode
* @parent: ofnode to the device containing ports and endpoints
*
* Return: count of endpoint of this device ofnode
*/
unsigned int ofnode_graph_get_endpoint_count(ofnode parent)
{
ofnode ports, port, endpoint;
unsigned int num = 0;
/* Check if ports node exists */
ports = ofnode_find_subnode(parent, "ports");
if (ofnode_valid(ports))
parent = ports;
ofnode_for_each_subnode(port, parent) {
if (!strncmp(ofnode_get_name(port), "port", 4)) {
/* Port node can only contain endpoints */
ofnode_for_each_subnode(endpoint, port)
num++;
}
};
log_debug("%s: detected %d endpoints\n", __func__, num);
return num++;
}
/**
* ofnode_graph_get_port_count() - get the number of port in a device or ports ofnode
* @parent: ofnode to the device or ports node
*
* Return: count of port of this device or ports node
*/
unsigned int ofnode_graph_get_port_count(ofnode parent)
{
ofnode ports, port;
unsigned int num = 0;
/* Check if ports node exists */
ports = ofnode_find_subnode(parent, "ports");
if (ofnode_valid(ports))
parent = ports;
ofnode_for_each_subnode(port, parent)
if (!strncmp(ofnode_get_name(port), "port", 4))
num++;
log_debug("%s: detected %d ports\n", __func__, num);
return num++;
}
/**
* ofnode_graph_get_port_by_id() - get the port matching a given id
* @parent: parent ofnode
* @id: id of the port
*
* Return: ofnode in given port.
*/
ofnode ofnode_graph_get_port_by_id(ofnode parent, u32 id)
{
ofnode ports, port;
u32 port_id;
ports = ofnode_find_subnode(parent, "ports");
if (!ofnode_valid(ports))
return ofnode_null();
/* Check ports for node with desired id */
ofnode_for_each_subnode(port, ports) {
ofnode_read_u32(port, "reg", &port_id);
log_debug("%s: detected port %d\n", __func__, port_id);
if (port_id == id)
return port;
}
return ofnode_null();
}
/**
* ofnode_graph_get_endpoint_by_regs() - get the endpoint matching a given id
* @parent: parent ofnode
* @reg_id: id of the port
* @id: id for the endpoint
*
* Return: ofnode in given endpoint or ofnode_null() if not found.
* reg and port_reg are ignored when they are -1.
*/
ofnode ofnode_graph_get_endpoint_by_regs(ofnode parent, int reg_id, int id)
{
ofnode port, endpoint;
u32 ep_id;
/* get the port to work with */
if (reg_id < 0)
port = ofnode_find_subnode(parent, "port");
else
port = ofnode_graph_get_port_by_id(parent, reg_id);
if (!ofnode_valid(port)) {
log_debug("%s: port node is not found\n", __func__);
return ofnode_null();
}
if (id < 0)
return ofnode_find_subnode(port, "endpoint");
/* Check endpoints for node with desired id */
ofnode_for_each_subnode(endpoint, port) {
ofnode_read_u32(endpoint, "reg", &ep_id);
log_debug("%s: detected endpoint %d\n", __func__, ep_id);
if (ep_id == id)
return endpoint;
}
return ofnode_null();
}
/**
* ofnode_graph_get_remote_endpoint() - get remote endpoint node
* @endpoint: ofnode of a local endpoint
*
* Return: Remote endpoint ofnode linked with local endpoint.
*/
ofnode ofnode_graph_get_remote_endpoint(ofnode endpoint)
{
/* Get remote endpoint node. */
return ofnode_parse_phandle(endpoint, "remote-endpoint", 0);
}
/**
* ofnode_graph_get_port_parent() - get port's parent node
* @endpoint: ofnode of a local endpoint
*
* Return: device ofnode associated with endpoint
*/
ofnode ofnode_graph_get_port_parent(ofnode endpoint)
{
ofnode port = ofnode_get_parent(endpoint);
ofnode parent = ofnode_get_parent(port);
/* check if we are on top level or in ports node */
if (!strcmp(ofnode_get_name(parent), "ports"))
parent = ofnode_get_parent(parent);
return parent;
}
/**
* ofnode_graph_get_remote_port_parent() - get remote port's parent ofnode
* @endpoint: ofnode of a local endpoint
*
* Return: device ofnode associated with endpoint linked to local endpoint.
*/
ofnode ofnode_graph_get_remote_port_parent(ofnode endpoint)
{
ofnode remote_endpoint = ofnode_graph_get_remote_endpoint(endpoint);
if (!ofnode_valid(remote_endpoint)) {
log_debug("%s: remote endpoint is not found\n", __func__);
return ofnode_null();
}
return ofnode_graph_get_port_parent(remote_endpoint);
}
/**
* ofnode_graph_get_remote_port() - get remote port ofnode
* @endpoint: ofnode of a local endpoint
*
* Return: port ofnode associated with remote endpoint node linked
* to local endpoint.
*/
ofnode ofnode_graph_get_remote_port(ofnode endpoint)
{
ofnode remote_endpoint = ofnode_graph_get_remote_endpoint(endpoint);
if (!ofnode_valid(remote_endpoint)) {
log_debug("%s: remote endpoint is not found\n", __func__);
return ofnode_null();
}
return ofnode_get_parent(remote_endpoint);
}
/**
* ofnode_graph_get_remote_node() - get remote parent ofnode for given port/endpoint
* @parent: parent ofnode containing graph port/endpoint
* @port: identifier (value of reg property) of the parent port ofnode
* @endpoint: identifier (value of reg property) of the endpoint ofnode
*
* Return: device ofnode associated with endpoint linked to local endpoint.
*/
ofnode ofnode_graph_get_remote_node(ofnode parent, int port, int endpoint)
{
ofnode endpoint_ofnode;
endpoint_ofnode = ofnode_graph_get_endpoint_by_regs(parent, port, endpoint);
if (!ofnode_valid(endpoint_ofnode)) {
log_debug("%s: endpoint is not found\n", __func__);
return ofnode_null();
}
return ofnode_graph_get_remote_port_parent(endpoint_ofnode);
}

View file

@ -59,3 +59,10 @@ config VIDEO_BRIDGE_TOSHIBA_TC358768
help
Toshiba TC358768AXBG/TC358778XBG DSI bridge chip driver.
Found in Asus Transformer Infinity TF700T.
config VIDEO_BRIDGE_LVDS_CODEC
bool "Transparent LVDS encoders and decoders support"
depends on VIDEO_BRIDGE && PANEL && DM_GPIO
help
Support for transparent LVDS encoders and decoders that don't
require any configuration.

View file

@ -10,3 +10,4 @@ obj-$(CONFIG_VIDEO_BRIDGE_NXP_PTN3460) += ptn3460.o
obj-$(CONFIG_VIDEO_BRIDGE_ANALOGIX_ANX6345) += anx6345.o
obj-$(CONFIG_VIDEO_BRIDGE_SOLOMON_SSD2825) += ssd2825.o
obj-$(CONFIG_VIDEO_BRIDGE_TOSHIBA_TC358768) += tc358768.o
obj-$(CONFIG_VIDEO_BRIDGE_LVDS_CODEC) += lvds-codec.o

View file

@ -0,0 +1,128 @@
// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright (c) 2025 Svyatoslav Ryhel <clamor95@gmail.com>
* Loosely based on Linux lvds-codec.c driver
*/
#include <dm.h>
#include <dm/ofnode_graph.h>
#include <log.h>
#include <panel.h>
#include <video_bridge.h>
#include <asm/gpio.h>
#include <power/regulator.h>
struct lvds_codec_priv {
struct udevice *panel;
struct display_timing timing;
struct gpio_desc powerdown_gpio;
struct udevice *power;
};
static int lvds_codec_attach(struct udevice *dev)
{
struct lvds_codec_priv *priv = dev_get_priv(dev);
regulator_set_enable_if_allowed(priv->power, 1);
dm_gpio_set_value(&priv->powerdown_gpio, 0);
return panel_enable_backlight(priv->panel);
}
static int lvds_codec_set_panel(struct udevice *dev, int percent)
{
struct lvds_codec_priv *priv = dev_get_priv(dev);
return panel_set_backlight(priv->panel, percent);
}
static int lvds_codec_panel_timings(struct udevice *dev,
struct display_timing *timing)
{
struct lvds_codec_priv *priv = dev_get_priv(dev);
memcpy(timing, &priv->timing, sizeof(*timing));
return 0;
}
/* Function is purely for sandbox testing */
static int lvds_codec_read_edid(struct udevice *dev, u8 *buf, int buf_size)
{
return 0;
}
static int lvds_codec_get_panel(struct udevice *dev)
{
struct lvds_codec_priv *priv = dev_get_priv(dev);
int i, ret;
u32 num = ofnode_graph_get_port_count(dev_ofnode(dev));
for (i = 0; i < num; i++) {
ofnode remote = ofnode_graph_get_remote_node(dev_ofnode(dev), i, -1);
ret = uclass_get_device_by_of_offset(UCLASS_PANEL,
ofnode_to_offset(remote),
&priv->panel);
if (!ret)
return 0;
}
/* If this point is reached, no panels were found */
return -ENODEV;
}
static int lvds_codec_probe(struct udevice *dev)
{
struct lvds_codec_priv *priv = dev_get_priv(dev);
int ret;
ret = lvds_codec_get_panel(dev);
if (ret) {
log_debug("%s: cannot get panel: ret=%d\n", __func__, ret);
return log_ret(ret);
}
panel_get_display_timing(priv->panel, &priv->timing);
ret = gpio_request_by_name(dev, "powerdown-gpios", 0,
&priv->powerdown_gpio, GPIOD_IS_OUT);
if (ret) {
log_debug("%s: could not get powerdown-gpios (%d)\n", __func__, ret);
if (ret != -ENOENT)
return log_ret(ret);
}
ret = device_get_supply_regulator(dev, "power-supply", &priv->power);
if (ret) {
log_debug("%s: power regulator error: %d\n", __func__, ret);
if (ret != -ENOENT)
return log_ret(ret);
}
return 0;
}
static const struct video_bridge_ops lvds_codec_ops = {
.attach = lvds_codec_attach,
.set_backlight = lvds_codec_set_panel,
.get_display_timing = lvds_codec_panel_timings,
.read_edid = lvds_codec_read_edid,
};
static const struct udevice_id lvds_codec_ids[] = {
{ .compatible = "lvds-decoder" },
{ .compatible = "lvds-encoder" },
{ }
};
U_BOOT_DRIVER(lvds_codec) = {
.name = "lvds_codec",
.id = UCLASS_VIDEO_BRIDGE,
.of_match = lvds_codec_ids,
.ops = &lvds_codec_ops,
.probe = lvds_codec_probe,
.priv_auto = sizeof(struct lvds_codec_priv),
};

View file

@ -33,6 +33,17 @@ int video_bridge_attach(struct udevice *dev)
return ops->attach(dev);
}
int video_bridge_get_display_timing(struct udevice *dev,
struct display_timing *timings)
{
struct video_bridge_ops *ops = video_bridge_get_ops(dev);
if (!ops->get_display_timing)
return -ENOSYS;
return ops->get_display_timing(dev, timings);
}
int video_bridge_check_attached(struct udevice *dev)
{
struct video_bridge_priv *uc_priv = dev_get_uclass_priv(dev);

View file

@ -6,7 +6,7 @@
#ifndef __CONFIG_H
#define __CONFIG_H
#define CFG_MALLOC_F_ADDR 0x0010000
#define CFG_MALLOC_F_ADDR 0x000f4000
/* Size of our emulated memory */
#define SB_CONCAT(x, y) x ## y

90
include/dm/ofnode_graph.h Normal file
View file

@ -0,0 +1,90 @@
/* SPDX-License-Identifier: GPL-2.0+ */
/*
* Copyright (c) 2025 Svyatoslav Ryhel <clamor95@gmail.com>
*/
#ifndef _DM_OFNODE_GRAPH_H
#define _DM_OFNODE_GRAPH_H
#include <dm/of.h>
/**
* ofnode_graph_get_endpoint_count() - get the number of endpoints in a device ofnode
* @parent: ofnode to the device containing ports and endpoints
*
* Return: count of endpoint of this device ofnode
*/
unsigned int ofnode_graph_get_endpoint_count(ofnode parent);
/**
* ofnode_graph_get_port_count() - get the number of port in a device or ports ofnode
* @parent: ofnode to the device or ports node
*
* Return: count of port of this device or ports node
*/
unsigned int ofnode_graph_get_port_count(ofnode parent);
/**
* ofnode_graph_get_port_by_id() - get the port matching a given id
* @parent: parent ofnode
* @id: id of the port
*
* Return: ofnode in given port.
*/
ofnode ofnode_graph_get_port_by_id(ofnode parent, u32 id);
/**
* ofnode_graph_get_endpoint_by_regs() - get the endpoint matching a given id
* @parent: parent ofnode
* @reg_id: id of the port
* @id: id for the endpoint
*
* Return: ofnode in given endpoint or NULL if not found.
* reg and port_reg are ignored when they are -1.
*/
ofnode ofnode_graph_get_endpoint_by_regs(ofnode parent, u32 reg_id, u32 id);
/**
* ofnode_graph_get_remote_endpoint() - get remote endpoint node
* @endoint: ofnode of a local endpoint
*
* Return: Remote endpoint ofnode linked with local endpoint.
*/
ofnode ofnode_graph_get_remote_endpoint(ofnode endpoint);
/**
* ofnode_graph_get_port_parent() - get port's parent node
* @endpoint: ofnode of a local endpoint
*
* Return: device ofnode associated with endpoint
*/
ofnode ofnode_graph_get_port_parent(ofnode endpoint);
/**
* ofnode_graph_get_remote_port_parent() - get remote port's parent ofnode
* @endoint: ofnode of a local endpoint
*
* Return: device ofnode associated with endpoint linked to local endpoint.
*/
ofnode ofnode_graph_get_remote_port_parent(ofnode endpoint);
/**
* ofnode_graph_get_remote_port() - get remote port ofnode
* @endoint: ofnode of a local endpoint
*
* Return: port ofnode associated with remote endpoint node linked
* to local endpoint.
*/
ofnode ofnode_graph_get_remote_port(ofnode endpoint);
/**
* ofnode_graph_get_remote_node() - get remote parent ofnode for given port/endpoint
* @parent: parent ofnode containing graph port/endpoint
* @port: identifier (value of reg property) of the parent port ofnode
* @endpoint: identifier (value of reg property) of the endpoint ofnode
*
* Return: device ofnode associated with endpoint linked to local endpoint.
*/
ofnode ofnode_graph_get_remote_node(ofnode parent, u32 port, u32 endpoint);
#endif

View file

@ -53,6 +53,19 @@ struct video_bridge_ops {
*/
int (*set_backlight)(struct udevice *dev, int percent);
/**
* get_display_timing() - Get display timings from bridge.
*
* @dev: Bridge device containing the linked display timings
* @tim: Place to put timings
* @return 0 if OK, -ve on error
*
* This call it totally optional and useful mainly for integrated
* bridges with fixed output device.
*/
int (*get_display_timing)(struct udevice *dev,
struct display_timing *timing);
/**
* read_edid() - Read information from EDID
*
@ -67,6 +80,7 @@ struct video_bridge_ops {
#define video_bridge_get_ops(dev) \
((struct video_bridge_ops *)(dev)->driver->ops)
#if CONFIG_IS_ENABLED(VIDEO_BRIDGE)
/**
* video_bridge_attach() - attach a video bridge
*
@ -98,6 +112,14 @@ int video_bridge_set_active(struct udevice *dev, bool active);
*/
int video_bridge_check_attached(struct udevice *dev);
/**
* video_bridge_get_display_timing() - Get display timings from bridge.
*
* @dev: Bridge device containing the linked display timings
* Return: 0 if OK, -ve on error
*/
int video_bridge_get_display_timing(struct udevice *dev,
struct display_timing *timing);
/**
* video_bridge_read_edid() - Read information from EDID
*
@ -107,5 +129,37 @@ int video_bridge_check_attached(struct udevice *dev);
* Return: number of bytes read, <=0 for error
*/
int video_bridge_read_edid(struct udevice *dev, u8 *buf, int buf_size);
#else
static inline int video_bridge_attach(struct udevice *dev)
{
return -ENOSYS;
}
static inline int video_bridge_set_backlight(struct udevice *dev, int percent)
{
return -ENOSYS;
}
static inline int video_bridge_set_active(struct udevice *dev, bool active)
{
return -ENOSYS;
}
static inline int video_bridge_check_attached(struct udevice *dev)
{
return -ENOSYS;
}
static inline int video_bridge_get_display_timing(struct udevice *dev,
struct display_timing *timing)
{
return -ENOSYS;
}
static inline int video_bridge_read_edid(struct udevice *dev, u8 *buf, int buf_size)
{
return -ENOSYS;
}
#endif /* CONFIG_VIDEO_BRIDGE */
#endif

View file

@ -63,6 +63,7 @@ obj-$(CONFIG_SOUND) += i2s.o
obj-$(CONFIG_CLK_K210_SET_RATE) += k210_pll.o
obj-$(CONFIG_IOMMU) += iommu.o
obj-$(CONFIG_LED) += led.o
obj-$(CONFIG_VIDEO_BRIDGE_LVDS_CODEC) += video_bridge.o
obj-$(CONFIG_DM_MAILBOX) += mailbox.o
obj-$(CONFIG_DM_MDIO) += mdio.o
obj-$(CONFIG_DM_MDIO_MUX) += mdio_mux.o

View file

@ -23,6 +23,7 @@
#include <dm/device-internal.h>
#include <dm/lists.h>
#include <dm/of_extra.h>
#include <dm/ofnode_graph.h>
#include <dm/root.h>
#include <dm/test.h>
#include <dm/uclass-internal.h>
@ -1651,3 +1652,56 @@ static int dm_test_bool(struct unit_test_state *uts)
return 0;
}
DM_TEST(dm_test_bool, UTF_SCAN_FDT);
/* test all helpers found in drivers/core/ofnode_graph.c */
static int dm_test_ofnode_graph(struct unit_test_state *uts)
{
/* 3 ports with 5 endpoints (2-1-2) */
ofnode graph1 = ofnode_path("/graph1");
/* 1 port with 1 endpoint */
ofnode graph2 = ofnode_path("/graph2");
ofnode node;
u32 id;
ut_asserteq(ofnode_graph_get_endpoint_count(graph1), 5);
ut_asserteq(ofnode_graph_get_endpoint_count(graph2), 1);
ut_asserteq(ofnode_graph_get_port_count(graph1), 3);
ut_asserteq(ofnode_graph_get_port_count(graph2), 1);
/* Request port with reg 2 */
node = ofnode_graph_get_port_by_id(graph1, 2);
ofnode_read_u32(node, "reg", &id);
ut_asserteq(id, 2);
/* Reqest parent from prev requested endpoint */
node = ofnode_graph_get_port_parent(node);
ut_asserteq_str(ofnode_get_name(node), "graph1");
/* Request endpoint under port 1 */
node = ofnode_graph_get_endpoint_by_regs(graph1, 1, -1);
ut_assert(ofnode_has_property(node, "test-property-0"));
/* Reqest remote endpoint from graph2 in graph1 */
node = ofnode_graph_get_endpoint_by_regs(graph2, -1, -1);
node = ofnode_graph_get_remote_endpoint(node);
ut_assert(ofnode_has_property(node, "test-property-1"));
/* Reqest remote parent from graph2 linked endpoint */
node = ofnode_graph_get_endpoint_by_regs(graph2, -1, -1);
node = ofnode_graph_get_remote_port_parent(node);
ut_asserteq_str(ofnode_get_name(node), "graph1");
/* Reqest remote port from graph2 linked endpoint */
node = ofnode_graph_get_endpoint_by_regs(graph2, -1, -1);
node = ofnode_graph_get_remote_port(node);
ofnode_read_u32(node, "reg", &id);
ut_asserteq(id, 2);
/* Reqest remote parent from graph2 linked endpoint */
node = ofnode_graph_get_remote_node(graph2, -1, -1);
ut_asserteq_str(ofnode_get_name(node), "graph1");
return 0;
}
DM_TEST(dm_test_ofnode_graph, UTF_SCAN_FDT);

67
test/dm/video_bridge.c Normal file
View file

@ -0,0 +1,67 @@
// SPDX-License-Identifier: GPL-2.0+
/*
* Test for video bridge uclass
*
* Copyright (c) 2025 Svyatoslav Ryhel <clamor95@gmail.com>
*/
#include <backlight.h>
#include <dm.h>
#include <panel.h>
#include <video.h>
#include <video_bridge.h>
#include <asm/gpio.h>
#include <asm/test.h>
#include <dm/test.h>
#include <power/regulator.h>
#include <test/test.h>
#include <test/ut.h>
/* Basic test of the video uclass, test is based on driven panel */
static int dm_test_video_bridge(struct unit_test_state *uts)
{
struct udevice *dev, *pwm, *gpio, *reg;
uint period_ns, duty_ns;
bool enable, polarity;
struct display_timing timing;
ut_assertok(uclass_first_device_err(UCLASS_VIDEO_BRIDGE, &dev));
ut_assertok(uclass_get_device_by_name(UCLASS_PWM, "pwm", &pwm));
ut_assertok(uclass_get_device(UCLASS_GPIO, 1, &gpio));
ut_assertok(regulator_get_by_platname("VDD_EMMC_1.8V", &reg));
ut_assertok(sandbox_pwm_get_config(pwm, 0, &period_ns, &duty_ns,
&enable, &polarity));
ut_asserteq(false, enable);
ut_asserteq(true, regulator_get_enable(reg));
/* bridge calls panel_enable_backlight() of panel */
ut_assertok(video_bridge_attach(dev));
ut_assertok(sandbox_pwm_get_config(pwm, 0, &period_ns, &duty_ns,
&enable, &polarity));
ut_asserteq(1000, period_ns);
ut_asserteq(170 * 1000 / 255, duty_ns);
ut_asserteq(true, enable);
ut_asserteq(false, polarity);
ut_asserteq(1, sandbox_gpio_get_value(gpio, 1));
ut_asserteq(true, regulator_get_enable(reg));
/* bridge calls panel_set_backlight() of panel */
ut_assertok(video_bridge_set_backlight(dev, BACKLIGHT_DEFAULT));
ut_assertok(sandbox_pwm_get_config(pwm, 0, &period_ns, &duty_ns,
&enable, &polarity));
ut_asserteq(true, enable);
ut_asserteq(170 * 1000 / 255, duty_ns);
/* bridge should be active */
ut_assertok(video_bridge_set_active(dev, true));
/* bridge is internal and has no hotplug gpio */
ut_asserteq(-ENOENT, video_bridge_check_attached(dev));
/* check passing timings and EDID */
ut_assertok(video_bridge_get_display_timing(dev, &timing));
ut_assertok(video_bridge_read_edid(dev, NULL, 0));
return 0;
}
DM_TEST(dm_test_video_bridge, UTF_SCAN_PDATA | UTF_SCAN_FDT);

View file

@ -22,9 +22,9 @@ static int lib_test_is_enabled(struct unit_test_state *uts)
ut_asserteq(0, CONFIG_IS_ENABLED(_UNDEFINED));
if (IS_ENABLED(CONFIG_BLOBLIST)) {
ut_asserteq(0xb000, IF_ENABLED_INT(CONFIG_BLOBLIST_FIXED,
ut_asserteq(0x100, IF_ENABLED_INT(CONFIG_BLOBLIST_FIXED,
CONFIG_BLOBLIST_ADDR));
ut_asserteq(0xb000, CONFIG_IF_ENABLED_INT(BLOBLIST_FIXED,
ut_asserteq(0x100, CONFIG_IF_ENABLED_INT(BLOBLIST_FIXED,
BLOBLIST_ADDR));
}