video: tegra: add 8-bit CPU driven protocol
Add support for 8-bit CPU driven (primary and secondary) display signal interface found in Tegra 2 and Tegra 3 SoC. Tested-by: Ion Agorria <ion@agorria.com> Signed-off-by: Svyatoslav Ryhel <clamor95@gmail.com>
This commit is contained in:
@@ -448,10 +448,19 @@ enum win_color_depth_id {
|
|||||||
#define LVS_OUTPUT_POLARITY_LOW BIT(28)
|
#define LVS_OUTPUT_POLARITY_LOW BIT(28)
|
||||||
#define LSC0_OUTPUT_POLARITY_LOW BIT(24)
|
#define LSC0_OUTPUT_POLARITY_LOW BIT(24)
|
||||||
|
|
||||||
|
/* DC_COM_PIN_OUTPUT_SELECT6 0x31a */
|
||||||
|
#define LDC_OUTPUT_SELECT_V_PULSE1 BIT(14) /* 100b */
|
||||||
|
|
||||||
/* DC_DISP_DISP_SIGNAL_OPTIONS0 0x400 */
|
/* DC_DISP_DISP_SIGNAL_OPTIONS0 0x400 */
|
||||||
#define H_PULSE0_ENABLE BIT(8)
|
#define H_PULSE0_ENABLE BIT(8)
|
||||||
#define H_PULSE1_ENABLE BIT(10)
|
#define H_PULSE1_ENABLE BIT(10)
|
||||||
#define H_PULSE2_ENABLE BIT(12)
|
#define H_PULSE2_ENABLE BIT(12)
|
||||||
|
#define V_PULSE0_ENABLE BIT(16)
|
||||||
|
#define V_PULSE1_ENABLE BIT(18)
|
||||||
|
#define V_PULSE2_ENABLE BIT(19)
|
||||||
|
#define V_PULSE3_ENABLE BIT(20)
|
||||||
|
#define M0_ENABLE BIT(24)
|
||||||
|
#define M1_ENABLE BIT(26)
|
||||||
|
|
||||||
/* DC_DISP_DISP_WIN_OPTIONS 0x402 */
|
/* DC_DISP_DISP_WIN_OPTIONS 0x402 */
|
||||||
#define CURSOR_ENABLE BIT(16)
|
#define CURSOR_ENABLE BIT(16)
|
||||||
@@ -525,6 +534,28 @@ enum {
|
|||||||
BASE_COLOR_SIZE_888,
|
BASE_COLOR_SIZE_888,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* DC_DISP_SHIFT_CLOCK_OPTIONS 0x431 */
|
||||||
|
#define SC0_H_QUALIFIER_SHIFT 0
|
||||||
|
#define SC1_H_QUALIFIER_SHIFT 16
|
||||||
|
enum {
|
||||||
|
SC_H_QUALIFIER_DISABLE,
|
||||||
|
SC_H_QUALIFIER_NONE,
|
||||||
|
SC_H_QUALIFIER_HACTIVE,
|
||||||
|
SC_H_QUALIFIER_EXT_HACTIVE,
|
||||||
|
SC_H_QUALIFIER_HPULSE,
|
||||||
|
SC_H_QUALIFIER_EXT_HPULSE,
|
||||||
|
};
|
||||||
|
#define SC0_V_QUALIFIER_SHIFT 3
|
||||||
|
#define SC1_V_QUALIFIER_SHIFT 19
|
||||||
|
enum {
|
||||||
|
SC_V_QUALIFIER_NONE,
|
||||||
|
SC_V_QUALIFIER_RSVD,
|
||||||
|
SC_V_QUALIFIER_VACTIVE,
|
||||||
|
SC_V_QUALIFIER_EXT_VACTIVE,
|
||||||
|
SC_V_QUALIFIER_VPULSE,
|
||||||
|
SC_V_QUALIFIER_EXT_VPULSE,
|
||||||
|
};
|
||||||
|
|
||||||
/* DC_DISP_DATA_ENABLE_OPTIONS 0x432 */
|
/* DC_DISP_DATA_ENABLE_OPTIONS 0x432 */
|
||||||
#define DE_SELECT_SHIFT 0
|
#define DE_SELECT_SHIFT 0
|
||||||
#define DE_SELECT_MASK (0x3 << DE_SELECT_SHIFT)
|
#define DE_SELECT_MASK (0x3 << DE_SELECT_SHIFT)
|
||||||
@@ -541,6 +572,23 @@ enum {
|
|||||||
DE_CONTROL_ACTIVE_BLANK,
|
DE_CONTROL_ACTIVE_BLANK,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* DC_DISP_INIT_SEQ_CONTROL 0x442 */
|
||||||
|
#define SEND_INIT_SEQUENCE BIT(0)
|
||||||
|
#define INIT_SEQUENCE_MODE_SPI BIT(1)
|
||||||
|
#define INIT_SEQUENCE_MODE_PLCD 0x0
|
||||||
|
#define INIT_SEQ_DC_SIGNAL_SHIFT 4
|
||||||
|
#define INIT_SEQ_DC_SIGNAL_MASK (0x7 << INIT_SEQ_DC_SIGNAL_SHIFT)
|
||||||
|
enum {
|
||||||
|
NO_DC_SIGNAL,
|
||||||
|
DC_SIGNAL_VSYNC,
|
||||||
|
DC_SIGNAL_VPULSE0,
|
||||||
|
DC_SIGNAL_VPULSE1,
|
||||||
|
DC_SIGNAL_VPULSE2,
|
||||||
|
DC_SIGNAL_VPULSE3,
|
||||||
|
};
|
||||||
|
#define INIT_SEQ_DC_CONTROL_SHIFT 7
|
||||||
|
#define FRAME_INIT_SEQ_CYCLES_SHIFT 8
|
||||||
|
|
||||||
/* DC_WIN_WIN_OPTIONS 0x700 */
|
/* DC_WIN_WIN_OPTIONS 0x700 */
|
||||||
#define H_DIRECTION BIT(0)
|
#define H_DIRECTION BIT(0)
|
||||||
enum {
|
enum {
|
||||||
|
@@ -42,6 +42,16 @@ config TEGRA_BACKLIGHT_PWM
|
|||||||
Enable support for the Display Controller dependent PWM backlight
|
Enable support for the Display Controller dependent PWM backlight
|
||||||
found in the Tegra SoC and usually used with DSI panels.
|
found in the Tegra SoC and usually used with DSI panels.
|
||||||
|
|
||||||
|
config TEGRA_8BIT_CPU_BRIDGE
|
||||||
|
bool "Enable 8 bit panel communication protocol for Tegra 20/30"
|
||||||
|
depends on VIDEO_BRIDGE && DM_GPIO
|
||||||
|
select VIDEO_TEGRA
|
||||||
|
select VIDEO_MIPI_DSI
|
||||||
|
help
|
||||||
|
Tegra 20 and Tegra 30 feature 8 bit CPU driver panel control
|
||||||
|
protocol. This option allows use it as a MIPI DSI bridge to
|
||||||
|
set up and control compatible panel.
|
||||||
|
|
||||||
config VIDEO_TEGRA124
|
config VIDEO_TEGRA124
|
||||||
bool "Enable video support on Tegra124"
|
bool "Enable video support on Tegra124"
|
||||||
imply VIDEO_DAMAGE
|
imply VIDEO_DAMAGE
|
||||||
|
@@ -5,5 +5,6 @@ obj-$(CONFIG_VIDEO_TEGRA) += dc.o
|
|||||||
obj-$(CONFIG_VIDEO_DSI_TEGRA) += dsi.o mipi.o mipi-phy.o
|
obj-$(CONFIG_VIDEO_DSI_TEGRA) += dsi.o mipi.o mipi-phy.o
|
||||||
obj-$(CONFIG_VIDEO_HDMI_TEGRA) += hdmi.o
|
obj-$(CONFIG_VIDEO_HDMI_TEGRA) += hdmi.o
|
||||||
obj-$(CONFIG_TEGRA_BACKLIGHT_PWM) += dc-pwm-backlight.o
|
obj-$(CONFIG_TEGRA_BACKLIGHT_PWM) += dc-pwm-backlight.o
|
||||||
|
obj-$(CONFIG_TEGRA_8BIT_CPU_BRIDGE) += cpu-bridge.o
|
||||||
|
|
||||||
obj-${CONFIG_VIDEO_TEGRA124} += tegra124/
|
obj-${CONFIG_VIDEO_TEGRA124} += tegra124/
|
||||||
|
325
drivers/video/tegra/cpu-bridge.c
Normal file
325
drivers/video/tegra/cpu-bridge.c
Normal file
@@ -0,0 +1,325 @@
|
|||||||
|
// SPDX-License-Identifier: GPL-2.0+
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2024 Svyatoslav Ryhel <clamor95@gmail.com>
|
||||||
|
*
|
||||||
|
* This driver uses 8-bit CPU interface found in Tegra 2
|
||||||
|
* and Tegra 3 to drive MIPI DSI panel.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <dm.h>
|
||||||
|
#include <dm/ofnode_graph.h>
|
||||||
|
#include <log.h>
|
||||||
|
#include <mipi_display.h>
|
||||||
|
#include <mipi_dsi.h>
|
||||||
|
#include <backlight.h>
|
||||||
|
#include <panel.h>
|
||||||
|
#include <video_bridge.h>
|
||||||
|
#include <linux/delay.h>
|
||||||
|
#include <linux/err.h>
|
||||||
|
#include <asm/gpio.h>
|
||||||
|
#include <asm/io.h>
|
||||||
|
|
||||||
|
#include "dc.h"
|
||||||
|
|
||||||
|
struct tegra_cpu_bridge_priv {
|
||||||
|
struct dc_ctlr *dc;
|
||||||
|
|
||||||
|
struct mipi_dsi_host host;
|
||||||
|
struct mipi_dsi_device device;
|
||||||
|
|
||||||
|
struct udevice *panel;
|
||||||
|
struct display_timing timing;
|
||||||
|
|
||||||
|
struct gpio_desc dc_gpio;
|
||||||
|
struct gpio_desc rw_gpio;
|
||||||
|
struct gpio_desc cs_gpio;
|
||||||
|
|
||||||
|
struct gpio_desc data_gpios[8];
|
||||||
|
|
||||||
|
u32 pixel_format;
|
||||||
|
u32 spi_init_seq[4];
|
||||||
|
};
|
||||||
|
|
||||||
|
#define TEGRA_CPU_BRIDGE_COMM 0
|
||||||
|
#define TEGRA_CPU_BRIDGE_DATA 1
|
||||||
|
|
||||||
|
static void tegra_cpu_bridge_write(struct tegra_cpu_bridge_priv *priv,
|
||||||
|
u8 type, u8 value)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
dm_gpio_set_value(&priv->dc_gpio, type);
|
||||||
|
|
||||||
|
dm_gpio_set_value(&priv->cs_gpio, 0);
|
||||||
|
dm_gpio_set_value(&priv->rw_gpio, 0);
|
||||||
|
|
||||||
|
for (i = 0; i < 8; i++)
|
||||||
|
dm_gpio_set_value(&priv->data_gpios[i],
|
||||||
|
(value >> i) & 0x1);
|
||||||
|
|
||||||
|
dm_gpio_set_value(&priv->cs_gpio, 1);
|
||||||
|
dm_gpio_set_value(&priv->rw_gpio, 1);
|
||||||
|
|
||||||
|
udelay(10);
|
||||||
|
|
||||||
|
log_debug("%s: type 0x%x, val 0x%x\n",
|
||||||
|
__func__, type, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
static ssize_t tegra_cpu_bridge_transfer(struct mipi_dsi_host *host,
|
||||||
|
const struct mipi_dsi_msg *msg)
|
||||||
|
{
|
||||||
|
struct udevice *dev = (struct udevice *)host->dev;
|
||||||
|
struct tegra_cpu_bridge_priv *priv = dev_get_priv(dev);
|
||||||
|
u8 command = *(u8 *)msg->tx_buf;
|
||||||
|
const u8 *data = msg->tx_buf;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
tegra_cpu_bridge_write(priv, TEGRA_CPU_BRIDGE_COMM, command);
|
||||||
|
|
||||||
|
for (i = 1; i < msg->tx_len; i++)
|
||||||
|
tegra_cpu_bridge_write(priv, TEGRA_CPU_BRIDGE_DATA, data[i]);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct mipi_dsi_host_ops tegra_cpu_bridge_host_ops = {
|
||||||
|
.transfer = tegra_cpu_bridge_transfer,
|
||||||
|
};
|
||||||
|
|
||||||
|
static int tegra_cpu_bridge_get_format(enum mipi_dsi_pixel_format format, u32 *fmt)
|
||||||
|
{
|
||||||
|
switch (format) {
|
||||||
|
case MIPI_DSI_FMT_RGB888:
|
||||||
|
case MIPI_DSI_FMT_RGB666_PACKED:
|
||||||
|
*fmt = BASE_COLOR_SIZE_888;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case MIPI_DSI_FMT_RGB666:
|
||||||
|
*fmt = BASE_COLOR_SIZE_666;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case MIPI_DSI_FMT_RGB565:
|
||||||
|
*fmt = BASE_COLOR_SIZE_565;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int tegra_cpu_bridge_attach(struct udevice *dev)
|
||||||
|
{
|
||||||
|
struct tegra_cpu_bridge_priv *priv = dev_get_priv(dev);
|
||||||
|
struct dc_disp_reg *disp = &priv->dc->disp;
|
||||||
|
struct dc_cmd_reg *cmd = &priv->dc->cmd;
|
||||||
|
struct dc_com_reg *com = &priv->dc->com;
|
||||||
|
u32 value;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
writel(CTRL_MODE_STOP << CTRL_MODE_SHIFT, &cmd->disp_cmd);
|
||||||
|
writel(0, &disp->disp_win_opt);
|
||||||
|
writel(GENERAL_UPDATE, &cmd->state_ctrl);
|
||||||
|
writel(GENERAL_ACT_REQ, &cmd->state_ctrl);
|
||||||
|
|
||||||
|
/* TODO: parametrize if needed */
|
||||||
|
writel(V_PULSE1_ENABLE, &disp->disp_signal_opt0);
|
||||||
|
writel(PULSE_POLARITY_LOW, &disp->v_pulse1.v_pulse_ctrl);
|
||||||
|
|
||||||
|
writel(PULSE_END(1), &disp->v_pulse1.v_pulse_pos[V_PULSE0_POSITION_A]);
|
||||||
|
writel(0, &disp->v_pulse1.v_pulse_pos[V_PULSE0_POSITION_B]);
|
||||||
|
writel(0, &disp->v_pulse1.v_pulse_pos[V_PULSE0_POSITION_C]);
|
||||||
|
|
||||||
|
ret = dev_read_u32_array(dev, "nvidia,init-sequence", priv->spi_init_seq, 4);
|
||||||
|
if (!ret) {
|
||||||
|
value = 1 << FRAME_INIT_SEQ_CYCLES_SHIFT |
|
||||||
|
DC_SIGNAL_VPULSE1 << INIT_SEQ_DC_SIGNAL_SHIFT |
|
||||||
|
INIT_SEQUENCE_MODE_PLCD | SEND_INIT_SEQUENCE;
|
||||||
|
writel(value, &disp->seq_ctrl);
|
||||||
|
|
||||||
|
writel(priv->spi_init_seq[0], &disp->spi_init_seq_data_a);
|
||||||
|
writel(priv->spi_init_seq[1], &disp->spi_init_seq_data_b);
|
||||||
|
writel(priv->spi_init_seq[2], &disp->spi_init_seq_data_c);
|
||||||
|
writel(priv->spi_init_seq[3], &disp->spi_init_seq_data_d);
|
||||||
|
}
|
||||||
|
|
||||||
|
value = readl(&cmd->disp_cmd);
|
||||||
|
value &= ~CTRL_MODE_MASK;
|
||||||
|
value |= CTRL_MODE_C_DISPLAY << CTRL_MODE_SHIFT;
|
||||||
|
writel(value, &cmd->disp_cmd);
|
||||||
|
|
||||||
|
/* set LDC pin to V Pulse 1 */
|
||||||
|
value = readl(&com->pin_output_sel[6]) | LDC_OUTPUT_SELECT_V_PULSE1;
|
||||||
|
writel(value, &com->pin_output_sel[6]);
|
||||||
|
|
||||||
|
value = readl(&disp->disp_interface_ctrl);
|
||||||
|
value |= DATA_ALIGNMENT_LSB << DATA_ALIGNMENT_SHIFT;
|
||||||
|
writel(value, &disp->disp_interface_ctrl);
|
||||||
|
|
||||||
|
value = SC_H_QUALIFIER_NONE << SC1_H_QUALIFIER_SHIFT |
|
||||||
|
SC_V_QUALIFIER_VACTIVE << SC0_V_QUALIFIER_SHIFT |
|
||||||
|
SC_H_QUALIFIER_HACTIVE << SC0_H_QUALIFIER_SHIFT;
|
||||||
|
writel(value, &disp->shift_clk_opt);
|
||||||
|
|
||||||
|
value = readl(&disp->disp_color_ctrl);
|
||||||
|
value |= priv->pixel_format;
|
||||||
|
writel(value, &disp->disp_color_ctrl);
|
||||||
|
|
||||||
|
/* Perform panel setup */
|
||||||
|
panel_enable_backlight(priv->panel);
|
||||||
|
|
||||||
|
dm_gpio_set_value(&priv->cs_gpio, 0);
|
||||||
|
|
||||||
|
dm_gpio_free(dev, &priv->dc_gpio);
|
||||||
|
dm_gpio_free(dev, &priv->rw_gpio);
|
||||||
|
dm_gpio_free(dev, &priv->cs_gpio);
|
||||||
|
|
||||||
|
gpio_free_list(dev, priv->data_gpios, 8);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int tegra_cpu_bridge_set_panel(struct udevice *dev, int percent)
|
||||||
|
{
|
||||||
|
struct tegra_cpu_bridge_priv *priv = dev_get_priv(dev);
|
||||||
|
|
||||||
|
return panel_set_backlight(priv->panel, percent);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int tegra_cpu_bridge_panel_timings(struct udevice *dev,
|
||||||
|
struct display_timing *timing)
|
||||||
|
{
|
||||||
|
struct tegra_cpu_bridge_priv *priv = dev_get_priv(dev);
|
||||||
|
|
||||||
|
memcpy(timing, &priv->timing, sizeof(*timing));
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int tegra_cpu_bridge_hw_init(struct udevice *dev)
|
||||||
|
{
|
||||||
|
struct tegra_cpu_bridge_priv *priv = dev_get_priv(dev);
|
||||||
|
|
||||||
|
dm_gpio_set_value(&priv->cs_gpio, 1);
|
||||||
|
|
||||||
|
dm_gpio_set_value(&priv->rw_gpio, 1);
|
||||||
|
dm_gpio_set_value(&priv->dc_gpio, 0);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int tegra_cpu_bridge_get_links(struct udevice *dev)
|
||||||
|
{
|
||||||
|
struct tegra_cpu_bridge_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);
|
||||||
|
|
||||||
|
/* Look for DC source */
|
||||||
|
if (ofnode_name_eq(remote, "rgb")) {
|
||||||
|
ofnode dc = ofnode_get_parent(remote);
|
||||||
|
|
||||||
|
priv->dc = (struct dc_ctlr *)ofnode_get_addr(dc);
|
||||||
|
if (!priv->dc) {
|
||||||
|
log_err("%s: failed to get DC controller\n", __func__);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Look for driven panel */
|
||||||
|
ret = uclass_get_device_by_ofnode(UCLASS_PANEL, remote, &priv->panel);
|
||||||
|
if (!ret)
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If this point is reached, no panels were found */
|
||||||
|
return -ENODEV;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int tegra_cpu_bridge_probe(struct udevice *dev)
|
||||||
|
{
|
||||||
|
struct tegra_cpu_bridge_priv *priv = dev_get_priv(dev);
|
||||||
|
struct mipi_dsi_device *device = &priv->device;
|
||||||
|
struct mipi_dsi_panel_plat *mipi_plat;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
ret = tegra_cpu_bridge_get_links(dev);
|
||||||
|
if (ret) {
|
||||||
|
log_debug("%s: links not found, ret %d\n", __func__, ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
panel_get_display_timing(priv->panel, &priv->timing);
|
||||||
|
|
||||||
|
mipi_plat = dev_get_plat(priv->panel);
|
||||||
|
mipi_plat->device = device;
|
||||||
|
|
||||||
|
priv->host.dev = (struct device *)dev;
|
||||||
|
priv->host.ops = &tegra_cpu_bridge_host_ops;
|
||||||
|
|
||||||
|
device->host = &priv->host;
|
||||||
|
device->lanes = mipi_plat->lanes;
|
||||||
|
device->format = mipi_plat->format;
|
||||||
|
device->mode_flags = mipi_plat->mode_flags;
|
||||||
|
|
||||||
|
tegra_cpu_bridge_get_format(device->format, &priv->pixel_format);
|
||||||
|
|
||||||
|
/* get control gpios */
|
||||||
|
ret = gpio_request_by_name(dev, "dc-gpios", 0,
|
||||||
|
&priv->dc_gpio, GPIOD_IS_OUT);
|
||||||
|
if (ret) {
|
||||||
|
log_debug("%s: could not decode dc-gpios (%d)\n", __func__, ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = gpio_request_by_name(dev, "rw-gpios", 0,
|
||||||
|
&priv->rw_gpio, GPIOD_IS_OUT);
|
||||||
|
if (ret) {
|
||||||
|
log_debug("%s: could not decode rw-gpios (%d)\n", __func__, ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = gpio_request_by_name(dev, "cs-gpios", 0,
|
||||||
|
&priv->cs_gpio, GPIOD_IS_OUT);
|
||||||
|
if (ret) {
|
||||||
|
log_debug("%s: could not decode cs-gpios (%d)\n", __func__, ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* get data gpios */
|
||||||
|
ret = gpio_request_list_by_name(dev, "data-gpios",
|
||||||
|
priv->data_gpios, 8,
|
||||||
|
GPIOD_IS_OUT);
|
||||||
|
if (ret < 0) {
|
||||||
|
log_debug("%s: could not decode data-gpios (%d)\n", __func__, ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
return tegra_cpu_bridge_hw_init(dev);
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct video_bridge_ops tegra_cpu_bridge_ops = {
|
||||||
|
.attach = tegra_cpu_bridge_attach,
|
||||||
|
.set_backlight = tegra_cpu_bridge_set_panel,
|
||||||
|
.get_display_timing = tegra_cpu_bridge_panel_timings,
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct udevice_id tegra_cpu_bridge_ids[] = {
|
||||||
|
{ .compatible = "nvidia,tegra-8bit-cpu" },
|
||||||
|
{ }
|
||||||
|
};
|
||||||
|
|
||||||
|
U_BOOT_DRIVER(tegra_8bit_cpu) = {
|
||||||
|
.name = "tegra_8bit_cpu",
|
||||||
|
.id = UCLASS_VIDEO_BRIDGE,
|
||||||
|
.of_match = tegra_cpu_bridge_ids,
|
||||||
|
.ops = &tegra_cpu_bridge_ops,
|
||||||
|
.bind = dm_scan_fdt_dev,
|
||||||
|
.probe = tegra_cpu_bridge_probe,
|
||||||
|
.priv_auto = sizeof(struct tegra_cpu_bridge_priv),
|
||||||
|
};
|
Reference in New Issue
Block a user