From eb65c25b611887ed57ec38ef8f61af80e76b7beb Mon Sep 17 00:00:00 2001 From: Svyatoslav Ryhel Date: Fri, 28 Feb 2025 20:02:23 +0200 Subject: [PATCH 01/47] video: tegra20: implement a minimal HOST1X driver for essential clock and reset setup Introduce a simplified HOST1X driver, limited to the basic clock and reset initialization of the bus. Signed-off-by: Svyatoslav Ryhel --- drivers/video/tegra20/Kconfig | 5 ++ drivers/video/tegra20/Makefile | 1 + drivers/video/tegra20/tegra-dc.c | 5 -- drivers/video/tegra20/tegra-host1x.c | 86 ++++++++++++++++++++++++++++ 4 files changed, 92 insertions(+), 5 deletions(-) create mode 100644 drivers/video/tegra20/tegra-host1x.c diff --git a/drivers/video/tegra20/Kconfig b/drivers/video/tegra20/Kconfig index f5c4843e119..d7c402e95fd 100644 --- a/drivers/video/tegra20/Kconfig +++ b/drivers/video/tegra20/Kconfig @@ -1,6 +1,11 @@ +config HOST1X_TEGRA + bool "NVIDIA Tegra host1x BUS support" + depends on SIMPLE_BUS + config VIDEO_TEGRA20 bool "Enable Display Controller support on Tegra20 and Tegra 30" depends on OF_CONTROL + select HOST1X_TEGRA help T20/T30 support video output to an attached LCD panel as well as other options such as HDMI. Only the LCD is supported in U-Boot. diff --git a/drivers/video/tegra20/Makefile b/drivers/video/tegra20/Makefile index a75aea2a875..c0fd42a72d5 100644 --- a/drivers/video/tegra20/Makefile +++ b/drivers/video/tegra20/Makefile @@ -1,5 +1,6 @@ # SPDX-License-Identifier: GPL-2.0+ +obj-$(CONFIG_HOST1X_TEGRA) += tegra-host1x.o obj-$(CONFIG_VIDEO_TEGRA20) += tegra-dc.o obj-$(CONFIG_VIDEO_DSI_TEGRA30) += tegra-dsi.o tegra-mipi.o mipi-phy.o obj-$(CONFIG_TEGRA_BACKLIGHT_PWM) += tegra-pwm-backlight.o diff --git a/drivers/video/tegra20/tegra-dc.c b/drivers/video/tegra20/tegra-dc.c index 16a2b5281bf..001967f2a5a 100644 --- a/drivers/video/tegra20/tegra-dc.c +++ b/drivers/video/tegra20/tegra-dc.c @@ -319,11 +319,6 @@ static int tegra_display_probe(struct tegra_lcd_priv *priv, / priv->pixel_clock) - 2; log_debug("Display clock %lu, divider %lu\n", rate, priv->scdiv); - /* - * HOST1X is init by default at 150MHz with PLLC as parent - */ - clock_start_periph_pll(PERIPH_ID_HOST1X, CLOCK_ID_CGENERAL, - 150 * 1000000); clock_start_periph_pll(priv->clk->id, priv->clk_parent->id, rate); diff --git a/drivers/video/tegra20/tegra-host1x.c b/drivers/video/tegra20/tegra-host1x.c new file mode 100644 index 00000000000..58ab871a3b4 --- /dev/null +++ b/drivers/video/tegra20/tegra-host1x.c @@ -0,0 +1,86 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (c) 2025 Svyatoslav Ryhel + */ + +#include +#include +#include +#include +#include + +#include +#include + +struct tegra_host1x_info { + u32 clk_parent; + u32 rate; +}; + +static int tegra_host1x_probe(struct udevice *dev) +{ + struct clk *clk; + struct reset_ctl reset_ctl; + const struct tegra_host1x_info *info; + int ret; + + clk = devm_clk_get(dev, NULL); + if (IS_ERR(clk)) { + log_debug("%s: cannot get HOST1X clock: %ld\n", + __func__, PTR_ERR(clk)); + return PTR_ERR(clk); + } + + ret = reset_get_by_name(dev, "host1x", &reset_ctl); + if (ret) { + log_debug("%s: cannot get HOST1X reset: %d\n", + __func__, ret); + return ret; + } + + info = (struct tegra_host1x_info *)dev_get_driver_data(dev); + + reset_assert(&reset_ctl); + clock_start_periph_pll(clk->id, info->clk_parent, info->rate); + + mdelay(2); + reset_deassert(&reset_ctl); + + return 0; +} + +static const struct tegra_host1x_info tegra20_host1x_info = { + .clk_parent = CLOCK_ID_CGENERAL, + .rate = 150000000, /* 150 MHz */ +}; + +static const struct tegra_host1x_info tegra114_host1x_info = { + .clk_parent = CLOCK_ID_PERIPH, + .rate = 136000000, /* 136 MHz */ +}; + +static const struct udevice_id tegra_host1x_ids[] = { + { + .compatible = "nvidia,tegra20-host1x", + .data = (ulong)&tegra20_host1x_info + }, { + .compatible = "nvidia,tegra30-host1x", + .data = (ulong)&tegra20_host1x_info + }, { + .compatible = "nvidia,tegra114-host1x", + .data = (ulong)&tegra114_host1x_info + }, { + .compatible = "nvidia,tegra124-host1x", + .data = (ulong)&tegra114_host1x_info + }, { + /* sentinel */ + } +}; + +U_BOOT_DRIVER(tegra_host1x) = { + .name = "tegra_host1x", + .id = UCLASS_SIMPLE_BUS, + .of_match = tegra_host1x_ids, + .probe = tegra_host1x_probe, + .flags = DM_FLAG_PRE_RELOC, +}; From 2dd1092ab8872fc535369e4f29afad0e8d9d0d6d Mon Sep 17 00:00:00 2001 From: Svyatoslav Ryhel Date: Thu, 22 Jun 2023 20:46:00 +0300 Subject: [PATCH 02/47] video: tegra20: provide driver support for the HDMI controller MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Tegra platforms feature native HDMI support. Implement a driver to enable functionality. This driver will initially support Tegra 2 and 3, with future extensibility. Co-developed-by: Jonas Schwöbel Signed-off-by: Jonas Schwöbel Signed-off-by: Svyatoslav Ryhel --- arch/arm/include/asm/arch-tegra/dc.h | 46 +- drivers/video/tegra20/Kconfig | 9 + drivers/video/tegra20/Makefile | 1 + drivers/video/tegra20/tegra-hdmi.c | 623 +++++++++++++++++++++++++ drivers/video/tegra20/tegra-hdmi.h | 648 +++++++++++++++++++++++++++ 5 files changed, 1324 insertions(+), 3 deletions(-) create mode 100644 drivers/video/tegra20/tegra-hdmi.c create mode 100644 drivers/video/tegra20/tegra-hdmi.h diff --git a/arch/arm/include/asm/arch-tegra/dc.h b/arch/arm/include/asm/arch-tegra/dc.h index ca3718411ab..2fd07403bdf 100644 --- a/arch/arm/include/asm/arch-tegra/dc.h +++ b/arch/arm/include/asm/arch-tegra/dc.h @@ -448,6 +448,11 @@ enum win_color_depth_id { #define LVS_OUTPUT_POLARITY_LOW BIT(28) #define LSC0_OUTPUT_POLARITY_LOW BIT(24) +/* DC_DISP_DISP_SIGNAL_OPTIONS0 0x400 */ +#define H_PULSE0_ENABLE BIT(8) +#define H_PULSE1_ENABLE BIT(10) +#define H_PULSE2_ENABLE BIT(12) + /* DC_DISP_DISP_WIN_OPTIONS 0x402 */ #define CURSOR_ENABLE BIT(16) #define SOR_ENABLE BIT(25) @@ -504,6 +509,22 @@ enum { DATA_ORDER_BLUE_RED, }; +/* DC_DISP_DISP_COLOR_CONTROL 0x430 */ +#define DITHER_CONTROL_DISABLE (0 << 8) +#define DITHER_CONTROL_ORDERED (2 << 8) +#define DITHER_CONTROL_ERRDIFF (3 << 8) +enum { + BASE_COLOR_SIZE_666, + BASE_COLOR_SIZE_111, + BASE_COLOR_SIZE_222, + BASE_COLOR_SIZE_333, + BASE_COLOR_SIZE_444, + BASE_COLOR_SIZE_555, + BASE_COLOR_SIZE_565, + BASE_COLOR_SIZE_332, + BASE_COLOR_SIZE_888, +}; + /* DC_DISP_DATA_ENABLE_OPTIONS 0x432 */ #define DE_SELECT_SHIFT 0 #define DE_SELECT_MASK (0x3 << DE_SELECT_SHIFT) @@ -570,8 +591,27 @@ enum { #define V_DDA_INC_SHIFT 16 #define V_DDA_INC_MASK (0xFFFF << V_DDA_INC_SHIFT) -#define DC_POLL_TIMEOUT_MS 50 -#define DC_N_WINDOWS 5 -#define DC_REG_SAVE_SPACE (DC_N_WINDOWS + 5) +#define DC_POLL_TIMEOUT_MS 50 +#define DC_N_WINDOWS 5 +#define DC_REG_SAVE_SPACE (DC_N_WINDOWS + 5) + +#define PULSE_MODE_NORMAL (0 << 3) +#define PULSE_MODE_ONE_CLOCK (1 << 3) +#define PULSE_POLARITY_HIGH (0 << 4) +#define PULSE_POLARITY_LOW (1 << 4) +#define PULSE_QUAL_ALWAYS (0 << 6) +#define PULSE_QUAL_VACTIVE (2 << 6) +#define PULSE_QUAL_VACTIVE1 (3 << 6) +#define PULSE_LAST_START_A (0 << 8) +#define PULSE_LAST_END_A (1 << 8) +#define PULSE_LAST_START_B (2 << 8) +#define PULSE_LAST_END_B (3 << 8) +#define PULSE_LAST_START_C (4 << 8) +#define PULSE_LAST_END_C (5 << 8) +#define PULSE_LAST_START_D (6 << 8) +#define PULSE_LAST_END_D (7 << 8) + +#define PULSE_START(x) (((x) & 0xfff) << 0) +#define PULSE_END(x) (((x) & 0xfff) << 16) #endif /* __ASM_ARCH_TEGRA_DC_H */ diff --git a/drivers/video/tegra20/Kconfig b/drivers/video/tegra20/Kconfig index d7c402e95fd..ce990b4481f 100644 --- a/drivers/video/tegra20/Kconfig +++ b/drivers/video/tegra20/Kconfig @@ -21,6 +21,15 @@ config VIDEO_DSI_TEGRA30 T30 has native support for DSI panels. This option enables support for such panels which can be used on endeavoru and tf600t. +config VIDEO_HDMI_TEGRA + bool "Enable Tegra HDMI support" + depends on VIDEO_BRIDGE && DM_I2C + select I2C_EDID + select VIDEO_TEGRA20 + help + Tegra has native support for HDMI. This option enables support + for such connection and can be used for any supported device. + config TEGRA_BACKLIGHT_PWM bool "Enable Tegra DC PWM backlight support" depends on BACKLIGHT diff --git a/drivers/video/tegra20/Makefile b/drivers/video/tegra20/Makefile index c0fd42a72d5..78521405749 100644 --- a/drivers/video/tegra20/Makefile +++ b/drivers/video/tegra20/Makefile @@ -3,4 +3,5 @@ obj-$(CONFIG_HOST1X_TEGRA) += tegra-host1x.o obj-$(CONFIG_VIDEO_TEGRA20) += tegra-dc.o obj-$(CONFIG_VIDEO_DSI_TEGRA30) += tegra-dsi.o tegra-mipi.o mipi-phy.o +obj-$(CONFIG_VIDEO_HDMI_TEGRA) += tegra-hdmi.o obj-$(CONFIG_TEGRA_BACKLIGHT_PWM) += tegra-pwm-backlight.o diff --git a/drivers/video/tegra20/tegra-hdmi.c b/drivers/video/tegra20/tegra-hdmi.c new file mode 100644 index 00000000000..bda69919d92 --- /dev/null +++ b/drivers/video/tegra20/tegra-hdmi.c @@ -0,0 +1,623 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2013 NVIDIA Corporation + * Copyright (c) 2023 Svyatoslav Ryhel + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "tegra-dc.h" +#include "tegra-hdmi.h" + +#define DDCCI_ENTRY_ADDR 0x37 +#define DDCCI_SOURSE_ADDR 0x51 +#define DDCCI_COMMAND_WRITE 0x03 +#define DDCCI_CTRL_BRIGHTNESS 0x10 + +#define HDMI_EDID_I2C_ADDR 0x50 +#define HDMI_REKEY_DEFAULT 56 + +static const char * const hdmi_supplies[] = { + "hdmi-supply", "pll-supply", "vdd-supply" +}; + +struct tmds_config { + unsigned int pclk; + u32 pll0; + u32 pll1; + u32 pe_current; + u32 drive_current; + u32 peak_current; +}; + +struct tegra_hdmi_config { + const struct tmds_config *tmds; + unsigned int num_tmds; + unsigned int max_pclk; + + /* to be filled */ +}; + +struct tegra_hdmi_priv { + struct hdmi_ctlr *hdmi_regmap; + + struct udevice *supplies[ARRAY_SIZE(hdmi_supplies)]; + struct udevice *hdmi_ddc; + + struct gpio_desc hpd; /* hotplug detection gpio */ + struct display_timing timing; + + struct clk *clk; + struct clk *clk_parent; + + int panel_bits_per_colourp; + const struct tegra_hdmi_config *config; +}; + +/* 1280x720p 60hz: EIA/CEA-861-B Format 4 */ +static struct display_timing default_720p_timing = { + .pixelclock.typ = 74250000, + .hactive.typ = 1280, + .hfront_porch.typ = 110, + .hback_porch.typ = 220, + .hsync_len.typ = 40, + .vactive.typ = 720, + .vfront_porch.typ = 5, + .vback_porch.typ = 20, + .vsync_len.typ = 5, + .flags = DISPLAY_FLAGS_HSYNC_HIGH | + DISPLAY_FLAGS_VSYNC_HIGH, +}; + +static const struct tmds_config tegra20_tmds_config[] = { + { /* slow pixel clock modes */ + .pclk = 27000000, + .pll0 = SOR_PLL_BG_V17_S(3) | SOR_PLL_ICHPMP(1) | + SOR_PLL_RESISTORSEL | SOR_PLL_VCOCAP(0) | + SOR_PLL_TX_REG_LOAD(3), + .pll1 = SOR_PLL_TMDS_TERM_ENABLE, + .pe_current = PE_CURRENT0(PE_CURRENT_0_0_mA) | + PE_CURRENT1(PE_CURRENT_0_0_mA) | + PE_CURRENT2(PE_CURRENT_0_0_mA) | + PE_CURRENT3(PE_CURRENT_0_0_mA), + .drive_current = DRIVE_CURRENT_LANE0(DRIVE_CURRENT_7_125_mA) | + DRIVE_CURRENT_LANE1(DRIVE_CURRENT_7_125_mA) | + DRIVE_CURRENT_LANE2(DRIVE_CURRENT_7_125_mA) | + DRIVE_CURRENT_LANE3(DRIVE_CURRENT_7_125_mA), + }, + { /* high pixel clock modes */ + .pclk = UINT_MAX, + .pll0 = SOR_PLL_BG_V17_S(3) | SOR_PLL_ICHPMP(1) | + SOR_PLL_RESISTORSEL | SOR_PLL_VCOCAP(1) | + SOR_PLL_TX_REG_LOAD(3), + .pll1 = SOR_PLL_TMDS_TERM_ENABLE | SOR_PLL_PE_EN, + .pe_current = PE_CURRENT0(PE_CURRENT_6_0_mA) | + PE_CURRENT1(PE_CURRENT_6_0_mA) | + PE_CURRENT2(PE_CURRENT_6_0_mA) | + PE_CURRENT3(PE_CURRENT_6_0_mA), + .drive_current = DRIVE_CURRENT_LANE0(DRIVE_CURRENT_7_125_mA) | + DRIVE_CURRENT_LANE1(DRIVE_CURRENT_7_125_mA) | + DRIVE_CURRENT_LANE2(DRIVE_CURRENT_7_125_mA) | + DRIVE_CURRENT_LANE3(DRIVE_CURRENT_7_125_mA), + }, +}; + +static const struct tmds_config tegra30_tmds_config[] = { + { /* 480p modes */ + .pclk = 27000000, + .pll0 = SOR_PLL_BG_V17_S(3) | SOR_PLL_ICHPMP(1) | + SOR_PLL_RESISTORSEL | SOR_PLL_VCOCAP(0) | + SOR_PLL_TX_REG_LOAD(0), + .pll1 = SOR_PLL_TMDS_TERM_ENABLE, + .pe_current = PE_CURRENT0(PE_CURRENT_0_0_mA) | + PE_CURRENT1(PE_CURRENT_0_0_mA) | + PE_CURRENT2(PE_CURRENT_0_0_mA) | + PE_CURRENT3(PE_CURRENT_0_0_mA), + .drive_current = DRIVE_CURRENT_LANE0(DRIVE_CURRENT_5_250_mA) | + DRIVE_CURRENT_LANE1(DRIVE_CURRENT_5_250_mA) | + DRIVE_CURRENT_LANE2(DRIVE_CURRENT_5_250_mA) | + DRIVE_CURRENT_LANE3(DRIVE_CURRENT_5_250_mA), + }, { /* 720p modes */ + .pclk = 74250000, + .pll0 = SOR_PLL_BG_V17_S(3) | SOR_PLL_ICHPMP(1) | + SOR_PLL_RESISTORSEL | SOR_PLL_VCOCAP(1) | + SOR_PLL_TX_REG_LOAD(0), + .pll1 = SOR_PLL_TMDS_TERM_ENABLE | SOR_PLL_PE_EN, + .pe_current = PE_CURRENT0(PE_CURRENT_5_0_mA) | + PE_CURRENT1(PE_CURRENT_5_0_mA) | + PE_CURRENT2(PE_CURRENT_5_0_mA) | + PE_CURRENT3(PE_CURRENT_5_0_mA), + .drive_current = DRIVE_CURRENT_LANE0(DRIVE_CURRENT_5_250_mA) | + DRIVE_CURRENT_LANE1(DRIVE_CURRENT_5_250_mA) | + DRIVE_CURRENT_LANE2(DRIVE_CURRENT_5_250_mA) | + DRIVE_CURRENT_LANE3(DRIVE_CURRENT_5_250_mA), + }, { /* 1080p modes */ + .pclk = UINT_MAX, + .pll0 = SOR_PLL_BG_V17_S(3) | SOR_PLL_ICHPMP(1) | + SOR_PLL_RESISTORSEL | SOR_PLL_VCOCAP(3) | + SOR_PLL_TX_REG_LOAD(0), + .pll1 = SOR_PLL_TMDS_TERM_ENABLE | SOR_PLL_PE_EN, + .pe_current = PE_CURRENT0(PE_CURRENT_5_0_mA) | + PE_CURRENT1(PE_CURRENT_5_0_mA) | + PE_CURRENT2(PE_CURRENT_5_0_mA) | + PE_CURRENT3(PE_CURRENT_5_0_mA), + .drive_current = DRIVE_CURRENT_LANE0(DRIVE_CURRENT_5_250_mA) | + DRIVE_CURRENT_LANE1(DRIVE_CURRENT_5_250_mA) | + DRIVE_CURRENT_LANE2(DRIVE_CURRENT_5_250_mA) | + DRIVE_CURRENT_LANE3(DRIVE_CURRENT_5_250_mA), + }, +}; + +static void tegra_dc_enable_controller(struct udevice *dev) +{ + struct tegra_dc_plat *dc_plat = dev_get_plat(dev); + struct dc_ctlr *dc = dc_plat->dc; + u32 value; + + value = readl(&dc->disp.disp_win_opt); + value |= HDMI_ENABLE; + writel(value, &dc->disp.disp_win_opt); + + writel(GENERAL_UPDATE, &dc->cmd.state_ctrl); + writel(GENERAL_ACT_REQ, &dc->cmd.state_ctrl); +} + +static void tegra_hdmi_setup_tmds(struct tegra_hdmi_priv *priv, + const struct tmds_config *tmds) +{ + struct hdmi_ctlr *hdmi = priv->hdmi_regmap; + u32 value; + + writel(tmds->pll0, &hdmi->nv_pdisp_sor_pll0); + writel(tmds->pll1, &hdmi->nv_pdisp_sor_pll1); + writel(tmds->pe_current, &hdmi->nv_pdisp_pe_current); + + writel(tmds->drive_current, &hdmi->nv_pdisp_sor_lane_drive_current); + + value = readl(&hdmi->nv_pdisp_sor_lane_drive_current); + value |= BIT(31); + writel(value, &hdmi->nv_pdisp_sor_lane_drive_current); +} + +static int tegra_hdmi_encoder_enable(struct udevice *dev) +{ + struct tegra_dc_plat *dc_plat = dev_get_plat(dev); + struct tegra_hdmi_priv *priv = dev_get_priv(dev); + struct dc_ctlr *dc = dc_plat->dc; + struct display_timing *dt = &priv->timing; + struct hdmi_ctlr *hdmi = priv->hdmi_regmap; + unsigned long rate, div82; + unsigned int pulse_start, rekey; + int retries = 1000; + u32 value; + int i; + + /* power up sequence */ + value = readl(&hdmi->nv_pdisp_sor_pll0); + value &= ~SOR_PLL_PDBG; + writel(value, &hdmi->nv_pdisp_sor_pll0); + + udelay(20); + + value = readl(&hdmi->nv_pdisp_sor_pll0); + value &= ~SOR_PLL_PWR; + writel(value, &hdmi->nv_pdisp_sor_pll0); + + writel(VSYNC_H_POSITION(1), &dc->disp.disp_timing_opt); + writel(DITHER_CONTROL_DISABLE | BASE_COLOR_SIZE_888, + &dc->disp.disp_color_ctrl); + + /* video_preamble uses h_pulse2 */ + pulse_start = 1 + dt->hsync_len.typ + dt->hback_porch.typ - 10; + + writel(H_PULSE2_ENABLE, &dc->disp.disp_signal_opt0); + + value = PULSE_MODE_NORMAL | PULSE_POLARITY_HIGH | + PULSE_QUAL_VACTIVE | PULSE_LAST_END_A; + writel(value, &dc->disp.h_pulse[H_PULSE2].h_pulse_ctrl); + + value = PULSE_START(pulse_start) | PULSE_END(pulse_start + 8); + writel(value, &dc->disp.h_pulse[H_PULSE2].h_pulse_pos[H_PULSE0_POSITION_A]); + + value = VSYNC_WINDOW_END(0x210) | VSYNC_WINDOW_START(0x200) | + VSYNC_WINDOW_ENABLE; + writel(value, &hdmi->nv_pdisp_hdmi_vsync_window); + + if (dc_plat->pipe) + value = HDMI_SRC_DISPLAYB; + else + value = HDMI_SRC_DISPLAYA; + + if (dt->hactive.typ == 720 && (dt->vactive.typ == 480 || + dt->vactive.typ == 576)) + writel(value | ARM_VIDEO_RANGE_FULL, + &hdmi->nv_pdisp_input_control); + else + writel(value | ARM_VIDEO_RANGE_LIMITED, + &hdmi->nv_pdisp_input_control); + + rate = clock_get_periph_rate(priv->clk->id, priv->clk_parent->id); + div82 = rate / USEC_PER_SEC * 4; + value = SOR_REFCLK_DIV_INT(div82 >> 2) | SOR_REFCLK_DIV_FRAC(div82); + writel(value, &hdmi->nv_pdisp_sor_refclk); + + rekey = HDMI_REKEY_DEFAULT; + value = HDMI_CTRL_REKEY(rekey); + value |= HDMI_CTRL_MAX_AC_PACKET((dt->hsync_len.typ + dt->hback_porch.typ + + dt->hfront_porch.typ - rekey - 18) / 32); + writel(value, &hdmi->nv_pdisp_hdmi_ctrl); + + /* TMDS CONFIG */ + for (i = 0; i < priv->config->num_tmds; i++) { + if (dt->pixelclock.typ <= priv->config->tmds[i].pclk) { + tegra_hdmi_setup_tmds(priv, &priv->config->tmds[i]); + break; + } + } + + writel(SOR_SEQ_PU_PC(0) | SOR_SEQ_PU_PC_ALT(0) | SOR_SEQ_PD_PC(8) | + SOR_SEQ_PD_PC_ALT(8), &hdmi->nv_pdisp_sor_seq_ctl); + + value = SOR_SEQ_INST_WAIT_TIME(1) | SOR_SEQ_INST_WAIT_UNITS_VSYNC | + SOR_SEQ_INST_HALT | SOR_SEQ_INST_PIN_A_LOW | + SOR_SEQ_INST_PIN_B_LOW | SOR_SEQ_INST_DRIVE_PWM_OUT_LO; + + writel(value, &hdmi->nv_pdisp_sor_seq_inst0); + writel(value, &hdmi->nv_pdisp_sor_seq_inst8); + + value = readl(&hdmi->nv_pdisp_sor_cstm); + + value &= ~SOR_CSTM_ROTCLK(~0); + value |= SOR_CSTM_ROTCLK(2); + value |= SOR_CSTM_PLLDIV; + value &= ~SOR_CSTM_LVDS_ENABLE; + value &= ~SOR_CSTM_MODE_MASK; + value |= SOR_CSTM_MODE_TMDS; + + writel(value, &hdmi->nv_pdisp_sor_cstm); + + /* start SOR */ + writel(SOR_PWR_NORMAL_STATE_PU | SOR_PWR_NORMAL_START_NORMAL | + SOR_PWR_SAFE_STATE_PD | SOR_PWR_SETTING_NEW_TRIGGER, + &hdmi->nv_pdisp_sor_pwr); + writel(SOR_PWR_NORMAL_STATE_PU | SOR_PWR_NORMAL_START_NORMAL | + SOR_PWR_SAFE_STATE_PD | SOR_PWR_SETTING_NEW_DONE, + &hdmi->nv_pdisp_sor_pwr); + + do { + if (--retries < 0) + return -ETIME; + value = readl(&hdmi->nv_pdisp_sor_pwr); + } while (value & SOR_PWR_SETTING_NEW_PENDING); + + value = SOR_STATE_ASY_CRCMODE_COMPLETE | + SOR_STATE_ASY_OWNER_HEAD0 | + SOR_STATE_ASY_SUBOWNER_BOTH | + SOR_STATE_ASY_PROTOCOL_SINGLE_TMDS_A | + SOR_STATE_ASY_DEPOL_POS; + + /* setup sync polarities */ + if (dt->flags & DISPLAY_FLAGS_HSYNC_HIGH) + value |= SOR_STATE_ASY_HSYNCPOL_POS; + + if (dt->flags & DISPLAY_FLAGS_HSYNC_LOW) + value |= SOR_STATE_ASY_HSYNCPOL_NEG; + + if (dt->flags & DISPLAY_FLAGS_VSYNC_HIGH) + value |= SOR_STATE_ASY_VSYNCPOL_POS; + + if (dt->flags & DISPLAY_FLAGS_VSYNC_LOW) + value |= SOR_STATE_ASY_VSYNCPOL_NEG; + + writel(value, &hdmi->nv_pdisp_sor_state2); + + value = SOR_STATE_ASY_HEAD_OPMODE_AWAKE | SOR_STATE_ASY_ORMODE_NORMAL; + writel(value, &hdmi->nv_pdisp_sor_state1); + + writel(0, &hdmi->nv_pdisp_sor_state0); + writel(SOR_STATE_UPDATE, &hdmi->nv_pdisp_sor_state0); + writel(value | SOR_STATE_ATTACHED, + &hdmi->nv_pdisp_sor_state1); + writel(0, &hdmi->nv_pdisp_sor_state0); + + tegra_dc_enable_controller(dev); + + return 0; +} + +/* DDC/CI backlight control */ +static int tegra_hdmi_set_connector(struct udevice *dev, int percent) +{ + struct tegra_hdmi_priv *priv = dev_get_priv(dev); + struct udevice *ddc_entry; + struct i2c_msg msg[1]; + u8 checksum = DDCCI_ENTRY_ADDR << 1; + int i, ret; + + ret = dm_i2c_probe(priv->hdmi_ddc, DDCCI_ENTRY_ADDR, 0, &ddc_entry); + if (ret) { + log_debug("%s: cannot probe DDC/CI entry: error %d\n", + __func__, ret); + return 0; + } + + /* + * payload[1] is length: hithest bit OR last 4 bits indicate + * the number of following bytes (excluding checksum) + */ + u8 payload[7] = { DDCCI_SOURSE_ADDR, BIT(7) | (sizeof(payload) - 3), + DDCCI_COMMAND_WRITE, DDCCI_CTRL_BRIGHTNESS, + (u8)(percent & 0xff), (u8)(percent & 0xff), 0 }; + + /* DDC/CI checksum is a simple XOR of all preceding bytes */ + for (i = 0; i < (sizeof(payload) - 1); i++) + checksum ^= payload[i]; + + payload[6] = checksum; + + msg->addr = DDCCI_ENTRY_ADDR; + msg->flags = 0; + msg->len = sizeof(payload); + msg->buf = payload; + + dm_i2c_xfer(ddc_entry, msg, 1); + + return 0; +} + +static int tegra_hdmi_timings(struct udevice *dev, + struct display_timing *timing) +{ + struct tegra_hdmi_priv *priv = dev_get_priv(dev); + + memcpy(timing, &priv->timing, sizeof(*timing)); + + return 0; +} + +static void tegra_hdmi_init_clocks(struct udevice *dev) +{ + struct tegra_hdmi_priv *priv = dev_get_priv(dev); + u32 n = priv->timing.pixelclock.typ * 2 / USEC_PER_SEC; + + switch (clock_get_osc_freq()) { + case CLOCK_OSC_FREQ_12_0: /* OSC is 12Mhz */ + case CLOCK_OSC_FREQ_48_0: /* OSC is 48Mhz */ + clock_set_rate(priv->clk_parent->id, n, 12, 0, 8); + break; + + case CLOCK_OSC_FREQ_26_0: /* OSC is 26Mhz */ + clock_set_rate(priv->clk_parent->id, n, 26, 0, 8); + break; + + case CLOCK_OSC_FREQ_13_0: /* OSC is 13Mhz */ + case CLOCK_OSC_FREQ_16_8: /* OSC is 16.8Mhz */ + clock_set_rate(priv->clk_parent->id, n, 13, 0, 8); + break; + + case CLOCK_OSC_FREQ_19_2: + case CLOCK_OSC_FREQ_38_4: + default: + /* + * These are not supported. + */ + break; + } + + clock_start_periph_pll(priv->clk->id, priv->clk_parent->id, + priv->timing.pixelclock.typ); +} + +static bool tegra_hdmi_mode_valid(void *hdmi_priv, const struct display_timing *timing) +{ + struct tegra_hdmi_priv *priv = hdmi_priv; + + if (timing->pixelclock.typ > priv->config->max_pclk) + return false; + + return true; +} + +static int tegra_hdmi_decode_edid(struct udevice *dev) +{ + struct tegra_hdmi_priv *priv = dev_get_priv(dev); + struct udevice *hdmi_edid; + uchar edid_buf[EDID_SIZE] = { 0 }; + int i, ret; + + /* Poll for 1 sec in case EDID is not ready right after hpd */ + for (i = 0; i < 10; i++) { + ret = dm_i2c_probe(priv->hdmi_ddc, HDMI_EDID_I2C_ADDR, 0, + &hdmi_edid); + if (!ret) + break; + + mdelay(100); + } + if (ret) { + log_debug("%s: cannot probe EDID: error %d\n", + __func__, ret); + return ret; + } + + ret = dm_i2c_read(hdmi_edid, 0, edid_buf, sizeof(edid_buf)); + if (ret) { + log_debug("%s: cannot dump EDID buffer: error %d\n", + __func__, ret); + return ret; + } + + ret = edid_get_timing_validate(edid_buf, sizeof(edid_buf), &priv->timing, + &priv->panel_bits_per_colourp, + tegra_hdmi_mode_valid, priv); + if (ret) { + log_debug("%s: cannot decode EDID info: error %d\n", + __func__, ret); + return ret; + } + + return 0; +} + +static int tegra_hdmi_wait_hpd(struct tegra_hdmi_priv *priv) +{ + int i; + + /* Poll 1 second for HPD signal */ + for (i = 0; i < 10; i++) { + if (dm_gpio_get_value(&priv->hpd)) + return 0; + + mdelay(100); + } + + return -ETIMEDOUT; +} + +static int tegra_hdmi_probe(struct udevice *dev) +{ + struct tegra_hdmi_priv *priv = dev_get_priv(dev); + struct reset_ctl reset_ctl; + int i, ret; + + priv->hdmi_regmap = (struct hdmi_ctlr *)dev_read_addr_ptr(dev); + if (!priv->hdmi_regmap) { + log_debug("%s: no display controller address\n", __func__); + return -EINVAL; + } + + priv->config = (struct tegra_hdmi_config *)dev_get_driver_data(dev); + + priv->clk = devm_clk_get(dev, NULL); + if (IS_ERR(priv->clk)) { + log_debug("%s: Could not get HDMI clock: %ld\n", + __func__, PTR_ERR(priv->clk)); + return PTR_ERR(priv->clk); + } + + priv->clk_parent = devm_clk_get(dev, "parent"); + if (IS_ERR(priv->clk_parent)) { + log_debug("%s: Could not get HDMI clock parent: %ld\n", + __func__, PTR_ERR(priv->clk_parent)); + return PTR_ERR(priv->clk_parent); + } + + for (i = 0; i < ARRAY_SIZE(hdmi_supplies); i++) { + ret = device_get_supply_regulator(dev, hdmi_supplies[i], + &priv->supplies[i]); + if (ret) { + log_debug("%s: cannot get %s %d\n", __func__, + hdmi_supplies[i], ret); + if (ret != -ENOENT) + return log_ret(ret); + } + + ret = regulator_set_enable_if_allowed(priv->supplies[i], true); + if (ret && ret != -ENOSYS) { + log_debug("%s: cannot enable %s: error %d\n", + __func__, hdmi_supplies[i], ret); + return ret; + } + } + + ret = reset_get_by_name(dev, "hdmi", &reset_ctl); + if (ret) { + log_debug("%s: reset_get_by_name() failed: %d\n", + __func__, ret); + return ret; + } + + ret = uclass_get_device_by_phandle(UCLASS_I2C, dev, + "nvidia,ddc-i2c-bus", + &priv->hdmi_ddc); + if (ret) { + log_debug("%s: cannot get hdmi ddc i2c bus: error %d\n", + __func__, ret); + return ret; + } + + ret = gpio_request_by_name(dev, "nvidia,hpd-gpio", 0, + &priv->hpd, GPIOD_IS_IN); + if (ret) { + log_debug("%s: Could not decode hpd-gpios (%d)\n", + __func__, ret); + return ret; + } + + /* wait for connector */ + ret = tegra_hdmi_wait_hpd(priv); + if (ret) { + /* HPD failed, use default timings */ + memcpy(&priv->timing, &default_720p_timing, + sizeof(default_720p_timing)); + } else { + ret = tegra_hdmi_decode_edid(dev); + if (ret) + memcpy(&priv->timing, &default_720p_timing, + sizeof(default_720p_timing)); + } + + reset_assert(&reset_ctl); + tegra_hdmi_init_clocks(dev); + + mdelay(2); + reset_deassert(&reset_ctl); + + return 0; +} + +static const struct tegra_hdmi_config tegra20_hdmi_config = { + .tmds = tegra20_tmds_config, + .num_tmds = ARRAY_SIZE(tegra20_tmds_config), + .max_pclk = 148500000, /* 1080p */ +}; + +static const struct tegra_hdmi_config tegra30_hdmi_config = { + .tmds = tegra30_tmds_config, + .num_tmds = ARRAY_SIZE(tegra30_tmds_config), + .max_pclk = 148500000, /* 1080p */ +}; + +static const struct video_bridge_ops tegra_hdmi_ops = { + .attach = tegra_hdmi_encoder_enable, + .set_backlight = tegra_hdmi_set_connector, + .get_display_timing = tegra_hdmi_timings, +}; + +static const struct udevice_id tegra_hdmi_ids[] = { + { + .compatible = "nvidia,tegra20-hdmi", + .data = (ulong)&tegra20_hdmi_config + }, { + .compatible = "nvidia,tegra30-hdmi", + .data = (ulong)&tegra30_hdmi_config + }, { + /* sentinel */ + } +}; + +U_BOOT_DRIVER(tegra_hdmi) = { + .name = "tegra_hdmi", + .id = UCLASS_VIDEO_BRIDGE, + .of_match = tegra_hdmi_ids, + .ops = &tegra_hdmi_ops, + .probe = tegra_hdmi_probe, + .plat_auto = sizeof(struct tegra_dc_plat), + .priv_auto = sizeof(struct tegra_hdmi_priv), +}; diff --git a/drivers/video/tegra20/tegra-hdmi.h b/drivers/video/tegra20/tegra-hdmi.h new file mode 100644 index 00000000000..d17655973e3 --- /dev/null +++ b/drivers/video/tegra20/tegra-hdmi.h @@ -0,0 +1,648 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * (C) Copyright 2010 + * NVIDIA Corporation + */ + +#ifndef _TEGRA_HDMI_H +#define _TEGRA_HDMI_H + +#ifndef __ASSEMBLY__ +#include +#endif + +/* Register definitions for the Tegra high-definition multimedia interface */ + +/* High-Definition Multimedia Interface (HDMI_) regs */ +struct hdmi_ctlr { + /* Address 0x000 ~ 0x0d2 */ + uint ctxsw; /* _CTXSW */ /* 0x00 */ + + uint nv_pdisp_sor_state0; /* _NV_PDISP_SOR_STATE0 */ + uint nv_pdisp_sor_state1; /* _NV_PDISP_SOR_STATE1 */ + uint nv_pdisp_sor_state2; /* _NV_PDISP_SOR_STATE2 */ + + uint nv_pdisp_rg_hdcp_an_msb; /* _NV_PDISP_RG_HDCP_AN_MSB */ + uint nv_pdisp_rg_hdcp_an_lsb; /* _NV_PDISP_RG_HDCP_AN_LSB */ + uint nv_pdisp_rg_hdcp_cn_msb; /* _NV_PDISP_RG_HDCP_CN_MSB */ + uint nv_pdisp_rg_hdcp_cn_lsb; /* _NV_PDISP_RG_HDCP_CN_LSB */ + uint nv_pdisp_rg_hdcp_aksv_msb; /* _NV_PDISP_RG_HDCP_AKSV_MSB */ + uint nv_pdisp_rg_hdcp_aksv_lsb; /* _NV_PDISP_RG_HDCP_AKSV_LSB */ + uint nv_pdisp_rg_hdcp_bksv_msb; /* _NV_PDISP_RG_HDCP_BKSV_MSB */ + uint nv_pdisp_rg_hdcp_bksv_lsb; /* _NV_PDISP_RG_HDCP_BKSV_LSB */ + uint nv_pdisp_rg_hdcp_cksv_msb; /* _NV_PDISP_RG_HDCP_CKSV_MSB */ + uint nv_pdisp_rg_hdcp_cksv_lsb; /* _NV_PDISP_RG_HDCP_CKSV_LSB */ + uint nv_pdisp_rg_hdcp_dksv_msb; /* _NV_PDISP_RG_HDCP_DKSV_MSB */ + uint nv_pdisp_rg_hdcp_dksv_lsb; /* _NV_PDISP_RG_HDCP_DKSV_LSB */ + uint nv_pdisp_rg_hdcp_ctrl; /* _NV_PDISP_RG_HDCP_CTRL */ /* 0x10 */ + uint nv_pdisp_rg_hdcp_cmode; /* _NV_PDISP_RG_HDCP_CMODE */ + uint nv_pdisp_rg_hdcp_mprime_msb; /* _NV_PDISP_RG_HDCP_MPRIME_MSB */ + uint nv_pdisp_rg_hdcp_mprime_lsb; /* _NV_PDISP_RG_HDCP_MPRIME_LSB */ + uint nv_pdisp_rg_hdcp_sprime_msb; /* _NV_PDISP_RG_HDCP_SPRIME_MSB */ + uint nv_pdisp_rg_hdcp_sprime_lsb2; /* _NV_PDISP_RG_HDCP_SPRIME_LSB2 */ + uint nv_pdisp_rg_hdcp_sprime_lsb1; /* _NV_PDISP_RG_HDCP_SPRIME_LSB1 */ + uint nv_pdisp_rg_hdcp_ri; /* _NV_PDISP_RG_HDCP_RI */ + uint nv_pdisp_rg_hdcp_cs_msb; /* _NV_PDISP_RG_HDCP_CS_MSB */ + uint nv_pdisp_rg_hdcp_cs_lsb; /* _NV_PDISP_RG_HDCP_CS_LSB */ + + uint nv_pdisp_hdmi_audio_emu0; /* _NV_PDISP_HDMI_AUDIO_EMU0 */ + uint nv_pdisp_hdmi_audio_emu_rdata0; /* _NV_PDISP_HDMI_AUDIO_EMU_RDATA0 */ + uint nv_pdisp_hdmi_audio_emu1; /* _NV_PDISP_HDMI_AUDIO_EMU1 */ + uint nv_pdisp_hdmi_audio_emu2; /* _NV_PDISP_HDMI_AUDIO_EMU2 */ + uint nv_pdisp_hdmi_audio_infoframe_ctrl; /* _NV_PDISP_HDMI_AUDIO_INFOFRAME_CTRL */ + uint nv_pdisp_hdmi_audio_infoframe_status; /* _NV_PDISP_HDMI_AUDIO_INFOFRAME_STATUS */ + uint nv_pdisp_hdmi_audio_infoframe_header; /* _NV_PDISP_HDMI_AUDIO_INFOFRAME_HEADER */ /* 0x20 */ + uint nv_pdisp_hdmi_audio_infoframe_subpack0_low; /* _NV_PDISP_HDMI_AUDIO_INFOFRAME_SUBPACK0_LOW */ + uint nv_pdisp_hdmi_audio_infoframe_subpack0_high; /* _NV_PDISP_HDMI_AUDIO_INFOFRAME_SUBPACK0_HIGH */ + + uint nv_pdisp_hdmi_avi_infoframe_ctrl; /* _NV_PDISP_HDMI_AVI_INFOFRAME_CTRL */ + uint nv_pdisp_hdmi_avi_infoframe_status; /* _NV_PDISP_HDMI_AVI_INFOFRAME_STATUS */ + uint nv_pdisp_hdmi_avi_infoframe_header; /* _NV_PDISP_HDMI_AVI_INFOFRAME_HEADER */ + uint nv_pdisp_hdmi_avi_infoframe_subpack0_low; /* _NV_PDISP_HDMI_AVI_INFOFRAME_SUBPACK0_LOW */ + uint nv_pdisp_hdmi_avi_infoframe_subpack0_high; /* _NV_PDISP_HDMI_AVI_INFOFRAME_SUBPACK0_HIGH */ + uint nv_pdisp_hdmi_avi_infoframe_subpack1_low; /* _NV_PDISP_HDMI_AVI_INFOFRAME_SUBPACK1_LOW */ + uint nv_pdisp_hdmi_avi_infoframe_subpack1_high; /* _NV_PDISP_HDMI_AVI_INFOFRAME_SUBPACK1_HIGH */ + + uint nv_pdisp_hdmi_generic_ctrl; /* _NV_PDISP_HDMI_GENERIC_CTRL */ + uint nv_pdisp_hdmi_generic_status; /* _NV_PDISP_HDMI_GENERIC_STATUS */ + uint nv_pdisp_hdmi_generic_header; /* _NV_PDISP_HDMI_GENERIC_HEADER */ + uint nv_pdisp_hdmi_generic_subpack0_low; /* _NV_PDISP_HDMI_GENERIC_SUBPACK0_LOW */ + uint nv_pdisp_hdmi_generic_subpack0_high; /* _NV_PDISP_HDMI_GENERIC_SUBPACK0_HIGH */ + uint nv_pdisp_hdmi_generic_subpack1_low; /* _NV_PDISP_HDMI_GENERIC_SUBPACK1_LOW */ + uint nv_pdisp_hdmi_generic_subpack1_high; /* _NV_PDISP_HDMI_GENERIC_SUBPACK1_HIGH */ + uint nv_pdisp_hdmi_generic_subpack2_low; /* _NV_PDISP_HDMI_GENERIC_SUBPACK2_LOW */ + uint nv_pdisp_hdmi_generic_subpack2_high; /* _NV_PDISP_HDMI_GENERIC_SUBPACK2_HIGH */ + uint nv_pdisp_hdmi_generic_subpack3_low; /* _NV_PDISP_HDMI_GENERIC_SUBPACK3_LOW */ + uint nv_pdisp_hdmi_generic_subpack3_high; /* _NV_PDISP_HDMI_GENERIC_SUBPACK3_HIGH */ + + uint nv_pdisp_hdmi_acr_ctrl; /* _NV_PDISP_HDMI_ACR_CTRL */ + uint nv_pdisp_hdmi_acr_0320_subpack_low; /* _NV_PDISP_HDMI_ACR_0320_SUBPACK_LOW */ + uint nv_pdisp_hdmi_acr_0320_subpack_high; /* _NV_PDISP_HDMI_ACR_0320_SUBPACK_HIGH */ + uint nv_pdisp_hdmi_acr_0441_subpack_low; /* _NV_PDISP_HDMI_ACR_0441_SUBPACK_LOW */ + uint nv_pdisp_hdmi_acr_0441_subpack_high; /* _NV_PDISP_HDMI_ACR_0441_SUBPACK_HIGH */ + uint nv_pdisp_hdmi_acr_0882_subpack_low; /* _NV_PDISP_HDMI_ACR_0882_SUBPACK_LOW */ + uint nv_pdisp_hdmi_acr_0882_subpack_high; /* _NV_PDISP_HDMI_ACR_0882_SUBPACK_HIGH */ + uint nv_pdisp_hdmi_acr_1764_subpack_low; /* _NV_PDISP_HDMI_ACR_1764_SUBPACK_LOW */ + uint nv_pdisp_hdmi_acr_1764_subpack_high; /* _NV_PDISP_HDMI_ACR_1764_SUBPACK_HIGH */ + uint nv_pdisp_hdmi_acr_0480_subpack_low; /* _NV_PDISP_HDMI_ACR_0480_SUBPACK_LOW */ + uint nv_pdisp_hdmi_acr_0480_subpack_high; /* _NV_PDISP_HDMI_ACR_0480_SUBPACK_HIGH */ + uint nv_pdisp_hdmi_acr_0960_subpack_low; /* _NV_PDISP_HDMI_ACR_0960_SUBPACK_LOW */ + uint nv_pdisp_hdmi_acr_0960_subpack_high; /* _NV_PDISP_HDMI_ACR_0960_SUBPACK_HIGH */ + uint nv_pdisp_hdmi_acr_1920_subpack_low; /* _NV_PDISP_HDMI_ACR_1920_SUBPACK_LOW */ + uint nv_pdisp_hdmi_acr_1920_subpack_high; /* _NV_PDISP_HDMI_ACR_1920_SUBPACK_HIGH */ + + uint nv_pdisp_hdmi_ctrl; /* _NV_PDISP_HDMI_CTRL */ + uint nv_pdisp_hdmi_vsync_keepout; /* _NV_PDISP_HDMI_VSYNC_KEEPOUT */ + uint nv_pdisp_hdmi_vsync_window; /* _NV_PDISP_HDMI_VSYNC_WINDOW */ + uint nv_pdisp_hdmi_gcp_ctrl; /* _NV_PDISP_HDMI_GCP_CTRL */ + uint nv_pdisp_hdmi_gcp_status; /* _NV_PDISP_HDMI_GCP_STATUS */ + uint nv_pdisp_hdmi_gcp_subpack; /* _NV_PDISP_HDMI_GCP_SUBPACK */ + uint nv_pdisp_hdmi_channel_status1; /* _NV_PDISP_HDMI_CHANNEL_STATUS1 */ + uint nv_pdisp_hdmi_channel_status2; /* _NV_PDISP_HDMI_CHANNEL_STATUS2 */ + uint nv_pdisp_hdmi_emu0; /* _NV_PDISP_HDMI_EMU0 */ + uint nv_pdisp_hdmi_emu1; /* _NV_PDISP_HDMI_EMU1 */ + uint nv_pdisp_hdmi_emu1_rdata; /* _NV_PDISP_HDMI_EMU1_RDATA */ + uint nv_pdisp_hdmi_spare; /* _NV_PDISP_HDMI_SPARE */ + uint nv_pdisp_hdmi_spdif_chn_status1; /* _NV_PDISP_HDMI_SPDIF_CHN_STATUS1 */ + uint nv_pdisp_hdmi_spdif_chn_status2; /* _NV_PDISP_HDMI_SPDIF_CHN_STATUS2 */ + + uint nv_pdisp_hdcprif_rom_ctrl; /* _NV_PDISP_HDCPRIF_ROM_CTRL */ + + uint unused; + + uint nv_pdisp_sor_cap; /* _NV_PDISP_SOR_CAP */ + uint nv_pdisp_sor_pwr; /* _NV_PDISP_SOR_PWR */ + uint nv_pdisp_sor_test; /* _NV_PDISP_SOR_TEST */ + uint nv_pdisp_sor_pll0; /* _NV_PDISP_SOR_PLL0 */ + uint nv_pdisp_sor_pll1; /* _NV_PDISP_SOR_PLL1 */ + uint nv_pdisp_sor_pll2; /* _NV_PDISP_SOR_PLL2 */ + uint nv_pdisp_sor_cstm; /* _NV_PDISP_SOR_CSTM */ + uint nv_pdisp_sor_lvds; /* _NV_PDISP_SOR_LVDS */ + uint nv_pdisp_sor_crca; /* _NV_PDISP_SOR_CRCA */ + uint nv_pdisp_sor_crcb; /* _NV_PDISP_SOR_CRCB */ + uint nv_pdisp_sor_blank; /* _NV_PDISP_SOR_BLANK */ + + uint nv_pdisp_sor_seq_ctl; /* _NV_PDISP_SOR_SEQ_CTL */ + uint nv_pdisp_sor_seq_inst0; /* _NV_PDISP_SOR_SEQ_INST0 */ + uint nv_pdisp_sor_seq_inst1; /* _NV_PDISP_SOR_SEQ_INST1 */ + uint nv_pdisp_sor_seq_inst2; /* _NV_PDISP_SOR_SEQ_INST2 */ + uint nv_pdisp_sor_seq_inst3; /* _NV_PDISP_SOR_SEQ_INST3 */ + uint nv_pdisp_sor_seq_inst4; /* _NV_PDISP_SOR_SEQ_INST4 */ + uint nv_pdisp_sor_seq_inst5; /* _NV_PDISP_SOR_SEQ_INST5 */ + uint nv_pdisp_sor_seq_inst6; /* _NV_PDISP_SOR_SEQ_INST6 */ + uint nv_pdisp_sor_seq_inst7; /* _NV_PDISP_SOR_SEQ_INST7 */ + uint nv_pdisp_sor_seq_inst8; /* _NV_PDISP_SOR_SEQ_INST8 */ + uint nv_pdisp_sor_seq_inst9; /* _NV_PDISP_SOR_SEQ_INST9 */ + uint nv_pdisp_sor_seq_insta; /* _NV_PDISP_SOR_SEQ_INSTA */ + uint nv_pdisp_sor_seq_instb; /* _NV_PDISP_SOR_SEQ_INSTB */ + uint nv_pdisp_sor_seq_instc; /* _NV_PDISP_SOR_SEQ_INSTC */ + uint nv_pdisp_sor_seq_instd; /* _NV_PDISP_SOR_SEQ_INSTD */ + uint nv_pdisp_sor_seq_inste; /* _NV_PDISP_SOR_SEQ_INSTE */ + uint nv_pdisp_sor_seq_instf; /* _NV_PDISP_SOR_SEQ_INSTF */ + + uint unused1[2]; + + uint nv_pdisp_sor_vcrca0; /* _NV_PDISP_SOR_VCRCA0 */ + uint nv_pdisp_sor_vcrca1; /* _NV_PDISP_SOR_VCRCA1 */ + uint nv_pdisp_sor_ccrca0; /* _NV_PDISP_SOR_CCRCA0 */ + uint nv_pdisp_sor_ccrca1; /* _NV_PDISP_SOR_CCRCA1 */ + + uint nv_pdisp_sor_edataa0; /* _NV_PDISP_SOR_EDATAA0 */ + uint nv_pdisp_sor_edataa1; /* _NV_PDISP_SOR_EDATAA1 */ + + uint nv_pdisp_sor_counta0; /* _NV_PDISP_SOR_COUNTA0 */ + uint nv_pdisp_sor_counta1; /* _NV_PDISP_SOR_COUNTA1 */ + + uint nv_pdisp_sor_debuga0; /* _NV_PDISP_SOR_DEBUGA0 */ + uint nv_pdisp_sor_debuga1; /* _NV_PDISP_SOR_DEBUGA1 */ + + uint nv_pdisp_sor_trig; /* _NV_PDISP_SOR_TRIG */ + uint nv_pdisp_sor_mscheck; /* _NV_PDISP_SOR_MSCHECK */ + uint nv_pdisp_sor_lane_drive_current; /* _NV_PDISP_SOR_LANE_DRIVE_CURRENT */ + + uint nv_pdisp_audio_debug0; /* _NV_PDISP_AUDIO_DEBUG0 0x7f */ + uint nv_pdisp_audio_debug1; /* _NV_PDISP_AUDIO_DEBUG1 0x80 */ + uint nv_pdisp_audio_debug2; /* _NV_PDISP_AUDIO_DEBUG2 0x81 */ + + uint nv_pdisp_audio_fs1; /* _NV_PDISP_AUDIO_FS1 0x82 */ + uint nv_pdisp_audio_fs2; /* _NV_PDISP_AUDIO_FS2 */ + uint nv_pdisp_audio_fs3; /* _NV_PDISP_AUDIO_FS3 */ + uint nv_pdisp_audio_fs4; /* _NV_PDISP_AUDIO_FS4 */ + uint nv_pdisp_audio_fs5; /* _NV_PDISP_AUDIO_FS5 */ + uint nv_pdisp_audio_fs6; /* _NV_PDISP_AUDIO_FS6 */ + uint nv_pdisp_audio_fs7; /* _NV_PDISP_AUDIO_FS7 0x88 */ + + uint nv_pdisp_audio_pulse_width; /* _NV_PDISP_AUDIO_PULSE_WIDTH */ + uint nv_pdisp_audio_threshold; /* _NV_PDISP_AUDIO_THRESHOLD */ + uint nv_pdisp_audio_cntrl0; /* _NV_PDISP_AUDIO_CNTRL0 */ + uint nv_pdisp_audio_n; /* _NV_PDISP_AUDIO_N */ + uint nv_pdisp_audio_nval[7]; /* _NV_PDISP_AUDIO_NVAL */ + + uint nv_pdisp_hdcprif_rom_timing; /* _NV_PDISP_HDCPRIF_ROM_TIMING */ + uint nv_pdisp_sor_refclk; /* _NV_PDISP_SOR_REFCLK */ + uint nv_pdisp_crc_control; /* _NV_PDISP_CRC_CONTROL */ + uint nv_pdisp_input_control; /* _NV_PDISP_INPUT_CONTROL */ + uint nv_pdisp_scratch; /* _NV_PDISP_SCRATCH */ + uint nv_pdisp_pe_current; /* _NV_PDISP_PE_CURRENT */ + + uint nv_pdisp_key_ctrl; /* _NV_PDISP_KEY_CTRL */ + uint nv_pdisp_key_debug0; /* _NV_PDISP_KEY_DEBUG0 */ + uint nv_pdisp_key_debug1; /* _NV_PDISP_KEY_DEBUG1 */ + uint nv_pdisp_key_debug2; /* _NV_PDISP_KEY_DEBUG2 */ + uint nv_pdisp_key_hdcp_key_0; /* _NV_PDISP_KEY_HDCP_KEY_0 */ + uint nv_pdisp_key_hdcp_key_1; /* _NV_PDISP_KEY_HDCP_KEY_1 */ + uint nv_pdisp_key_hdcp_key_2; /* _NV_PDISP_KEY_HDCP_KEY_2 */ + uint nv_pdisp_key_hdcp_key_3; /* _NV_PDISP_KEY_HDCP_KEY_3 */ + uint nv_pdisp_key_hdcp_key_trig; /* _NV_PDISP_KEY_HDCP_KEY_3 */ + uint nv_pdisp_key_skey_index; /* _NV_PDISP_KEY_HDCP_KEY_3 */ /* 0xa3 */ + + uint unused2[8]; + + uint nv_pdisp_sor_audio_cntrl0; /* _NV_PDISP_SOR_AUDIO_CNTRL0 */ /* 0xac */ + uint nv_pdisp_sor_audio_debug; /* _NV_PDISP_SOR_AUDIO_DEBUG */ + uint nv_pdisp_sor_audio_spare0; /* _NV_PDISP_SOR_AUDIO_SPARE0 */ + uint nv_pdisp_sor_audio_nval[7]; /* _NV_PDISP_SOR_AUDIO_NVAL 0xaf ~ 0xb5 */ + uint nv_pdisp_sor_audio_hda_scratch[4]; /* _NV_PDISP_SOR_AUDIO_HDA_SCRATCH 0xb6 ~ 0xb9 */ + uint nv_pdisp_sor_audio_hda_codec_scratch[2]; /* _NV_PDISP_SOR_AUDIO_HDA_CODEC_SCRATCH 0xba ~ 0xbb */ + + uint nv_pdisp_sor_audio_hda_eld_bufwr; /* _NV_PDISP_SOR_AUDIO_HDA_ELD_BUFWR */ + uint nv_pdisp_sor_audio_hda_presense; /* _NV_PDISP_SOR_AUDIO_HDA_PRESENSE */ + uint nv_pdisp_sor_audio_hda_cp; /* _NV_PDISP_SOR_AUDIO_HDA_CP */ + uint nv_pdisp_sor_audio_aval[8]; /* _NV_PDISP_SOR_AUDIO_AVAL */ + uint nv_pdisp_sor_audio_gen_ctrl; /* _NV_PDISP_SOR_AUDIO_GEN_CTRL */ + + uint unused3[4]; + + uint nv_pdisp_int_status; /* _NV_PDISP_INT_STATUS */ + uint nv_pdisp_int_mask; /* _NV_PDISP_INT_MASK */ + uint nv_pdisp_int_enable; /* _NV_PDISP_INT_ENABLE */ + + uint unused4[2]; + + uint nv_pdisp_sor_io_peak_current; /* _NV_PDISP_SOR_IO_PEAK_CURRENT */ + uint nv_pdisp_sor_pad_ctls0; /* _NV_PDISP_SOR_PAD_CTLS0 */ +}; + +/* HDMI_NV_PDISP_SOR_STATE0 0x01 */ +#define SOR_STATE_UPDATE BIT(0) + +/* HDMI_NV_PDISP_SOR_STATE1 0x02 */ +#define SOR_STATE_ASY_HEAD_OPMODE_AWAKE BIT(1) +#define SOR_STATE_ASY_ORMODE_NORMAL BIT(2) +#define SOR_STATE_ATTACHED BIT(3) + +/* HDMI_NV_PDISP_SOR_STATE2 0x03 */ +#define SOR_STATE_ASY_OWNER_NONE (0 << 0) +#define SOR_STATE_ASY_OWNER_HEAD0 (1 << 0) +#define SOR_STATE_ASY_SUBOWNER_NONE (0 << 4) +#define SOR_STATE_ASY_SUBOWNER_SUBHEAD0 (1 << 4) +#define SOR_STATE_ASY_SUBOWNER_SUBHEAD1 (2 << 4) +#define SOR_STATE_ASY_SUBOWNER_BOTH (3 << 4) +#define SOR_STATE_ASY_CRCMODE_ACTIVE (0 << 6) +#define SOR_STATE_ASY_CRCMODE_COMPLETE (1 << 6) +#define SOR_STATE_ASY_CRCMODE_NON_ACTIVE (2 << 6) +#define SOR_STATE_ASY_PROTOCOL_SINGLE_TMDS_A (1 << 8) +#define SOR_STATE_ASY_PROTOCOL_CUSTOM (15 << 8) +#define SOR_STATE_ASY_HSYNCPOL_POS (0 << 12) +#define SOR_STATE_ASY_HSYNCPOL_NEG (1 << 12) +#define SOR_STATE_ASY_VSYNCPOL_POS (0 << 13) +#define SOR_STATE_ASY_VSYNCPOL_NEG (1 << 13) +#define SOR_STATE_ASY_DEPOL_POS (0 << 14) +#define SOR_STATE_ASY_DEPOL_NEG (1 << 14) + +#define INFOFRAME_CTRL_ENABLE BIT(0) +#define INFOFRAME_HEADER_TYPE(x) (((x) & 0xff) << 0) +#define INFOFRAME_HEADER_VERSION(x) (((x) & 0xff) << 8) +#define INFOFRAME_HEADER_LEN(x) (((x) & 0x0f) << 16) + +/* HDMI_NV_PDISP_HDMI_GENERIC_CTRL 0x2a */ +#define GENERIC_CTRL_ENABLE BIT(0) +#define GENERIC_CTRL_OTHER BIT(4) +#define GENERIC_CTRL_SINGLE BIT(8) +#define GENERIC_CTRL_HBLANK BIT(12) +#define GENERIC_CTRL_AUDIO BIT(16) + +/* HDMI_NV_PDISP_HDMI_ACR_* */ +#define ACR_SUBPACK_CTS(x) (((x) & 0xffffff) << 8) +#define ACR_SUBPACK_N(x) (((x) & 0xffffff) << 0) +#define ACR_ENABLE BIT(31) + +/* HDMI_NV_PDISP_HDMI_CTRL 0x44 */ +#define HDMI_CTRL_REKEY(x) (((x) & 0x7f) << 0) +#define HDMI_CTRL_MAX_AC_PACKET(x) (((x) & 0x1f) << 16) +#define HDMI_CTRL_ENABLE BIT(30) + +/* HDMI_NV_PDISP_HDMI_VSYNC_* */ +#define VSYNC_WINDOW_END(x) (((x) & 0x3ff) << 0) +#define VSYNC_WINDOW_START(x) (((x) & 0x3ff) << 16) +#define VSYNC_WINDOW_ENABLE BIT(31) + +/* HDMI_NV_PDISP_HDMI_SPARE 0x4f */ +#define SPARE_HW_CTS BIT(0) +#define SPARE_FORCE_SW_CTS BIT(1) +#define SPARE_CTS_RESET_VAL(x) (((x) & 0x7) << 16) + +/* HDMI_NV_PDISP_SOR_PWR 0x55 */ +#define SOR_PWR_NORMAL_STATE_PD (0 << 0) +#define SOR_PWR_NORMAL_STATE_PU (1 << 0) +#define SOR_PWR_NORMAL_START_NORMAL (0 << 1) +#define SOR_PWR_NORMAL_START_ALT (1 << 1) +#define SOR_PWR_SAFE_STATE_PD (0 << 16) +#define SOR_PWR_SAFE_STATE_PU (1 << 16) +#define SOR_PWR_SETTING_NEW_DONE (0 << 31) +#define SOR_PWR_SETTING_NEW_PENDING (1 << 31) +#define SOR_PWR_SETTING_NEW_TRIGGER (1 << 31) + +/* HDMI_NV_PDISP_SOR_PLL0 0x57 */ +#define SOR_PLL_PWR BIT(0) +#define SOR_PLL_PDBG BIT(1) +#define SOR_PLL_VCAPD BIT(2) +#define SOR_PLL_PDPORT BIT(3) +#define SOR_PLL_RESISTORSEL BIT(4) +#define SOR_PLL_PULLDOWN BIT(5) +#define SOR_PLL_VCOCAP(x) (((x) & 0xf) << 8) +#define SOR_PLL_BG_V17_S(x) (((x) & 0xf) << 12) +#define SOR_PLL_FILTER(x) (((x) & 0xf) << 16) +#define SOR_PLL_ICHPMP(x) (((x) & 0xf) << 24) +#define SOR_PLL_TX_REG_LOAD(x) (((x) & 0xf) << 28) + +/* HDMI_NV_PDISP_SOR_PLL1 0x58 */ +#define SOR_PLL_TMDS_TERM_ENABLE BIT(8) +#define SOR_PLL_TMDS_TERMADJ(x) (((x) & 0xf) << 9) +#define SOR_PLL_LOADADJ(x) (((x) & 0xf) << 20) +#define SOR_PLL_PE_EN BIT(28) +#define SOR_PLL_HALF_FULL_PE BIT(29) +#define SOR_PLL_S_D_PIN_PE BIT(30) + +/* HDMI_NV_PDISP_SOR_CSTM 0x5a */ +#define SOR_CSTM_ROTCLK(x) (((x) & 0xf) << 24) +#define SOR_CSTM_PLLDIV BIT(21) +#define SOR_CSTM_LVDS_ENABLE BIT(16) +#define SOR_CSTM_MODE_LVDS (0 << 12) +#define SOR_CSTM_MODE_TMDS (1 << 12) +#define SOR_CSTM_MODE_MASK (3 << 12) + +/* HDMI_NV_PDISP_SOR_SEQ_CTL 0x5f */ +#define SOR_SEQ_PU_PC(x) (((x) & 0xf) << 0) +#define SOR_SEQ_PU_PC_ALT(x) (((x) & 0xf) << 4) +#define SOR_SEQ_PD_PC(x) (((x) & 0xf) << 8) +#define SOR_SEQ_PD_PC_ALT(x) (((x) & 0xf) << 12) +#define SOR_SEQ_PC(x) (((x) & 0xf) << 16) +#define SOR_SEQ_STATUS BIT(28) +#define SOR_SEQ_SWITCH BIT(30) + +/* HDMI_NV_PDISP_SOR_SEQ_INST(x) (0x60 + (x)) */ +#define SOR_SEQ_INST_WAIT_TIME(x) (((x) & 0x3ff) << 0) +#define SOR_SEQ_INST_WAIT_UNITS_VSYNC (2 << 12) +#define SOR_SEQ_INST_HALT (1 << 15) +#define SOR_SEQ_INST_PIN_A_LOW (0 << 21) +#define SOR_SEQ_INST_PIN_A_HIGH (1 << 21) +#define SOR_SEQ_INST_PIN_B_LOW (0 << 22) +#define SOR_SEQ_INST_PIN_B_HIGH (1 << 22) +#define SOR_SEQ_INST_DRIVE_PWM_OUT_LO (1 << 23) + +/* HDMI_NV_PDISP_SOR_LANE_DRIVE_CURRENT 0x7e */ +#define DRIVE_CURRENT_LANE0(x) (((x) & 0x3f) << 0) +#define DRIVE_CURRENT_LANE1(x) (((x) & 0x3f) << 8) +#define DRIVE_CURRENT_LANE2(x) (((x) & 0x3f) << 16) +#define DRIVE_CURRENT_LANE3(x) (((x) & 0x3f) << 24) +#define DRIVE_CURRENT_LANE0_T114(x) (((x) & 0x7f) << 0) +#define DRIVE_CURRENT_LANE1_T114(x) (((x) & 0x7f) << 8) +#define DRIVE_CURRENT_LANE2_T114(x) (((x) & 0x7f) << 16) +#define DRIVE_CURRENT_LANE3_T114(x) (((x) & 0x7f) << 24) + +/* Drive current list */ +enum { + DRIVE_CURRENT_1_500_mA, + DRIVE_CURRENT_1_875_mA, + DRIVE_CURRENT_2_250_mA, + DRIVE_CURRENT_2_625_mA, + DRIVE_CURRENT_3_000_mA, + DRIVE_CURRENT_3_375_mA, + DRIVE_CURRENT_3_750_mA, + DRIVE_CURRENT_4_125_mA, + DRIVE_CURRENT_4_500_mA, + DRIVE_CURRENT_4_875_mA, + DRIVE_CURRENT_5_250_mA, + DRIVE_CURRENT_5_625_mA, + DRIVE_CURRENT_6_000_mA, + DRIVE_CURRENT_6_375_mA, + DRIVE_CURRENT_6_750_mA, + DRIVE_CURRENT_7_125_mA, + DRIVE_CURRENT_7_500_mA, + DRIVE_CURRENT_7_875_mA, + DRIVE_CURRENT_8_250_mA, + DRIVE_CURRENT_8_625_mA, + DRIVE_CURRENT_9_000_mA, + DRIVE_CURRENT_9_375_mA, + DRIVE_CURRENT_9_750_mA, + DRIVE_CURRENT_10_125_mA, + DRIVE_CURRENT_10_500_mA, + DRIVE_CURRENT_10_875_mA, + DRIVE_CURRENT_11_250_mA, + DRIVE_CURRENT_11_625_mA, + DRIVE_CURRENT_12_000_mA, + DRIVE_CURRENT_12_375_mA, + DRIVE_CURRENT_12_750_mA, + DRIVE_CURRENT_13_125_mA, + DRIVE_CURRENT_13_500_mA, + DRIVE_CURRENT_13_875_mA, + DRIVE_CURRENT_14_250_mA, + DRIVE_CURRENT_14_625_mA, + DRIVE_CURRENT_15_000_mA, + DRIVE_CURRENT_15_375_mA, + DRIVE_CURRENT_15_750_mA, + DRIVE_CURRENT_16_125_mA, + DRIVE_CURRENT_16_500_mA, + DRIVE_CURRENT_16_875_mA, + DRIVE_CURRENT_17_250_mA, + DRIVE_CURRENT_17_625_mA, + DRIVE_CURRENT_18_000_mA, + DRIVE_CURRENT_18_375_mA, + DRIVE_CURRENT_18_750_mA, + DRIVE_CURRENT_19_125_mA, + DRIVE_CURRENT_19_500_mA, + DRIVE_CURRENT_19_875_mA, + DRIVE_CURRENT_20_250_mA, + DRIVE_CURRENT_20_625_mA, + DRIVE_CURRENT_21_000_mA, + DRIVE_CURRENT_21_375_mA, + DRIVE_CURRENT_21_750_mA, + DRIVE_CURRENT_22_125_mA, + DRIVE_CURRENT_22_500_mA, + DRIVE_CURRENT_22_875_mA, + DRIVE_CURRENT_23_250_mA, + DRIVE_CURRENT_23_625_mA, + DRIVE_CURRENT_24_000_mA, + DRIVE_CURRENT_24_375_mA, + DRIVE_CURRENT_24_750_mA, +}; + +/* Drive current list for T114 */ +enum { + DRIVE_CURRENT_0_000_mA_T114, + DRIVE_CURRENT_0_400_mA_T114, + DRIVE_CURRENT_0_800_mA_T114, + DRIVE_CURRENT_1_200_mA_T114, + DRIVE_CURRENT_1_600_mA_T114, + DRIVE_CURRENT_2_000_mA_T114, + DRIVE_CURRENT_2_400_mA_T114, + DRIVE_CURRENT_2_800_mA_T114, + DRIVE_CURRENT_3_200_mA_T114, + DRIVE_CURRENT_3_600_mA_T114, + DRIVE_CURRENT_4_000_mA_T114, + DRIVE_CURRENT_4_400_mA_T114, + DRIVE_CURRENT_4_800_mA_T114, + DRIVE_CURRENT_5_200_mA_T114, + DRIVE_CURRENT_5_600_mA_T114, + DRIVE_CURRENT_6_000_mA_T114, + DRIVE_CURRENT_6_400_mA_T114, + DRIVE_CURRENT_6_800_mA_T114, + DRIVE_CURRENT_7_200_mA_T114, + DRIVE_CURRENT_7_600_mA_T114, + DRIVE_CURRENT_8_000_mA_T114, + DRIVE_CURRENT_8_400_mA_T114, + DRIVE_CURRENT_8_800_mA_T114, + DRIVE_CURRENT_9_200_mA_T114, + DRIVE_CURRENT_9_600_mA_T114, + DRIVE_CURRENT_10_000_mA_T114, + DRIVE_CURRENT_10_400_mA_T114, + DRIVE_CURRENT_10_800_mA_T114, + DRIVE_CURRENT_11_200_mA_T114, + DRIVE_CURRENT_11_600_mA_T114, + DRIVE_CURRENT_12_000_mA_T114, + DRIVE_CURRENT_12_400_mA_T114, + DRIVE_CURRENT_12_800_mA_T114, + DRIVE_CURRENT_13_200_mA_T114, + DRIVE_CURRENT_13_600_mA_T114, + DRIVE_CURRENT_14_000_mA_T114, + DRIVE_CURRENT_14_400_mA_T114, + DRIVE_CURRENT_14_800_mA_T114, + DRIVE_CURRENT_15_200_mA_T114, + DRIVE_CURRENT_15_600_mA_T114, + DRIVE_CURRENT_16_000_mA_T114, + DRIVE_CURRENT_16_400_mA_T114, + DRIVE_CURRENT_16_800_mA_T114, + DRIVE_CURRENT_17_200_mA_T114, + DRIVE_CURRENT_17_600_mA_T114, + DRIVE_CURRENT_18_000_mA_T114, + DRIVE_CURRENT_18_400_mA_T114, + DRIVE_CURRENT_18_800_mA_T114, + DRIVE_CURRENT_19_200_mA_T114, + DRIVE_CURRENT_19_600_mA_T114, + DRIVE_CURRENT_20_000_mA_T114, + DRIVE_CURRENT_20_400_mA_T114, + DRIVE_CURRENT_20_800_mA_T114, + DRIVE_CURRENT_21_200_mA_T114, + DRIVE_CURRENT_21_600_mA_T114, + DRIVE_CURRENT_22_000_mA_T114, + DRIVE_CURRENT_22_400_mA_T114, + DRIVE_CURRENT_22_800_mA_T114, + DRIVE_CURRENT_23_200_mA_T114, + DRIVE_CURRENT_23_600_mA_T114, + DRIVE_CURRENT_24_000_mA_T114, + DRIVE_CURRENT_24_400_mA_T114, + DRIVE_CURRENT_24_800_mA_T114, + DRIVE_CURRENT_25_200_mA_T114, + DRIVE_CURRENT_25_400_mA_T114, + DRIVE_CURRENT_25_800_mA_T114, + DRIVE_CURRENT_26_200_mA_T114, + DRIVE_CURRENT_26_600_mA_T114, + DRIVE_CURRENT_27_000_mA_T114, + DRIVE_CURRENT_27_400_mA_T114, + DRIVE_CURRENT_27_800_mA_T114, + DRIVE_CURRENT_28_200_mA_T114, +}; + +/* HDMI_NV_PDISP_AUDIO_FS */ +#define AUDIO_FS_LOW(x) (((x) & 0xfff) << 0) +#define AUDIO_FS_HIGH(x) (((x) & 0xfff) << 16) + +/* HDMI_NV_PDISP_AUDIO_CNTRL0 0x8b */ +#define AUDIO_CNTRL0_ERROR_TOLERANCE(x) (((x) & 0xff) << 0) +#define AUDIO_CNTRL0_SOURCE_SELECT_AUTO (0 << 20) +#define AUDIO_CNTRL0_SOURCE_SELECT_SPDIF (1 << 20) +#define AUDIO_CNTRL0_SOURCE_SELECT_HDAL (2 << 20) +#define AUDIO_CNTRL0_FRAMES_PER_BLOCK(x) (((x) & 0xff) << 24) + +/* HDMI_NV_PDISP_AUDIO_N 0x8c */ +#define AUDIO_N_VALUE(x) (((x) & 0xfffff) << 0) +#define AUDIO_N_RESETF (1 << 20) +#define AUDIO_N_GENERATE_NORMAL (0 << 24) +#define AUDIO_N_GENERATE_ALTERNATE (1 << 24) + +/* HDMI_NV_PDISP_SOR_REFCLK 0x95 */ +#define SOR_REFCLK_DIV_INT(x) (((x) & 0xff) << 8) +#define SOR_REFCLK_DIV_FRAC(x) (((x) & 0x03) << 6) + +/* HDMI_NV_PDISP_INPUT_CONTROL 0x97 */ +#define HDMI_SRC_DISPLAYA (0 << 0) +#define HDMI_SRC_DISPLAYB (1 << 0) +#define ARM_VIDEO_RANGE_FULL (0 << 1) +#define ARM_VIDEO_RANGE_LIMITED (1 << 1) + +/* HDMI_NV_PDISP_PE_CURRENT 0x99 */ +#define PE_CURRENT0(x) (((x) & 0xf) << 0) +#define PE_CURRENT1(x) (((x) & 0xf) << 8) +#define PE_CURRENT2(x) (((x) & 0xf) << 16) +#define PE_CURRENT3(x) (((x) & 0xf) << 24) + +enum { + PE_CURRENT_0_0_mA, + PE_CURRENT_0_5_mA, + PE_CURRENT_1_0_mA, + PE_CURRENT_1_5_mA, + PE_CURRENT_2_0_mA, + PE_CURRENT_2_5_mA, + PE_CURRENT_3_0_mA, + PE_CURRENT_3_5_mA, + PE_CURRENT_4_0_mA, + PE_CURRENT_4_5_mA, + PE_CURRENT_5_0_mA, + PE_CURRENT_5_5_mA, + PE_CURRENT_6_0_mA, + PE_CURRENT_6_5_mA, + PE_CURRENT_7_0_mA, + PE_CURRENT_7_5_mA, +}; + +enum { + PE_CURRENT_0_mA_T114, + PE_CURRENT_1_mA_T114, + PE_CURRENT_2_mA_T114, + PE_CURRENT_3_mA_T114, + PE_CURRENT_4_mA_T114, + PE_CURRENT_5_mA_T114, + PE_CURRENT_6_mA_T114, + PE_CURRENT_7_mA_T114, + PE_CURRENT_8_mA_T114, + PE_CURRENT_9_mA_T114, + PE_CURRENT_10_mA_T114, + PE_CURRENT_11_mA_T114, + PE_CURRENT_12_mA_T114, + PE_CURRENT_13_mA_T114, + PE_CURRENT_14_mA_T114, + PE_CURRENT_15_mA_T114, +}; + +/* HDMI_NV_PDISP_SOR_AUDIO_CNTRL0 0xac */ +#define SOR_AUDIO_CNTRL0_SOURCE_SELECT_AUTO (0 << 20) +#define SOR_AUDIO_CNTRL0_SOURCE_SELECT_SPDIF (1 << 20) +#define SOR_AUDIO_CNTRL0_SOURCE_SELECT_HDAL (2 << 20) +#define SOR_AUDIO_CNTRL0_INJECT_NULLSMPL (1 << 29) + +/* HDMI_NV_PDISP_SOR_AUDIO_SPARE0 0xae */ +#define SOR_AUDIO_SPARE0_HBR_ENABLE BIT(27) + +/* HDMI_NV_PDISP_SOR_AUDIO_HDA_CODEC_SCRATCH0 0xba */ +#define SOR_AUDIO_HDA_CODEC_SCRATCH0_VALID BIT(30) +#define SOR_AUDIO_HDA_CODEC_SCRATCH0_FMT_MASK 0xffff + +/* HDMI_NV_PDISP_SOR_AUDIO_HDA_PRESENSE 0xbd */ +#define SOR_AUDIO_HDA_PRESENSE_VALID BIT(1) +#define SOR_AUDIO_HDA_PRESENSE_PRESENT BIT(0) + +/* HDMI_NV_PDISP_INT_STATUS 0xcc */ +#define INT_SCRATCH BIT(3) +#define INT_CP_REQUEST BIT(2) +#define INT_CODEC_SCRATCH1 BIT(1) +#define INT_CODEC_SCRATCH0 BIT(0) + +/* HDMI_NV_PDISP_SOR_IO_PEAK_CURRENT 0xd1 */ +#define PEAK_CURRENT_LANE0(x) (((x) & 0x7f) << 0) +#define PEAK_CURRENT_LANE1(x) (((x) & 0x7f) << 8) +#define PEAK_CURRENT_LANE2(x) (((x) & 0x7f) << 16) +#define PEAK_CURRENT_LANE3(x) (((x) & 0x7f) << 24) + +enum { + PEAK_CURRENT_0_000_mA, + PEAK_CURRENT_0_200_mA, + PEAK_CURRENT_0_400_mA, + PEAK_CURRENT_0_600_mA, + PEAK_CURRENT_0_800_mA, + PEAK_CURRENT_1_000_mA, + PEAK_CURRENT_1_200_mA, + PEAK_CURRENT_1_400_mA, + PEAK_CURRENT_1_600_mA, + PEAK_CURRENT_1_800_mA, + PEAK_CURRENT_2_000_mA, + PEAK_CURRENT_2_200_mA, + PEAK_CURRENT_2_400_mA, + PEAK_CURRENT_2_600_mA, + PEAK_CURRENT_2_800_mA, + PEAK_CURRENT_3_000_mA, + PEAK_CURRENT_3_200_mA, + PEAK_CURRENT_3_400_mA, + PEAK_CURRENT_3_600_mA, + PEAK_CURRENT_3_800_mA, + PEAK_CURRENT_4_000_mA, + PEAK_CURRENT_4_200_mA, + PEAK_CURRENT_4_400_mA, + PEAK_CURRENT_4_600_mA, + PEAK_CURRENT_4_800_mA, + PEAK_CURRENT_5_000_mA, + PEAK_CURRENT_5_200_mA, + PEAK_CURRENT_5_400_mA, + PEAK_CURRENT_5_600_mA, + PEAK_CURRENT_5_800_mA, + PEAK_CURRENT_6_000_mA, + PEAK_CURRENT_6_200_mA, + PEAK_CURRENT_6_400_mA, + PEAK_CURRENT_6_600_mA, + PEAK_CURRENT_6_800_mA, + PEAK_CURRENT_7_000_mA, + PEAK_CURRENT_7_200_mA, + PEAK_CURRENT_7_400_mA, + PEAK_CURRENT_7_600_mA, + PEAK_CURRENT_7_800_mA, + PEAK_CURRENT_8_000_mA, + PEAK_CURRENT_8_200_mA, + PEAK_CURRENT_8_400_mA, + PEAK_CURRENT_8_600_mA, + PEAK_CURRENT_8_800_mA, + PEAK_CURRENT_9_000_mA, + PEAK_CURRENT_9_200_mA, + PEAK_CURRENT_9_400_mA, +}; + +#endif /* _TEGRA_HDMI_H */ From 811a85af8efd7c7b46ecde708c8177abde4f68f1 Mon Sep 17 00:00:00 2001 From: Svyatoslav Ryhel Date: Fri, 14 Feb 2025 15:13:01 +0200 Subject: [PATCH 03/47] video: tegra20: dc: add video bridge support Rework existing DC driver configuration to support bridges (both external and internal DSI and HDMI controllers) and align video devices chain logic with Linux implementation. Additionally, this should improve communication between DC and internal DSI/HDMI controllers. Signed-off-by: Svyatoslav Ryhel --- drivers/video/tegra20/tegra-dc.c | 204 +++++++++++++++++++++++-------- drivers/video/tegra20/tegra-dc.h | 3 - 2 files changed, 151 insertions(+), 56 deletions(-) diff --git a/drivers/video/tegra20/tegra-dc.c b/drivers/video/tegra20/tegra-dc.c index 001967f2a5a..6b8275ef9fa 100644 --- a/drivers/video/tegra20/tegra-dc.c +++ b/drivers/video/tegra20/tegra-dc.c @@ -1,6 +1,7 @@ // SPDX-License-Identifier: GPL-2.0+ /* * Copyright (c) 2011 The Chromium OS Authors. + * Copyright (c) 2024 Svyatoslav Ryhel */ #include @@ -11,6 +12,7 @@ #include #include #include +#include #include #include #include @@ -31,7 +33,8 @@ struct tegra_lcd_priv { int height; /* height in pixels */ enum video_log2_bpp log2_bpp; /* colour depth */ struct display_timing timing; - struct udevice *panel; + struct udevice *panel; /* Panels attached to RGB */ + struct udevice *bridge; /* Bridge linked with DC */ struct dc_ctlr *dc; /* Display controller regmap */ const struct tegra_dc_soc_info *soc; fdt_addr_t frame_buffer; /* Address of frame buffer */ @@ -373,11 +376,12 @@ static int tegra_lcd_probe(struct udevice *dev) } /* Get shift clock divider from Tegra DSI if used */ - if (!strcmp(priv->panel->name, TEGRA_DSI_A) || - !strcmp(priv->panel->name, TEGRA_DSI_B)) { - struct tegra_dc_plat *dc_plat = dev_get_plat(priv->panel); + if (priv->bridge) { + if (!strcmp(priv->bridge->driver->name, "tegra_dsi")) { + struct tegra_dc_plat *dc_plat = dev_get_plat(priv->bridge); - priv->scdiv = dc_plat->scdiv; + priv->scdiv = dc_plat->scdiv; + } } /* Clean the framebuffer area */ @@ -390,10 +394,20 @@ static int tegra_lcd_probe(struct udevice *dev) return ret; } - ret = panel_enable_backlight(priv->panel); - if (ret) { - log_debug("%s: Cannot enable backlight, ret=%d\n", __func__, ret); - return ret; + if (priv->panel) { + ret = panel_enable_backlight(priv->panel); + if (ret) { + log_debug("%s: Cannot enable backlight, ret=%d\n", __func__, ret); + return ret; + } + } + + if (priv->bridge) { + ret = video_bridge_attach(priv->bridge); + if (ret) { + log_debug("%s: Cannot attach bridge, ret=%d\n", __func__, ret); + return ret; + } } mmu_set_region_dcache_behaviour(priv->frame_buffer, plat->size, @@ -408,17 +422,110 @@ static int tegra_lcd_probe(struct udevice *dev) log_debug("LCD frame buffer at %08x, size %x\n", priv->frame_buffer, plat->size); - return panel_set_backlight(priv->panel, BACKLIGHT_DEFAULT); + if (priv->panel) { + ret = panel_set_backlight(priv->panel, BACKLIGHT_DEFAULT); + if (ret) + return ret; + } + + if (priv->bridge) { + ret = video_bridge_set_backlight(priv->bridge, BACKLIGHT_DEFAULT); + if (ret) + return ret; + } + + return 0; +} + +static int tegra_lcd_configure_rgb(struct udevice *dev, ofnode rgb) +{ + struct tegra_lcd_priv *priv = dev_get_priv(dev); + ofnode remote; + int ret; + + remote = ofnode_parse_phandle(rgb, "nvidia,panel", 0); + if (!ofnode_valid(remote)) + return -EINVAL; + + ret = uclass_get_device_by_ofnode(UCLASS_PANEL, remote, &priv->panel); + if (ret) { + log_debug("%s: Cannot find panel for '%s' (ret=%d)\n", + __func__, dev->name, ret); + + ret = uclass_get_device_by_ofnode(UCLASS_VIDEO_BRIDGE, remote, + &priv->bridge); + if (ret) { + log_err("%s: Cannot find panel or bridge for '%s' (ret=%d)\n", + __func__, dev->name, ret); + return ret; + } + } + + return 0; +} + +static int tegra_lcd_configure_internal(struct udevice *dev) +{ + struct tegra_lcd_priv *priv = dev_get_priv(dev); + struct tegra_dc_plat *dc_plat; + ofnode host1x = ofnode_get_parent(dev_ofnode(dev)); + ofnode node; + int ret; + + switch (priv->pipe) { + case 0: /* DC0 is usually used for DSI */ + /* Check for ganged DSI configuration */ + ofnode_for_each_subnode(node, host1x) + if (ofnode_name_eq(node, "dsi") && ofnode_is_enabled(node) && + ofnode_read_bool(node, "nvidia,ganged-mode")) + goto exit; + + /* If no master DSI found loop for any active DSI */ + ofnode_for_each_subnode(node, host1x) + if (ofnode_name_eq(node, "dsi") && ofnode_is_enabled(node)) + goto exit; + + log_err("%s: failed to find DSI device for '%s'\n", + __func__, dev->name); + + return -ENODEV; + case 1: /* DC1 is usually used for HDMI */ + ofnode_for_each_subnode(node, host1x) + if (ofnode_name_eq(node, "hdmi")) + goto exit; + + log_err("%s: failed to find HDMI device for '%s'\n", + __func__, dev->name); + + return -ENODEV; + default: + log_debug("Unsupported DC selection\n"); + return -EINVAL; + } + +exit: + ret = uclass_get_device_by_ofnode(UCLASS_VIDEO_BRIDGE, node, &priv->bridge); + if (ret) { + log_err("%s: failed to get DSI/HDMI device for '%s' (ret %d)\n", + __func__, dev->name, ret); + return ret; + } + + dc_plat = dev_get_plat(priv->bridge); + + /* Fill the platform data for internal devices */ + dc_plat->dev = dev; + dc_plat->dc = priv->dc; + dc_plat->pipe = priv->pipe; + + return 0; } static int tegra_lcd_of_to_plat(struct udevice *dev) { struct tegra_lcd_priv *priv = dev_get_priv(dev); - const void *blob = gd->fdt_blob; struct display_timing *timing; - int node = dev_of_offset(dev); - int panel_node; - int rgb; + ofnode rgb; int ret; priv->dc = (struct dc_ctlr *)dev_read_addr_ptr(dev); @@ -446,44 +553,42 @@ static int tegra_lcd_of_to_plat(struct udevice *dev) priv->rotation = dev_read_bool(dev, "nvidia,180-rotation"); priv->pipe = dev_read_u32_default(dev, "nvidia,head", 0); - rgb = fdt_subnode_offset(blob, node, "rgb"); - if (rgb < 0) { - log_debug("%s: Cannot find rgb subnode for '%s' (ret=%d)\n", - __func__, dev->name, rgb); - return -EINVAL; - } - /* - * Sadly the panel phandle is in an rgb subnode so we cannot use - * uclass_get_device_by_phandle(). + * Usual logic of Tegra video routing should be next: + * 1. Check rgb subnode for RGB/LVDS panels or bridges + * 2. If none found, then iterate through bridges bound, + * looking for DSIA or DSIB for DC0 and HDMI for DC1. + * If none of above is valid, then configuration is not + * valid. */ - panel_node = fdtdec_lookup_phandle(blob, rgb, "nvidia,panel"); - if (panel_node < 0) { - log_debug("%s: Cannot find panel information\n", __func__); - return -EINVAL; + + rgb = dev_read_subnode(dev, "rgb"); + if (ofnode_valid(rgb) && ofnode_is_enabled(rgb)) { + /* RGB is available, use it */ + ret = tegra_lcd_configure_rgb(dev, rgb); + if (ret) + return ret; + } else { + /* RGB is not available, check for internal devices */ + ret = tegra_lcd_configure_internal(dev); + if (ret) + return ret; } - ret = uclass_get_device_by_of_offset(UCLASS_PANEL, panel_node, - &priv->panel); - if (ret) { - log_debug("%s: Cannot find panel for '%s' (ret=%d)\n", __func__, - dev->name, ret); - return ret; + if (priv->panel) { + ret = panel_get_display_timing(priv->panel, &priv->timing); + if (ret) { + ret = ofnode_decode_display_timing(rgb, 0, &priv->timing); + if (ret) { + log_debug("%s: Cannot read display timing for '%s' (ret=%d)\n", + __func__, dev->name, ret); + return -EINVAL; + } + } } - /* Fill the platform data for internal devices */ - if (!strcmp(priv->panel->name, TEGRA_DSI_A) || - !strcmp(priv->panel->name, TEGRA_DSI_B)) { - struct tegra_dc_plat *dc_plat = dev_get_plat(priv->panel); - - dc_plat->dev = dev; - dc_plat->dc = priv->dc; - dc_plat->pipe = priv->pipe; - } - - ret = panel_get_display_timing(priv->panel, &priv->timing); - if (ret) { - ret = fdtdec_decode_display_timing(blob, rgb, 0, &priv->timing); + if (priv->bridge) { + ret = video_bridge_get_display_timing(priv->bridge, &priv->timing); if (ret) { log_debug("%s: Cannot read display timing for '%s' (ret=%d)\n", __func__, dev->name, ret); @@ -503,13 +608,6 @@ static int tegra_lcd_of_to_plat(struct udevice *dev) static int tegra_lcd_bind(struct udevice *dev) { struct video_uc_plat *plat = dev_get_uclass_plat(dev); - const void *blob = gd->fdt_blob; - int node = dev_of_offset(dev); - int rgb; - - rgb = fdt_subnode_offset(blob, node, "rgb"); - if ((rgb < 0) || !fdtdec_get_is_enabled(blob, rgb)) - return -ENODEV; plat->size = LCD_MAX_WIDTH * LCD_MAX_HEIGHT * (1 << LCD_MAX_LOG2_BPP) / 8; diff --git a/drivers/video/tegra20/tegra-dc.h b/drivers/video/tegra20/tegra-dc.h index 7d0c189ec80..2a4013b3355 100644 --- a/drivers/video/tegra20/tegra-dc.h +++ b/drivers/video/tegra20/tegra-dc.h @@ -14,9 +14,6 @@ /* arch-tegra/dc exists only because T124 uses it */ #include -#define TEGRA_DSI_A "dsi@54300000" -#define TEGRA_DSI_B "dsi@54400000" - struct tegra_dc_plat { struct udevice *dev; /* Display controller device */ struct dc_ctlr *dc; /* Display controller regmap */ From 052c2630e50a01529eb0c0143555712d8b9eff08 Mon Sep 17 00:00:00 2001 From: Svyatoslav Ryhel Date: Sat, 15 Feb 2025 19:48:44 +0200 Subject: [PATCH 04/47] video: tegra20: dc: convert to use of_graph Use OF graph as a main bridge/panel source, preserving backwards compatibility with phandle implementation. Signed-off-by: Svyatoslav Ryhel --- drivers/video/tegra20/tegra-dc.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/drivers/video/tegra20/tegra-dc.c b/drivers/video/tegra20/tegra-dc.c index 6b8275ef9fa..775043bb1fe 100644 --- a/drivers/video/tegra20/tegra-dc.c +++ b/drivers/video/tegra20/tegra-dc.c @@ -8,6 +8,7 @@ #include #include #include +#include #include #include #include @@ -443,6 +444,18 @@ static int tegra_lcd_configure_rgb(struct udevice *dev, ofnode rgb) ofnode remote; int ret; + /* DC can have only 1 port */ + remote = ofnode_graph_get_remote_node(rgb, -1, -1); + + ret = uclass_get_device_by_ofnode(UCLASS_PANEL, remote, &priv->panel); + if (!ret) + return 0; + + ret = uclass_get_device_by_ofnode(UCLASS_VIDEO_BRIDGE, remote, &priv->bridge); + if (!ret) + return 0; + + /* Try legacy method if graph did not work */ remote = ofnode_parse_phandle(rgb, "nvidia,panel", 0); if (!ofnode_valid(remote)) return -EINVAL; From 6fb58c1f7a4ad6ce8dfba93ce46978d0c6191692 Mon Sep 17 00:00:00 2001 From: Svyatoslav Ryhel Date: Sun, 23 Feb 2025 11:27:09 +0200 Subject: [PATCH 05/47] video: tegra20: dc: get DSI/HDMI clock parent if internal DSI/HDMI is used If device uses native Tegra DSI or HDMI, DC clock MUST use the same parent as DSI/HDMI clock uses. Hence remove need in device tree configuration and satisfy this condition by default. Signed-off-by: Svyatoslav Ryhel --- drivers/video/tegra20/tegra-dc.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/drivers/video/tegra20/tegra-dc.c b/drivers/video/tegra20/tegra-dc.c index 775043bb1fe..904d0d205f6 100644 --- a/drivers/video/tegra20/tegra-dc.c +++ b/drivers/video/tegra20/tegra-dc.c @@ -524,6 +524,13 @@ exit: return ret; } + priv->clk_parent = devm_clk_get(priv->bridge, "parent"); + if (IS_ERR(priv->clk_parent)) { + log_debug("%s: Could not get DC clock parent from DSI/HDMI: %ld\n", + __func__, PTR_ERR(priv->clk_parent)); + return PTR_ERR(priv->clk_parent); + } + dc_plat = dev_get_plat(priv->bridge); /* Fill the platform data for internal devices */ From 9be5770d85c1fbb89e30037524d17e55c9afa0ca Mon Sep 17 00:00:00 2001 From: Svyatoslav Ryhel Date: Sat, 1 Mar 2025 16:24:42 +0200 Subject: [PATCH 06/47] video: tegra20: dc: remove unused video operations Video operations are not required by the Tegra Display Controller and should therefore be removed. Signed-off-by: Svyatoslav Ryhel --- drivers/video/tegra20/tegra-dc.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/drivers/video/tegra20/tegra-dc.c b/drivers/video/tegra20/tegra-dc.c index 904d0d205f6..516a397872a 100644 --- a/drivers/video/tegra20/tegra-dc.c +++ b/drivers/video/tegra20/tegra-dc.c @@ -635,9 +635,6 @@ static int tegra_lcd_bind(struct udevice *dev) return 0; } -static const struct video_ops tegra_lcd_ops = { -}; - static const struct tegra_dc_soc_info tegra20_dc_soc_info = { .has_timer = true, .has_rgb = true, @@ -678,7 +675,6 @@ U_BOOT_DRIVER(tegra_lcd) = { .name = "tegra_lcd", .id = UCLASS_VIDEO, .of_match = tegra_lcd_ids, - .ops = &tegra_lcd_ops, .bind = tegra_lcd_bind, .probe = tegra_lcd_probe, .of_to_plat = tegra_lcd_of_to_plat, From 4e539c8bddb994d90e46c4bd0e282b8a852ce6f2 Mon Sep 17 00:00:00 2001 From: Svyatoslav Ryhel Date: Sat, 1 Mar 2025 14:41:28 +0200 Subject: [PATCH 07/47] video: tegra20: dc: support binding child devices Implement child binding helper within DC bind to support DC PWM backlight feature. Signed-off-by: Svyatoslav Ryhel --- drivers/video/tegra20/tegra-dc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/video/tegra20/tegra-dc.c b/drivers/video/tegra20/tegra-dc.c index 516a397872a..1f43153ff27 100644 --- a/drivers/video/tegra20/tegra-dc.c +++ b/drivers/video/tegra20/tegra-dc.c @@ -632,7 +632,7 @@ static int tegra_lcd_bind(struct udevice *dev) plat->size = LCD_MAX_WIDTH * LCD_MAX_HEIGHT * (1 << LCD_MAX_LOG2_BPP) / 8; - return 0; + return dm_scan_fdt_dev(dev); } static const struct tegra_dc_soc_info tegra20_dc_soc_info = { From 3c21f740788828117a484a6110f7019542db65dd Mon Sep 17 00:00:00 2001 From: Svyatoslav Ryhel Date: Sat, 1 Mar 2025 14:45:04 +0200 Subject: [PATCH 08/47] video: tegra20: pwm-backlight: convert into DC child Establish the backlight as a DC display controller child. Signed-off-by: Svyatoslav Ryhel --- drivers/video/tegra20/tegra-pwm-backlight.c | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/drivers/video/tegra20/tegra-pwm-backlight.c b/drivers/video/tegra20/tegra-pwm-backlight.c index 79d8a021a3a..998f0df1991 100644 --- a/drivers/video/tegra20/tegra-pwm-backlight.c +++ b/drivers/video/tegra20/tegra-pwm-backlight.c @@ -17,9 +17,6 @@ #include "tegra-dc.h" -#define TEGRA_DISPLAY_A_BASE 0x54200000 -#define TEGRA_DISPLAY_B_BASE 0x54240000 - #define TEGRA_PWM_BL_MIN_BRIGHTNESS 0x10 #define TEGRA_PWM_BL_MAX_BRIGHTNESS 0xFF @@ -106,14 +103,11 @@ static int tegra_pwm_backlight_enable(struct udevice *dev) static int tegra_pwm_backlight_probe(struct udevice *dev) { struct tegra_pwm_backlight_priv *priv = dev_get_priv(dev); + ofnode dc = ofnode_get_parent(dev_ofnode(dev)); - if (dev_read_bool(dev, "nvidia,display-b-base")) - priv->dc = (struct dc_ctlr *)TEGRA_DISPLAY_B_BASE; - else - priv->dc = (struct dc_ctlr *)TEGRA_DISPLAY_A_BASE; - + priv->dc = (struct dc_ctlr *)ofnode_get_addr(dc); if (!priv->dc) { - log_err("no display controller address\n"); + log_err("%s: failed to get DC controller\n", __func__); return -EINVAL; } From d4325bbc16a66ce1fcecdddb394190d971dcffbc Mon Sep 17 00:00:00 2001 From: Svyatoslav Ryhel Date: Fri, 14 Feb 2025 15:24:13 +0200 Subject: [PATCH 09/47] video: tegra20: dsi: convert to video bridge UCLASS Switch from PANEL_UCLASS to VIDEO_BRIDGE_UCLASS since now Tegra DC driver has bridge support. Signed-off-by: Svyatoslav Ryhel --- drivers/video/tegra20/Kconfig | 2 +- drivers/video/tegra20/tegra-dsi.c | 9 +++++---- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/drivers/video/tegra20/Kconfig b/drivers/video/tegra20/Kconfig index ce990b4481f..598f9ea1f21 100644 --- a/drivers/video/tegra20/Kconfig +++ b/drivers/video/tegra20/Kconfig @@ -14,7 +14,7 @@ config VIDEO_TEGRA20 config VIDEO_DSI_TEGRA30 bool "Enable Tegra 30 DSI support" - depends on PANEL && DM_GPIO + depends on VIDEO_BRIDGE && PANEL && DM_GPIO select VIDEO_TEGRA20 select VIDEO_MIPI_DSI help diff --git a/drivers/video/tegra20/tegra-dsi.c b/drivers/video/tegra20/tegra-dsi.c index 9f39ac7589b..3ce0d33e380 100644 --- a/drivers/video/tegra20/tegra-dsi.c +++ b/drivers/video/tegra20/tegra-dsi.c @@ -11,6 +11,7 @@ #include #include #include +#include #include #include #include @@ -991,7 +992,7 @@ static int tegra_dsi_ganged_probe(struct udevice *dev) struct tegra_dsi_priv *mpriv = dev_get_priv(dev); struct udevice *gangster; - uclass_get_device_by_phandle(UCLASS_PANEL, dev, + uclass_get_device_by_phandle(UCLASS_VIDEO_BRIDGE, dev, "nvidia,ganged-mode", &gangster); if (gangster) { /* Ganged mode is set */ @@ -1118,8 +1119,8 @@ static int tegra_dsi_bridge_probe(struct udevice *dev) return 0; } -static const struct panel_ops tegra_dsi_bridge_ops = { - .enable_backlight = tegra_dsi_encoder_enable, +static const struct video_bridge_ops tegra_dsi_bridge_ops = { + .attach = tegra_dsi_encoder_enable, .set_backlight = tegra_dsi_bridge_set_panel, .get_display_timing = tegra_dsi_panel_timings, }; @@ -1133,7 +1134,7 @@ static const struct udevice_id tegra_dsi_bridge_ids[] = { U_BOOT_DRIVER(tegra_dsi) = { .name = "tegra_dsi", - .id = UCLASS_PANEL, + .id = UCLASS_VIDEO_BRIDGE, .of_match = tegra_dsi_bridge_ids, .ops = &tegra_dsi_bridge_ops, .bind = dm_scan_fdt_dev, From ae31d4347710e853b129deed0a0721ae42b584e0 Mon Sep 17 00:00:00 2001 From: Svyatoslav Ryhel Date: Fri, 21 Feb 2025 14:13:08 +0200 Subject: [PATCH 10/47] video: tegra20: dsi: respect speed mode used for DSI commands transfer Use DSI message flag to set correct speed mode for message transfer. Signed-off-by: Svyatoslav Ryhel --- drivers/video/tegra20/tegra-dsi.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/video/tegra20/tegra-dsi.c b/drivers/video/tegra20/tegra-dsi.c index 3ce0d33e380..a2a22fa0fe2 100644 --- a/drivers/video/tegra20/tegra-dsi.c +++ b/drivers/video/tegra20/tegra-dsi.c @@ -251,6 +251,9 @@ static ssize_t tegra_dsi_host_transfer(struct mipi_dsi_host *host, value = DSI_HOST_CONTROL_CRC_RESET | DSI_HOST_CONTROL_TX_TRIG_HOST | DSI_HOST_CONTROL_CS | DSI_HOST_CONTROL_ECC; + if ((msg->flags & MIPI_DSI_MSG_USE_LPM) == 0) + value |= DSI_HOST_CONTROL_HS; + /* * The host FIFO has a maximum of 64 words, so larger transmissions * need to use the video FIFO. From aeffe2abed0517acdbcd6b2d01ce36f13bc0fb61 Mon Sep 17 00:00:00 2001 From: Svyatoslav Ryhel Date: Fri, 14 Feb 2025 15:29:19 +0200 Subject: [PATCH 11/47] video: bridge: dp501: convert to video bridge UCLASS Switch from PANEL_UCLASS to VIDEO_BRIDGE_UCLASS since now its user driver has bridge support. Signed-off-by: Svyatoslav Ryhel --- drivers/video/bridge/Kconfig | 2 +- drivers/video/bridge/dp501.c | 27 +++++++++++---------------- 2 files changed, 12 insertions(+), 17 deletions(-) diff --git a/drivers/video/bridge/Kconfig b/drivers/video/bridge/Kconfig index 21c5a043e02..23fc26729ef 100644 --- a/drivers/video/bridge/Kconfig +++ b/drivers/video/bridge/Kconfig @@ -9,7 +9,7 @@ config VIDEO_BRIDGE config VIDEO_BRIDGE_PARADE_DP501 bool "Support Parade DP501 DP & DVI/HDMI dual mode transmitter" - depends on PANEL && DM_GPIO + depends on VIDEO_BRIDGE && PANEL && DM_GPIO select DM_I2C help The Parade DP501 is a DP & DVI/HDMI dual-mode transmitter. It diff --git a/drivers/video/bridge/dp501.c b/drivers/video/bridge/dp501.c index 095e3e71fed..9937cfe095b 100644 --- a/drivers/video/bridge/dp501.c +++ b/drivers/video/bridge/dp501.c @@ -9,6 +9,7 @@ #include #include #include +#include #include #include #include @@ -206,7 +207,6 @@ struct dp501_priv { struct udevice *chip2; struct udevice *vdd; - struct gpio_desc reset_gpio; struct gpio_desc enable_gpio; }; @@ -484,16 +484,19 @@ static int dp501_panel_timings(struct udevice *dev, return 0; } -static void dp501_hw_init(struct dp501_priv *priv) +static void dp501_hw_init(struct udevice *dev) { - dm_gpio_set_value(&priv->reset_gpio, 1); + struct dp501_priv *priv = dev_get_priv(dev); + struct video_bridge_priv *uc_priv = dev_get_uclass_priv(dev); + + dm_gpio_set_value(&uc_priv->reset, 1); regulator_set_enable_if_allowed(priv->vdd, 1); dm_gpio_set_value(&priv->enable_gpio, 1); udelay(100); - dm_gpio_set_value(&priv->reset_gpio, 0); + dm_gpio_set_value(&uc_priv->reset, 0); mdelay(80); } @@ -521,14 +524,6 @@ static int dp501_setup(struct udevice *dev) } /* get gpios */ - ret = gpio_request_by_name(dev, "reset-gpios", 0, - &priv->reset_gpio, GPIOD_IS_OUT); - if (ret) { - log_debug("%s: Could not decode reset-gpios (%d)\n", - __func__, ret); - return ret; - } - ret = gpio_request_by_name(dev, "enable-gpios", 0, &priv->enable_gpio, GPIOD_IS_OUT); if (ret) { @@ -544,7 +539,7 @@ static int dp501_setup(struct udevice *dev) return ret; } - dp501_hw_init(priv); + dp501_hw_init(dev); /* get EDID */ return panel_get_display_timing(priv->panel, &priv->timing); @@ -558,8 +553,8 @@ static int dp501_probe(struct udevice *dev) return dp501_setup(dev); } -struct panel_ops dp501_ops = { - .enable_backlight = dp501_attach, +static const struct video_bridge_ops dp501_ops = { + .attach = dp501_attach, .set_backlight = dp501_set_backlight, .get_display_timing = dp501_panel_timings, }; @@ -571,7 +566,7 @@ static const struct udevice_id dp501_ids[] = { U_BOOT_DRIVER(dp501) = { .name = "dp501", - .id = UCLASS_PANEL, + .id = UCLASS_VIDEO_BRIDGE, .of_match = dp501_ids, .ops = &dp501_ops, .probe = dp501_probe, From 44144f1ba9abee9f6db368cdbab24174dfbd4ec1 Mon Sep 17 00:00:00 2001 From: Svyatoslav Ryhel Date: Fri, 14 Feb 2025 15:28:28 +0200 Subject: [PATCH 12/47] video: bridge: tc358768: convert to video bridge UCLASS Switch from PANEL_UCLASS to VIDEO_BRIDGE_UCLASS since now its user driver has bridge support. Signed-off-by: Svyatoslav Ryhel --- drivers/video/bridge/Kconfig | 2 +- drivers/video/bridge/tc358768.c | 26 +++++++++++--------------- 2 files changed, 12 insertions(+), 16 deletions(-) diff --git a/drivers/video/bridge/Kconfig b/drivers/video/bridge/Kconfig index 23fc26729ef..79dba0e60ca 100644 --- a/drivers/video/bridge/Kconfig +++ b/drivers/video/bridge/Kconfig @@ -53,7 +53,7 @@ config VIDEO_BRIDGE_SOLOMON_SSD2825 config VIDEO_BRIDGE_TOSHIBA_TC358768 bool "Support Toshiba TC358768 MIPI DSI bridge" - depends on PANEL && DM_GPIO + depends on VIDEO_BRIDGE && PANEL && DM_GPIO select VIDEO_MIPI_DSI select DM_I2C help diff --git a/drivers/video/bridge/tc358768.c b/drivers/video/bridge/tc358768.c index 19b6ca29d3e..b5d45e0e3c9 100644 --- a/drivers/video/bridge/tc358768.c +++ b/drivers/video/bridge/tc358768.c @@ -12,6 +12,7 @@ #include #include #include +#include #include #include #include @@ -265,8 +266,10 @@ static void tc358768_sw_reset(struct udevice *dev) tc358768_write(dev, TC358768_SYSCTL, 0); } -static void tc358768_hw_enable(struct tc358768_priv *priv) +static void tc358768_hw_enable(struct udevice *dev) { + struct tc358768_priv *priv = dev_get_priv(dev); + struct video_bridge_priv *uc_priv = dev_get_uclass_priv(dev); int ret; ret = clk_prepare_enable(priv->refclk); @@ -293,7 +296,7 @@ static void tc358768_hw_enable(struct tc358768_priv *priv) * The RESX is active low (GPIO_ACTIVE_LOW). * DEASSERT (value = 0) the reset_gpio to enable the chip */ - ret = dm_gpio_set_value(&priv->reset_gpio, 0); + ret = dm_gpio_set_value(&uc_priv->reset, 0); if (ret) log_debug("%s: error changing reset-gpio (%d)\n", __func__, ret); @@ -477,7 +480,7 @@ static int tc358768_attach(struct udevice *dev) device->mode_flags &= ~MIPI_DSI_CLOCK_NON_CONTINUOUS; } - tc358768_hw_enable(priv); + tc358768_hw_enable(dev); tc358768_sw_reset(dev); tc358768_setup_pll(dev); @@ -877,6 +880,7 @@ static int tc358768_panel_timings(struct udevice *dev, static int tc358768_setup(struct udevice *dev) { struct tc358768_priv *priv = dev_get_priv(dev); + struct video_bridge_priv *uc_priv = dev_get_uclass_priv(dev); struct mipi_dsi_device *device = &priv->device; struct mipi_dsi_panel_plat *mipi_plat; int ret; @@ -942,15 +946,7 @@ static int tc358768_setup(struct udevice *dev) return PTR_ERR(priv->refclk); } - /* get gpios */ - ret = gpio_request_by_name(dev, "reset-gpios", 0, - &priv->reset_gpio, GPIOD_IS_OUT); - if (ret) { - log_debug("%s: Could not decode reset-gpios (%d)\n", __func__, ret); - return ret; - } - - dm_gpio_set_value(&priv->reset_gpio, 1); + dm_gpio_set_value(&uc_priv->reset, 1); return 0; } @@ -963,8 +959,8 @@ static int tc358768_probe(struct udevice *dev) return tc358768_setup(dev); } -struct panel_ops tc358768_ops = { - .enable_backlight = tc358768_attach, +static const struct video_bridge_ops tc358768_ops = { + .attach = tc358768_attach, .set_backlight = tc358768_set_backlight, .get_display_timing = tc358768_panel_timings, }; @@ -977,7 +973,7 @@ static const struct udevice_id tc358768_ids[] = { U_BOOT_DRIVER(tc358768) = { .name = "tc358768", - .id = UCLASS_PANEL, + .id = UCLASS_VIDEO_BRIDGE, .of_match = tc358768_ids, .ops = &tc358768_ops, .probe = tc358768_probe, From 82424ce784d77eba8be5c287297ae0f712db00ed Mon Sep 17 00:00:00 2001 From: Svyatoslav Ryhel Date: Fri, 21 Feb 2025 13:29:43 +0200 Subject: [PATCH 13/47] video: bridge: tc358768: convert to use of_graph Use OF graph parsing helpers to get linked panel. Signed-off-by: Svyatoslav Ryhel --- drivers/video/bridge/tc358768.c | 29 +++++++++++++++++++++++++---- 1 file changed, 25 insertions(+), 4 deletions(-) diff --git a/drivers/video/bridge/tc358768.c b/drivers/video/bridge/tc358768.c index b5d45e0e3c9..15bee19a152 100644 --- a/drivers/video/bridge/tc358768.c +++ b/drivers/video/bridge/tc358768.c @@ -6,6 +6,7 @@ #include #include +#include #include #include #include @@ -877,6 +878,26 @@ static int tc358768_panel_timings(struct udevice *dev, return 0; } +static int tc358768_get_panel(struct udevice *dev) +{ + struct tc358768_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_ofnode(UCLASS_PANEL, remote, + &priv->panel); + if (!ret) + return 0; + } + + /* If this point is reached, no panels were found */ + return -ENODEV; +} + static int tc358768_setup(struct udevice *dev) { struct tc358768_priv *priv = dev_get_priv(dev); @@ -893,11 +914,10 @@ static int tc358768_setup(struct udevice *dev) return ret; } - ret = uclass_get_device_by_phandle(UCLASS_PANEL, dev, - "panel", &priv->panel); + ret = tc358768_get_panel(dev); if (ret) { - log_debug("%s: Cannot get panel: ret=%d\n", __func__, ret); - return log_ret(ret); + log_debug("%s: panel not found, ret %d\n", __func__, ret); + return ret; } panel_get_display_timing(priv->panel, &priv->timing); @@ -976,6 +996,7 @@ U_BOOT_DRIVER(tc358768) = { .id = UCLASS_VIDEO_BRIDGE, .of_match = tc358768_ids, .ops = &tc358768_ops, + .bind = dm_scan_fdt_dev, .probe = tc358768_probe, .priv_auto = sizeof(struct tc358768_priv), }; From ec890ada4c04eb15e6d047fc62059d14f1456b99 Mon Sep 17 00:00:00 2001 From: Svyatoslav Ryhel Date: Sun, 23 Feb 2025 11:39:13 +0200 Subject: [PATCH 14/47] video: bridge: tc358768: simplify power supplies request Simplify power supply request logic. Signed-off-by: Svyatoslav Ryhel --- drivers/video/bridge/tc358768.c | 44 ++++++++++++++------------------- 1 file changed, 18 insertions(+), 26 deletions(-) diff --git a/drivers/video/bridge/tc358768.c b/drivers/video/bridge/tc358768.c index 15bee19a152..6f1b057c208 100644 --- a/drivers/video/bridge/tc358768.c +++ b/drivers/video/bridge/tc358768.c @@ -124,6 +124,10 @@ #define NANO 1000000000UL #define PICO 1000000000000ULL +static const char * const tc358768_supplies[] = { + "vddc-supply", "vddmipi-supply", "vddio-supply" +}; + struct tc358768_priv { struct mipi_dsi_host host; struct mipi_dsi_device device; @@ -131,9 +135,7 @@ struct tc358768_priv { struct udevice *panel; struct display_timing timing; - struct udevice *vddc; - struct udevice *vddmipi; - struct udevice *vddio; + struct udevice *supplies[ARRAY_SIZE(tc358768_supplies)]; struct clk *refclk; @@ -277,17 +279,17 @@ static void tc358768_hw_enable(struct udevice *dev) if (ret) log_debug("%s: error enabling refclk (%d)\n", __func__, ret); - ret = regulator_set_enable_if_allowed(priv->vddc, true); + ret = regulator_set_enable_if_allowed(priv->supplies[0], true); if (ret) log_debug("%s: error enabling vddc (%d)\n", __func__, ret); - ret = regulator_set_enable_if_allowed(priv->vddmipi, true); + ret = regulator_set_enable_if_allowed(priv->supplies[1], true); if (ret) log_debug("%s: error enabling vddmipi (%d)\n", __func__, ret); mdelay(10); - ret = regulator_set_enable_if_allowed(priv->vddio, true); + ret = regulator_set_enable_if_allowed(priv->supplies[2], true); if (ret) log_debug("%s: error enabling vddio (%d)\n", __func__, ret); @@ -904,7 +906,7 @@ static int tc358768_setup(struct udevice *dev) struct video_bridge_priv *uc_priv = dev_get_uclass_priv(dev); struct mipi_dsi_device *device = &priv->device; struct mipi_dsi_panel_plat *mipi_plat; - int ret; + int i, ret; /* The bridge uses 16 bit registers */ ret = i2c_set_chip_offset_len(dev, 2); @@ -937,25 +939,15 @@ static int tc358768_setup(struct udevice *dev) priv->dsi_lanes = device->lanes; /* get regulators */ - ret = device_get_supply_regulator(dev, "vddc-supply", &priv->vddc); - if (ret) { - log_debug("%s: vddc regulator error: %d\n", __func__, ret); - if (ret != -ENOENT) - return log_ret(ret); - } - - ret = device_get_supply_regulator(dev, "vddmipi-supply", &priv->vddmipi); - if (ret) { - log_debug("%s: vddmipi regulator error: %d\n", __func__, ret); - if (ret != -ENOENT) - return log_ret(ret); - } - - ret = device_get_supply_regulator(dev, "vddio-supply", &priv->vddio); - if (ret) { - log_debug("%s: vddio regulator error: %d\n", __func__, ret); - if (ret != -ENOENT) - return log_ret(ret); + for (i = 0; i < ARRAY_SIZE(tc358768_supplies); i++) { + ret = device_get_supply_regulator(dev, tc358768_supplies[i], + &priv->supplies[i]); + if (ret) { + log_debug("%s: cannot get %s %d\n", __func__, + tc358768_supplies[i], ret); + if (ret != -ENOENT) + return log_ret(ret); + } } /* get clk */ From b90513c8529186842142b42a18d00230a595aeba Mon Sep 17 00:00:00 2001 From: Svyatoslav Ryhel Date: Sun, 23 Feb 2025 11:41:10 +0200 Subject: [PATCH 15/47] video: bridge: tc358768: remove need in clock name Bridge uses only one clock and enforcing name to be set may cause issues in the future. Signed-off-by: Svyatoslav Ryhel --- drivers/video/bridge/tc358768.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/video/bridge/tc358768.c b/drivers/video/bridge/tc358768.c index 6f1b057c208..358004f30f2 100644 --- a/drivers/video/bridge/tc358768.c +++ b/drivers/video/bridge/tc358768.c @@ -951,7 +951,7 @@ static int tc358768_setup(struct udevice *dev) } /* get clk */ - priv->refclk = devm_clk_get(dev, "refclk"); + priv->refclk = devm_clk_get(dev, NULL); if (IS_ERR(priv->refclk)) { log_debug("%s: Could not get refclk: %ld\n", __func__, PTR_ERR(priv->refclk)); From 18e810e2bbef492e2d371ef37bdf1637f28f5a6b Mon Sep 17 00:00:00 2001 From: Svyatoslav Ryhel Date: Fri, 14 Feb 2025 15:27:20 +0200 Subject: [PATCH 16/47] video: bridge: ssd2825: convert to video bridge UCLASS Switch from PANEL_UCLASS to VIDEO_BRIDGE_UCLASS since now its user has bridge support. Signed-off-by: Svyatoslav Ryhel --- drivers/video/bridge/Kconfig | 4 ++-- drivers/video/bridge/ssd2825.c | 22 ++++++++-------------- 2 files changed, 10 insertions(+), 16 deletions(-) diff --git a/drivers/video/bridge/Kconfig b/drivers/video/bridge/Kconfig index 79dba0e60ca..be53034bd3d 100644 --- a/drivers/video/bridge/Kconfig +++ b/drivers/video/bridge/Kconfig @@ -46,10 +46,10 @@ config VIDEO_BRIDGE_ANALOGIX_ANX6345 config VIDEO_BRIDGE_SOLOMON_SSD2825 bool "Solomon SSD2825 bridge driver" - depends on PANEL && DM_GPIO + depends on VIDEO_BRIDGE && PANEL && DM_GPIO select VIDEO_MIPI_DSI help - Solomon SSD2824 SPI RGB-DSI bridge driver wrapped into panel uClass. + Solomon SSD2824 SPI RGB-DSI bridge driver. config VIDEO_BRIDGE_TOSHIBA_TC358768 bool "Support Toshiba TC358768 MIPI DSI bridge" diff --git a/drivers/video/bridge/ssd2825.c b/drivers/video/bridge/ssd2825.c index f978021c860..b1f08d7f38c 100644 --- a/drivers/video/bridge/ssd2825.c +++ b/drivers/video/bridge/ssd2825.c @@ -10,6 +10,7 @@ #include #include #include +#include #include #include #include @@ -114,7 +115,6 @@ struct ssd2825_bridge_priv { struct display_timing timing; struct gpio_desc power_gpio; - struct gpio_desc reset_gpio; struct clk *tx_clk; @@ -343,7 +343,7 @@ static void ssd2825_setup_pll(struct udevice *dev) ssd2825_write_register(dev, SSD2825_VC_CTRL_REG, 0x0000); } -static int ssd2825_bridge_enable_panel(struct udevice *dev) +static int ssd2825_bridge_attach(struct udevice *dev) { struct ssd2825_bridge_priv *priv = dev_get_priv(dev); struct mipi_dsi_device *device = &priv->device; @@ -407,6 +407,7 @@ static int ssd2825_bridge_panel_timings(struct udevice *dev, static int ssd2825_bridge_hw_init(struct udevice *dev) { struct ssd2825_bridge_priv *priv = dev_get_priv(dev); + struct video_bridge_priv *uc_priv = dev_get_uclass_priv(dev); int ret; ret = clk_prepare_enable(priv->tx_clk); @@ -424,7 +425,7 @@ static int ssd2825_bridge_hw_init(struct udevice *dev) } mdelay(10); - ret = dm_gpio_set_value(&priv->reset_gpio, 0); + ret = dm_gpio_set_value(&uc_priv->reset, 0); if (ret) { log_debug("%s: error changing reset-gpios (%d)\n", __func__, ret); @@ -432,7 +433,7 @@ static int ssd2825_bridge_hw_init(struct udevice *dev) } mdelay(10); - ret = dm_gpio_set_value(&priv->reset_gpio, 1); + ret = dm_gpio_set_value(&uc_priv->reset, 1); if (ret) { log_debug("%s: error changing reset-gpios (%d)\n", __func__, ret); @@ -485,13 +486,6 @@ static int ssd2825_bridge_probe(struct udevice *dev) return ret; } - ret = gpio_request_by_name(dev, "reset-gpios", 0, - &priv->reset_gpio, GPIOD_IS_OUT); - if (ret) { - log_err("could not decode reset-gpios (%d)\n", ret); - return ret; - } - /* get clk */ priv->tx_clk = devm_clk_get(dev, "tx_clk"); if (IS_ERR(priv->tx_clk)) { @@ -502,8 +496,8 @@ static int ssd2825_bridge_probe(struct udevice *dev) return ssd2825_bridge_hw_init(dev); } -static const struct panel_ops ssd2825_bridge_ops = { - .enable_backlight = ssd2825_bridge_enable_panel, +static const struct video_bridge_ops ssd2825_bridge_ops = { + .attach = ssd2825_bridge_attach, .set_backlight = ssd2825_bridge_set_panel, .get_display_timing = ssd2825_bridge_panel_timings, }; @@ -515,7 +509,7 @@ static const struct udevice_id ssd2825_bridge_ids[] = { U_BOOT_DRIVER(ssd2825) = { .name = "ssd2825", - .id = UCLASS_PANEL, + .id = UCLASS_VIDEO_BRIDGE, .of_match = ssd2825_bridge_ids, .ops = &ssd2825_bridge_ops, .probe = ssd2825_bridge_probe, From 0ef7e0c4a148a79b12b2a41fd91b7b7262e1a2b3 Mon Sep 17 00:00:00 2001 From: Svyatoslav Ryhel Date: Sat, 15 Feb 2025 19:48:20 +0200 Subject: [PATCH 17/47] video: bridge: ssd2825: convert to use of_graph Use OF graph parsing helpers to get linked panel. Signed-off-by: Svyatoslav Ryhel --- drivers/video/bridge/ssd2825.c | 27 ++++++++++++++++++++++++--- 1 file changed, 24 insertions(+), 3 deletions(-) diff --git a/drivers/video/bridge/ssd2825.c b/drivers/video/bridge/ssd2825.c index b1f08d7f38c..e3be3d22bb4 100644 --- a/drivers/video/bridge/ssd2825.c +++ b/drivers/video/bridge/ssd2825.c @@ -5,6 +5,7 @@ #include #include +#include #include #include #include @@ -444,6 +445,26 @@ static int ssd2825_bridge_hw_init(struct udevice *dev) return 0; } +static int ssd2825_bridge_get_panel(struct udevice *dev) +{ + struct ssd2825_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); + + 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 ssd2825_bridge_probe(struct udevice *dev) { struct ssd2825_bridge_priv *priv = dev_get_priv(dev); @@ -458,10 +479,9 @@ static int ssd2825_bridge_probe(struct udevice *dev) return ret; } - ret = uclass_get_device_by_phandle(UCLASS_PANEL, dev, - "panel", &priv->panel); + ret = ssd2825_bridge_get_panel(dev); if (ret) { - log_err("cannot get panel: ret=%d\n", ret); + log_debug("%s: panel not found, ret %d\n", __func__, ret); return ret; } @@ -512,6 +532,7 @@ U_BOOT_DRIVER(ssd2825) = { .id = UCLASS_VIDEO_BRIDGE, .of_match = ssd2825_bridge_ids, .ops = &ssd2825_bridge_ops, + .bind = dm_scan_fdt_dev, .probe = ssd2825_bridge_probe, .priv_auto = sizeof(struct ssd2825_bridge_priv), }; From 8433c7c92a043f38cbf4a7f0adbc64f395573199 Mon Sep 17 00:00:00 2001 From: Svyatoslav Ryhel Date: Tue, 18 Feb 2025 18:57:54 +0200 Subject: [PATCH 18/47] video: bridge: ssd2825: move post configuration from transfer function Reconfigure post panel enable bridge configuration. Signed-off-by: Svyatoslav Ryhel --- drivers/video/bridge/ssd2825.c | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/drivers/video/bridge/ssd2825.c b/drivers/video/bridge/ssd2825.c index e3be3d22bb4..df69f993ea1 100644 --- a/drivers/video/bridge/ssd2825.c +++ b/drivers/video/bridge/ssd2825.c @@ -232,7 +232,6 @@ static ssize_t ssd2825_bridge_transfer(struct mipi_dsi_host *host, const struct mipi_dsi_msg *msg) { struct udevice *dev = (struct udevice *)host->dev; - u8 buf = *(u8 *)msg->tx_buf; u16 config; int ret; @@ -261,15 +260,6 @@ static ssize_t ssd2825_bridge_transfer(struct mipi_dsi_host *host, ssd2825_write_register(dev, SSD2825_VC_CTRL_REG, 0x0000); ssd2825_write_dsi(dev, msg->tx_buf, msg->tx_len); - if (buf == MIPI_DCS_SET_DISPLAY_ON) { - ssd2825_write_register(dev, SSD2825_CONFIGURATION_REG, - SSD2825_CONF_REG_HS | SSD2825_CONF_REG_VEN | - SSD2825_CONF_REG_DCS | SSD2825_CONF_REG_ECD | - SSD2825_CONF_REG_EOT); - ssd2825_write_register(dev, SSD2825_PLL_CTRL_REG, 0x0001); - ssd2825_write_register(dev, SSD2825_VC_CTRL_REG, 0x0000); - } - return 0; } @@ -349,6 +339,7 @@ static int ssd2825_bridge_attach(struct udevice *dev) struct ssd2825_bridge_priv *priv = dev_get_priv(dev); struct mipi_dsi_device *device = &priv->device; struct display_timing *dt = &priv->timing; + int ret; /* Perform SW reset */ ssd2825_write_register(dev, SSD2825_OPERATION_CTRL_REG, 0x0100); @@ -385,7 +376,18 @@ static int ssd2825_bridge_attach(struct udevice *dev) ssd2825_write_register(dev, SSD2825_VC_CTRL_REG, 0x0000); /* Perform panel setup */ - return panel_enable_backlight(priv->panel); + ret = panel_enable_backlight(priv->panel); + if (ret) + return ret; + + ssd2825_write_register(dev, SSD2825_CONFIGURATION_REG, + SSD2825_CONF_REG_HS | SSD2825_CONF_REG_VEN | + SSD2825_CONF_REG_DCS | SSD2825_CONF_REG_ECD | + SSD2825_CONF_REG_EOT); + ssd2825_write_register(dev, SSD2825_PLL_CTRL_REG, 0x0001); + ssd2825_write_register(dev, SSD2825_VC_CTRL_REG, 0x0000); + + return 0; } static int ssd2825_bridge_set_panel(struct udevice *dev, int percent) From 980a6c043941f55ec2b92e78366b791d12a8f3a0 Mon Sep 17 00:00:00 2001 From: Svyatoslav Ryhel Date: Fri, 21 Feb 2025 13:54:45 +0200 Subject: [PATCH 19/47] video: bridge: ssd2825: add HS delays configuration Set HS Zero and Prepare delays from device tree. Signed-off-by: Svyatoslav Ryhel --- drivers/video/bridge/ssd2825.c | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/drivers/video/bridge/ssd2825.c b/drivers/video/bridge/ssd2825.c index df69f993ea1..e7c9dc6b62b 100644 --- a/drivers/video/bridge/ssd2825.c +++ b/drivers/video/bridge/ssd2825.c @@ -120,6 +120,9 @@ struct ssd2825_bridge_priv { struct clk *tx_clk; u32 pll_freq_kbps; /* PLL in kbps */ + + u32 hzd; /* HS Zero Delay in ns */ + u32 hpd; /* HS Prepare Delay is ns */ }; static int ssd2825_spi_write(struct udevice *dev, int reg, @@ -303,7 +306,9 @@ static void ssd2825_setup_pll(struct udevice *dev) struct mipi_dsi_device *device = &priv->device; struct display_timing *dt = &priv->timing; u16 pll_config, lp_div; + u32 nibble_delay, nibble_freq_khz; u32 pclk_mult, tx_freq_khz, pd_lines; + u8 hzd, hpd; tx_freq_khz = clk_get_rate(priv->tx_clk) / 1000; pd_lines = mipi_dsi_pixel_format_to_bpp(device->format); @@ -315,12 +320,19 @@ static void ssd2825_setup_pll(struct udevice *dev) lp_div = priv->pll_freq_kbps / (SSD2825_LP_MIN_CLK * 8); + /* nibble_delay in nanoseconds */ + nibble_freq_khz = priv->pll_freq_kbps / 4; + nibble_delay = 1000 * 1000 / nibble_freq_khz; + + hzd = priv->hzd / nibble_delay; + hpd = (priv->hpd - 4 * nibble_delay) / nibble_delay; + /* Disable PLL */ ssd2825_write_register(dev, SSD2825_PLL_CTRL_REG, 0x0000); ssd2825_write_register(dev, SSD2825_LINE_CTRL_REG, 0x0001); /* Set delays */ - ssd2825_write_register(dev, SSD2825_DELAY_ADJ_REG_1, 0x2103); + ssd2825_write_register(dev, SSD2825_DELAY_ADJ_REG_1, (hzd << 8) | hpd); /* Set PLL coeficients */ ssd2825_write_register(dev, SSD2825_PLL_CONFIGURATION_REG, pll_config); @@ -515,6 +527,9 @@ static int ssd2825_bridge_probe(struct udevice *dev) return PTR_ERR(priv->tx_clk); } + priv->hzd = dev_read_u32_default(dev, "solomon,hs-zero-delay-ns", 133); + priv->hpd = dev_read_u32_default(dev, "solomon,hs-prep-delay-ns", 40); + return ssd2825_bridge_hw_init(dev); } From 86b0c2f2e8fed503a51065664cf41bd59dcdfe52 Mon Sep 17 00:00:00 2001 From: Svyatoslav Ryhel Date: Fri, 21 Feb 2025 13:59:35 +0200 Subject: [PATCH 20/47] video: bridge: ssd2825: make pixel format calculation more obvious Use switch condition to get pixel format. Signed-off-by: Svyatoslav Ryhel --- drivers/video/bridge/ssd2825.c | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/drivers/video/bridge/ssd2825.c b/drivers/video/bridge/ssd2825.c index e7c9dc6b62b..eafd9f55913 100644 --- a/drivers/video/bridge/ssd2825.c +++ b/drivers/video/bridge/ssd2825.c @@ -351,8 +351,26 @@ static int ssd2825_bridge_attach(struct udevice *dev) struct ssd2825_bridge_priv *priv = dev_get_priv(dev); struct mipi_dsi_device *device = &priv->device; struct display_timing *dt = &priv->timing; + u8 pixel_format; int ret; + /* Set pixel format */ + switch (device->format) { + case MIPI_DSI_FMT_RGB565: + pixel_format = 0x00; + break; + case MIPI_DSI_FMT_RGB666_PACKED: + pixel_format = 0x01; + break; + case MIPI_DSI_FMT_RGB666: + pixel_format = 0x02; + break; + case MIPI_DSI_FMT_RGB888: + default: + pixel_format = 0x03; + break; + } + /* Perform SW reset */ ssd2825_write_register(dev, SSD2825_OPERATION_CTRL_REG, 0x0100); @@ -371,7 +389,7 @@ static int ssd2825_bridge_attach(struct udevice *dev) ssd2825_write_register(dev, SSD2825_RGB_INTERFACE_CTRL_REG_6, SSD2825_HSYNC_HIGH | SSD2825_VSYNC_HIGH | SSD2825_PCKL_HIGH | SSD2825_NON_BURST | - (3 - device->format)); + pixel_format); ssd2825_write_register(dev, SSD2825_LANE_CONFIGURATION_REG, device->lanes - 1); ssd2825_write_register(dev, SSD2825_TEST_REG, 0x0004); From 4b03bd25086b5ba7d481c1cd6ec2364b6aff70c2 Mon Sep 17 00:00:00 2001 From: Svyatoslav Ryhel Date: Fri, 21 Feb 2025 14:06:00 +0200 Subject: [PATCH 21/47] video: bridge: ssd2825: set default minimum tx_clk If TX_CLK is not set or gives an error, use SSD2825_REF_MIN_CLK. Signed-off-by: Svyatoslav Ryhel --- drivers/video/bridge/ssd2825.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/video/bridge/ssd2825.c b/drivers/video/bridge/ssd2825.c index eafd9f55913..b8653cc7297 100644 --- a/drivers/video/bridge/ssd2825.c +++ b/drivers/video/bridge/ssd2825.c @@ -311,6 +311,9 @@ static void ssd2825_setup_pll(struct udevice *dev) u8 hzd, hpd; tx_freq_khz = clk_get_rate(priv->tx_clk) / 1000; + if (!tx_freq_khz || tx_freq_khz < 0) + tx_freq_khz = SSD2825_REF_MIN_CLK; + pd_lines = mipi_dsi_pixel_format_to_bpp(device->format); pclk_mult = pd_lines / device->lanes + 1; @@ -539,7 +542,7 @@ static int ssd2825_bridge_probe(struct udevice *dev) } /* get clk */ - priv->tx_clk = devm_clk_get(dev, "tx_clk"); + priv->tx_clk = devm_clk_get_optional(dev, NULL); if (IS_ERR(priv->tx_clk)) { log_err("cannot get tx_clk: %ld\n", PTR_ERR(priv->tx_clk)); return PTR_ERR(priv->tx_clk); From b17471ae41a0d7601e91cf02d34f115c4640fe50 Mon Sep 17 00:00:00 2001 From: Svyatoslav Ryhel Date: Fri, 21 Feb 2025 18:37:35 +0200 Subject: [PATCH 22/47] video: bridge: ssd2825: add power supplies Convert enable GPIO into a set of supplies according to datasheet. Signed-off-by: Svyatoslav Ryhel --- drivers/video/bridge/ssd2825.c | 40 +++++++++++++++++++++++----------- 1 file changed, 27 insertions(+), 13 deletions(-) diff --git a/drivers/video/bridge/ssd2825.c b/drivers/video/bridge/ssd2825.c index b8653cc7297..2a49b895404 100644 --- a/drivers/video/bridge/ssd2825.c +++ b/drivers/video/bridge/ssd2825.c @@ -13,6 +13,7 @@ #include #include #include +#include #include #include #include @@ -108,6 +109,10 @@ #define SSD2825_LP_MIN_CLK 5000 /* KHz */ #define SSD2825_REF_MIN_CLK 2000 /* KHz */ +static const char * const ssd2825_supplies[] = { + "dvdd-supply", "avdd-supply", "vddio-supply" +}; + struct ssd2825_bridge_priv { struct mipi_dsi_host host; struct mipi_dsi_device device; @@ -115,6 +120,8 @@ struct ssd2825_bridge_priv { struct udevice *panel; struct display_timing timing; + struct udevice *supplies[ARRAY_SIZE(ssd2825_supplies)]; + struct gpio_desc power_gpio; struct clk *tx_clk; @@ -444,7 +451,7 @@ static int ssd2825_bridge_hw_init(struct udevice *dev) { struct ssd2825_bridge_priv *priv = dev_get_priv(dev); struct video_bridge_priv *uc_priv = dev_get_uclass_priv(dev); - int ret; + int i, ret; ret = clk_prepare_enable(priv->tx_clk); if (ret) { @@ -453,11 +460,14 @@ static int ssd2825_bridge_hw_init(struct udevice *dev) return ret; } - ret = dm_gpio_set_value(&priv->power_gpio, 1); - if (ret) { - log_debug("%s: error changing power-gpios (%d)\n", - __func__, ret); - return ret; + /* enable supplies */ + for (i = 0; i < ARRAY_SIZE(ssd2825_supplies); i++) { + ret = regulator_set_enable_if_allowed(priv->supplies[i], 1); + if (ret) { + log_debug("%s: cannot enable %s %d\n", __func__, + ssd2825_supplies[i], ret); + return ret; + } } mdelay(10); @@ -506,7 +516,7 @@ static int ssd2825_bridge_probe(struct udevice *dev) struct spi_slave *slave = dev_get_parent_priv(dev); struct mipi_dsi_device *device = &priv->device; struct mipi_dsi_panel_plat *mipi_plat; - int ret; + int i, ret; ret = spi_claim_bus(slave); if (ret) { @@ -533,12 +543,16 @@ static int ssd2825_bridge_probe(struct udevice *dev) device->format = mipi_plat->format; device->mode_flags = mipi_plat->mode_flags; - /* get panel gpios */ - ret = gpio_request_by_name(dev, "power-gpios", 0, - &priv->power_gpio, GPIOD_IS_OUT); - if (ret) { - log_err("could not decode power-gpios (%d)\n", ret); - return ret; + /* get supplies */ + for (i = 0; i < ARRAY_SIZE(ssd2825_supplies); i++) { + ret = device_get_supply_regulator(dev, ssd2825_supplies[i], + &priv->supplies[i]); + if (ret) { + log_debug("%s: cannot get %s %d\n", __func__, + ssd2825_supplies[i], ret); + if (ret != -ENOENT) + return log_ret(ret); + } } /* get clk */ From bf2753796fd37659580983e4efd2963aa15786e5 Mon Sep 17 00:00:00 2001 From: Svyatoslav Ryhel Date: Wed, 5 Mar 2025 08:31:35 +0200 Subject: [PATCH 23/47] video: bridge: ssd2825: fix reset gpio direction The reset GPIO signal operates with a low-active logic. The driver needs to be adjusted to correctly handle this. Signed-off-by: Svyatoslav Ryhel --- drivers/video/bridge/ssd2825.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/video/bridge/ssd2825.c b/drivers/video/bridge/ssd2825.c index 2a49b895404..a307993377c 100644 --- a/drivers/video/bridge/ssd2825.c +++ b/drivers/video/bridge/ssd2825.c @@ -471,17 +471,17 @@ static int ssd2825_bridge_hw_init(struct udevice *dev) } mdelay(10); - ret = dm_gpio_set_value(&uc_priv->reset, 0); + ret = dm_gpio_set_value(&uc_priv->reset, 1); if (ret) { - log_debug("%s: error changing reset-gpios (%d)\n", + log_debug("%s: error entering reset (%d)\n", __func__, ret); return ret; } mdelay(10); - ret = dm_gpio_set_value(&uc_priv->reset, 1); + ret = dm_gpio_set_value(&uc_priv->reset, 0); if (ret) { - log_debug("%s: error changing reset-gpios (%d)\n", + log_debug("%s: error exiting reset (%d)\n", __func__, ret); return ret; } From 467f9275e73913e01b5e3813350c2caed468e462 Mon Sep 17 00:00:00 2001 From: Svyatoslav Ryhel Date: Sat, 1 Mar 2025 14:37:59 +0200 Subject: [PATCH 24/47] video: endeavoru-panel: move backlight request after probe Due to the use of the Tegra DC backlight feature by the HTC ONE X, backlight requests MUST NOT be made during probe or earlier. This is because it creates a loop, as the backlight is a DC child. To mitigate this issue, backlight requests can be made later, once the backlight is actively used. Signed-off-by: Svyatoslav Ryhel --- drivers/video/endeavoru-panel.c | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/drivers/video/endeavoru-panel.c b/drivers/video/endeavoru-panel.c index d4ba4d8b6da..90f838ecc20 100644 --- a/drivers/video/endeavoru-panel.c +++ b/drivers/video/endeavoru-panel.c @@ -117,6 +117,18 @@ static int endeavoru_panel_set_backlight(struct udevice *dev, int percent) struct endeavoru_panel_priv *priv = dev_get_priv(dev); int ret; + /* + * Due to the use of the Tegra DC backlight feature, backlight + * requests MUST NOT be made during probe or earlier. This is + * because it creates a loop, as the backlight is a DC child. + */ + ret = uclass_get_device_by_phandle(UCLASS_PANEL_BACKLIGHT, dev, + "backlight", &priv->backlight); + if (ret) { + log_err("cannot get backlight: ret = %d\n", ret); + return ret; + } + ret = backlight_enable(priv->backlight); if (ret) return ret; @@ -136,13 +148,6 @@ static int endeavoru_panel_of_to_plat(struct udevice *dev) struct endeavoru_panel_priv *priv = dev_get_priv(dev); int ret; - ret = uclass_get_device_by_phandle(UCLASS_PANEL_BACKLIGHT, dev, - "backlight", &priv->backlight); - if (ret) { - log_err("cannot get backlight: ret = %d\n", ret); - return ret; - } - ret = uclass_get_device_by_phandle(UCLASS_REGULATOR, dev, "vdd-supply", &priv->vdd); if (ret) { From 620b11de9919ab2402eb9f40535b3d33cdb3099c Mon Sep 17 00:00:00 2001 From: Svyatoslav Ryhel Date: Fri, 21 Feb 2025 16:01:07 +0200 Subject: [PATCH 25/47] video: endeavoru-panel: add missing LPM flag Add missing MIPI_DSI_MODE_LPM mode flag. Signed-off-by: Svyatoslav Ryhel --- drivers/video/endeavoru-panel.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/video/endeavoru-panel.c b/drivers/video/endeavoru-panel.c index 90f838ecc20..9950ff8bb05 100644 --- a/drivers/video/endeavoru-panel.c +++ b/drivers/video/endeavoru-panel.c @@ -236,7 +236,7 @@ static int endeavoru_panel_probe(struct udevice *dev) /* fill characteristics of DSI data link */ plat->lanes = 2; plat->format = MIPI_DSI_FMT_RGB888; - plat->mode_flags = MIPI_DSI_MODE_VIDEO; + plat->mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_LPM; return endeavoru_panel_hw_init(dev); } From 80f6949dd3c99586711921c591ee7793b333af98 Mon Sep 17 00:00:00 2001 From: Svyatoslav Ryhel Date: Fri, 21 Feb 2025 16:03:18 +0200 Subject: [PATCH 26/47] video: lg-ld070wx3: add missing LPM flag Add missing MIPI_DSI_MODE_LPM mode flag. Signed-off-by: Svyatoslav Ryhel --- drivers/video/lg-ld070wx3.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/video/lg-ld070wx3.c b/drivers/video/lg-ld070wx3.c index 610a06ffe7b..3676e45bc65 100644 --- a/drivers/video/lg-ld070wx3.c +++ b/drivers/video/lg-ld070wx3.c @@ -158,7 +158,7 @@ static int lg_ld070wx3_probe(struct udevice *dev) /* fill characteristics of DSI data link */ plat->lanes = 4; plat->format = MIPI_DSI_FMT_RGB888; - plat->mode_flags = MIPI_DSI_MODE_VIDEO; + plat->mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_LPM; return lg_ld070wx3_hw_init(dev); } From 94cb42bb3e7fbc684d5e8bfd6eb663c5c3dbdf2a Mon Sep 17 00:00:00 2001 From: Svyatoslav Ryhel Date: Fri, 21 Feb 2025 16:06:16 +0200 Subject: [PATCH 27/47] video: renesas-r61307: add missing mode flags Add missing MIPI DSI mode flags. Signed-off-by: Svyatoslav Ryhel --- drivers/video/renesas-r61307.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/video/renesas-r61307.c b/drivers/video/renesas-r61307.c index a3697bce5ee..e3623d72635 100644 --- a/drivers/video/renesas-r61307.c +++ b/drivers/video/renesas-r61307.c @@ -281,7 +281,8 @@ static int renesas_r61307_probe(struct udevice *dev) /* fill characteristics of DSI data link */ plat->lanes = 4; plat->format = MIPI_DSI_FMT_RGB888; - plat->mode_flags = MIPI_DSI_MODE_VIDEO; + plat->mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_SYNC_PULSE | + MIPI_DSI_CLOCK_NON_CONTINUOUS | MIPI_DSI_MODE_LPM; return renesas_r61307_hw_init(dev); } From 11b4ee5450c30395b7fd05418a3b7a2e0d551c75 Mon Sep 17 00:00:00 2001 From: Svyatoslav Ryhel Date: Tue, 4 Mar 2025 11:48:15 +0200 Subject: [PATCH 28/47] video: renesas-r61307: adjust compatible Vendor prefix of Hitachi should be "hit" to comply Linux vendor prefix list. Signed-off-by: Svyatoslav Ryhel --- drivers/video/renesas-r61307.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/video/renesas-r61307.c b/drivers/video/renesas-r61307.c index e3623d72635..8552c3dd959 100644 --- a/drivers/video/renesas-r61307.c +++ b/drivers/video/renesas-r61307.c @@ -295,7 +295,7 @@ static const struct panel_ops renesas_r61307_ops = { static const struct udevice_id renesas_r61307_ids[] = { { .compatible = "koe,tx13d100vm0eaa" }, - { .compatible = "hitachi,tx13d100vm0eaa" }, + { .compatible = "hit,tx13d100vm0eaa" }, { } }; From 7c8601de92a4bd618a89ce93ed1b49aaf8504c88 Mon Sep 17 00:00:00 2001 From: Svyatoslav Ryhel Date: Tue, 4 Mar 2025 21:13:33 +0200 Subject: [PATCH 29/47] video: renesas-r61307: fix reset gpio direction The reset GPIO signal operates with a low-active logic. The driver needs to be adjusted to correctly handle this. Signed-off-by: Svyatoslav Ryhel --- drivers/video/renesas-r61307.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/video/renesas-r61307.c b/drivers/video/renesas-r61307.c index 8552c3dd959..ef6fab1e953 100644 --- a/drivers/video/renesas-r61307.c +++ b/drivers/video/renesas-r61307.c @@ -254,17 +254,17 @@ static int renesas_r61307_hw_init(struct udevice *dev) return ret; } - ret = dm_gpio_set_value(&priv->reset_gpio, 0); + ret = dm_gpio_set_value(&priv->reset_gpio, 1); if (ret) { - log_debug("%s: changing reset-gpio failed (%d)\n", + log_debug("%s: entering reset failed (%d)\n", __func__, ret); return ret; } mdelay(5); - ret = dm_gpio_set_value(&priv->reset_gpio, 1); + ret = dm_gpio_set_value(&priv->reset_gpio, 0); if (ret) { - log_debug("%s: changing reset-gpio failed (%d)\n", + log_debug("%s: exiting reset failed (%d)\n", __func__, ret); return ret; } From 1403310bb1de67c5608d92da58ebd5baf339419e Mon Sep 17 00:00:00 2001 From: Svyatoslav Ryhel Date: Fri, 21 Feb 2025 16:08:10 +0200 Subject: [PATCH 30/47] video: renesas-r69328: add missing mode flags Add missing MIPI DSI mode flags. Signed-off-by: Svyatoslav Ryhel --- drivers/video/renesas-r69328.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/video/renesas-r69328.c b/drivers/video/renesas-r69328.c index 9861c3fef11..1147785c1e2 100644 --- a/drivers/video/renesas-r69328.c +++ b/drivers/video/renesas-r69328.c @@ -216,7 +216,8 @@ static int renesas_r69328_probe(struct udevice *dev) /* fill characteristics of DSI data link */ plat->lanes = 4; plat->format = MIPI_DSI_FMT_RGB888; - plat->mode_flags = MIPI_DSI_MODE_VIDEO; + plat->mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_SYNC_PULSE | + MIPI_DSI_CLOCK_NON_CONTINUOUS | MIPI_DSI_MODE_LPM; return renesas_r69328_hw_init(dev); } From 4ecc5d5a3968f10ae1726c4e4ec0aea6781a45c3 Mon Sep 17 00:00:00 2001 From: Svyatoslav Ryhel Date: Tue, 4 Mar 2025 21:22:04 +0200 Subject: [PATCH 31/47] video: renesas-r69328: fix reset gpio direction The reset GPIO signal operates with a low-active logic. The driver needs to be adjusted to correctly handle this. Signed-off-by: Svyatoslav Ryhel --- drivers/video/renesas-r69328.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/video/renesas-r69328.c b/drivers/video/renesas-r69328.c index 1147785c1e2..164285e3c8e 100644 --- a/drivers/video/renesas-r69328.c +++ b/drivers/video/renesas-r69328.c @@ -189,17 +189,17 @@ static int renesas_r69328_hw_init(struct udevice *dev) } mdelay(5); - ret = dm_gpio_set_value(&priv->reset_gpio, 0); + ret = dm_gpio_set_value(&priv->reset_gpio, 1); if (ret) { - log_debug("%s: error changing reset-gpios (%d)\n", + log_debug("%s: error entering reset (%d)\n", __func__, ret); return ret; } mdelay(5); - ret = dm_gpio_set_value(&priv->reset_gpio, 1); + ret = dm_gpio_set_value(&priv->reset_gpio, 0); if (ret) { - log_debug("%s: error changing reset-gpios (%d)\n", + log_debug("%s: error exiting reset (%d)\n", __func__, ret); return ret; } From 629290212f7efe46cf5b59d3cbb03f31d02c2258 Mon Sep 17 00:00:00 2001 From: Svyatoslav Ryhel Date: Tue, 4 Mar 2025 21:29:01 +0200 Subject: [PATCH 32/47] video: renesas-r69328: add power supplies Convert enable GPIO into a set of supplies. Signed-off-by: Svyatoslav Ryhel --- drivers/video/renesas-r69328.c | 26 ++++++++++++++++++++------ 1 file changed, 20 insertions(+), 6 deletions(-) diff --git a/drivers/video/renesas-r69328.c b/drivers/video/renesas-r69328.c index 164285e3c8e..0954b04b62e 100644 --- a/drivers/video/renesas-r69328.c +++ b/drivers/video/renesas-r69328.c @@ -32,9 +32,11 @@ #define R69328_POWER_SET 0xD1 struct renesas_r69328_priv { + struct udevice *vdd; + struct udevice *vddio; + struct udevice *backlight; - struct gpio_desc enable_gpio; struct gpio_desc reset_gpio; }; @@ -159,10 +161,15 @@ static int renesas_r69328_of_to_plat(struct udevice *dev) return ret; } - ret = gpio_request_by_name(dev, "enable-gpios", 0, - &priv->enable_gpio, GPIOD_IS_OUT); + ret = device_get_supply_regulator(dev, "vdd-supply", &priv->vdd); if (ret) { - log_err("could not decode enable-gpios (%d)\n", ret); + log_err("Cannot get vdd-supply: ret = %d\n", ret); + return ret; + } + + ret = device_get_supply_regulator(dev, "vddio-supply", &priv->vddio); + if (ret) { + log_err("Cannot get vddio-supply: ret = %d\n", ret); return ret; } @@ -181,14 +188,21 @@ static int renesas_r69328_hw_init(struct udevice *dev) struct renesas_r69328_priv *priv = dev_get_priv(dev); int ret; - ret = dm_gpio_set_value(&priv->enable_gpio, 1); + ret = regulator_set_enable_if_allowed(priv->vddio, 1); if (ret) { - log_debug("%s: error changing enable-gpios (%d)\n", + log_debug("%s: enabling vddio-supply failed (%d)\n", __func__, ret); return ret; } mdelay(5); + ret = regulator_set_enable_if_allowed(priv->vdd, 1); + if (ret) { + log_debug("%s: enabling vdd-supply failed (%d)\n", + __func__, ret); + return ret; + } + ret = dm_gpio_set_value(&priv->reset_gpio, 1); if (ret) { log_debug("%s: error entering reset (%d)\n", From e0a93d3a22931d6d92528c2d8840367c74d552b8 Mon Sep 17 00:00:00 2001 From: Svyatoslav Ryhel Date: Fri, 21 Feb 2025 16:16:11 +0200 Subject: [PATCH 33/47] video: samsung-ltl106hl02: add missing LPM flag Add missing MIPI_DSI_MODE_LPM mode flag. Signed-off-by: Svyatoslav Ryhel --- drivers/video/samsung-ltl106hl02.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/video/samsung-ltl106hl02.c b/drivers/video/samsung-ltl106hl02.c index 5e6c11c4be3..1efc9fca610 100644 --- a/drivers/video/samsung-ltl106hl02.c +++ b/drivers/video/samsung-ltl106hl02.c @@ -129,7 +129,7 @@ static int samsung_ltl106hl02_probe(struct udevice *dev) /* fill characteristics of DSI data link */ plat->lanes = 4; plat->format = MIPI_DSI_FMT_RGB888; - plat->mode_flags = MIPI_DSI_MODE_VIDEO; + plat->mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_LPM; return samsung_ltl106hl02_hw_init(dev); } From 188fc54f97d3f76e79cd0cd1b8b1b60c445cdf8d Mon Sep 17 00:00:00 2001 From: Svyatoslav Ryhel Date: Fri, 21 Feb 2025 16:18:24 +0200 Subject: [PATCH 34/47] video: sharp-lq101r1sx01: add missing LPM flag Add missing MIPI_DSI_MODE_LPM mode flag. Signed-off-by: Svyatoslav Ryhel --- drivers/video/sharp-lq101r1sx01.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/video/sharp-lq101r1sx01.c b/drivers/video/sharp-lq101r1sx01.c index 5d8453fd796..4fdf0da8a94 100644 --- a/drivers/video/sharp-lq101r1sx01.c +++ b/drivers/video/sharp-lq101r1sx01.c @@ -255,6 +255,7 @@ static int sharp_lq101r1sx01_probe(struct udevice *dev) /* fill characteristics of DSI data link */ plat->lanes = 4; plat->format = MIPI_DSI_FMT_RGB888; + plat->mode_flags = MIPI_DSI_MODE_LPM; return sharp_lq101r1sx01_hw_init(dev); } From c3eb558288d1b3c4b9ebde3d08310622b63f7afe Mon Sep 17 00:00:00 2001 From: Svyatoslav Ryhel Date: Fri, 21 Feb 2025 17:05:37 +0200 Subject: [PATCH 35/47] video: backlight: lm3533: add more flexibility with device tree Configure LM3533 based on preliminary device tree configuration. Signed-off-by: Svyatoslav Ryhel --- drivers/video/lm3533_backlight.c | 65 +++++++++++++++++++++++++++++--- 1 file changed, 59 insertions(+), 6 deletions(-) diff --git a/drivers/video/lm3533_backlight.c b/drivers/video/lm3533_backlight.c index 6b51fa0628e..a1a7397cbdc 100644 --- a/drivers/video/lm3533_backlight.c +++ b/drivers/video/lm3533_backlight.c @@ -7,6 +7,7 @@ #include #include +#include #include #include #include @@ -24,9 +25,23 @@ #define LM3533_OVP_FREQUENCY_PWM_POLARITY 0x2C #define LM3533_BRIGHTNESS_REGISTER_A 0x40 +#define LM3533_BOOST_OVP_16V 16000000UL +#define LM3533_BOOST_FREQ_500KHZ 500000UL + struct lm3533_backlight_priv { struct gpio_desc enable_gpio; u32 def_bl_lvl; + + /* Core */ + u32 boost_ovp; + u32 boost_freq; + + /* Backlight */ + u32 reg; + u16 max_current; /* 5000 - 29800 uA (800 uA step) */ + u8 pwm; /* 0 - 0x3f */ + bool linear; + bool hvled; }; static int lm3533_backlight_enable(struct udevice *dev) @@ -92,14 +107,12 @@ static int lm3533_backlight_set_brightness(struct udevice *dev, int percent) return 0; } -static int lm3533_backlight_probe(struct udevice *dev) +static int lm3533_backlight_of_to_plat(struct udevice *dev) { struct lm3533_backlight_priv *priv = dev_get_priv(dev); + ofnode child; int ret; - if (device_get_uclass_id(dev->parent) != UCLASS_I2C) - return -EPROTONOSUPPORT; - ret = gpio_request_by_name(dev, "enable-gpios", 0, &priv->enable_gpio, GPIOD_IS_OUT); if (ret) { @@ -107,8 +120,47 @@ static int lm3533_backlight_probe(struct udevice *dev) return ret; } - priv->def_bl_lvl = dev_read_u32_default(dev, "default-brightness-level", - LM3533_BL_MAX_BRIGHTNESS); + priv->boost_ovp = dev_read_u32_default(dev, "ti,boost-ovp-microvolt", + LM3533_BOOST_OVP_16V); + + /* boost_ovp is defined in microvolts, convert to enum value */ + priv->boost_ovp = priv->boost_ovp / (8 * 1000 * 1000) - 2; + + priv->boost_freq = dev_read_u32_default(dev, "ti,boost-freq-hz", + LM3533_BOOST_FREQ_500KHZ); + + /* boost_freq is defined in Hz, convert to enum value */ + priv->boost_freq = priv->boost_freq / (500 * 1000) - 1; + + /* Backlight is one of children but has no dedicated driver */ + ofnode_for_each_subnode(child, dev_ofnode(dev)) { + if (ofnode_device_is_compatible(child, "ti,lm3533-backlight")) { + const char *node_name = ofnode_get_name(child); + + if (!strcmp(&node_name[10], "1")) + priv->reg = 1; + else + priv->reg = 0; + + priv->max_current = ofnode_read_u32_default(child, "ti,max-current-microamp", + 5000); + priv->pwm = ofnode_read_u32_default(child, "ti,pwm-config-mask", 0); + + priv->def_bl_lvl = ofnode_read_u32_default(child, "default-brightness", + LM3533_BL_MAX_BRIGHTNESS); + + priv->linear = ofnode_read_bool(child, "ti,linear-mapping-mode"); + priv->hvled = ofnode_read_bool(child, "ti,hardware-controlled"); + } + } + + return 0; +} + +static int lm3533_backlight_probe(struct udevice *dev) +{ + if (device_get_uclass_id(dev->parent) != UCLASS_I2C) + return -EPROTONOSUPPORT; return 0; } @@ -127,6 +179,7 @@ U_BOOT_DRIVER(lm3533_backlight) = { .name = "lm3533_backlight", .id = UCLASS_PANEL_BACKLIGHT, .of_match = lm3533_backlight_ids, + .of_to_plat = lm3533_backlight_of_to_plat, .probe = lm3533_backlight_probe, .ops = &lm3533_backlight_ops, .priv_auto = sizeof(struct lm3533_backlight_priv), From 1d4e23d3d4fe90071b29a381f0ea04214d45b181 Mon Sep 17 00:00:00 2001 From: Svyatoslav Ryhel Date: Fri, 21 Feb 2025 17:22:47 +0200 Subject: [PATCH 36/47] video: backlight: lm3533: configure core in the probe Configure core stuff in the probe. Signed-off-by: Svyatoslav Ryhel --- drivers/video/lm3533_backlight.c | 31 ++++++++++++++++++++++++------- 1 file changed, 24 insertions(+), 7 deletions(-) diff --git a/drivers/video/lm3533_backlight.c b/drivers/video/lm3533_backlight.c index a1a7397cbdc..f97f17fec4e 100644 --- a/drivers/video/lm3533_backlight.c +++ b/drivers/video/lm3533_backlight.c @@ -23,6 +23,10 @@ #define LM3533_CONTROL_BANK_A_FULLSCALE_CURRENT 0x1F #define LM3533_CONTROL_BANK_ENABLE 0x27 #define LM3533_OVP_FREQUENCY_PWM_POLARITY 0x2C +#define BOOST_OVP_MASK GENMASK(2, 1) +#define BOOST_OVP_SHIFT 1 +#define BOOST_FREQ_MASK BIT(0) +#define BOOST_FREQ_SHIFT 0 #define LM3533_BRIGHTNESS_REGISTER_A 0x40 #define LM3533_BOOST_OVP_16V 16000000UL @@ -49,9 +53,6 @@ static int lm3533_backlight_enable(struct udevice *dev) struct lm3533_backlight_priv *priv = dev_get_priv(dev); int ret; - dm_gpio_set_value(&priv->enable_gpio, 1); - mdelay(5); - /* HVLED 1 & 2 are controlled by Bank A */ ret = dm_i2c_reg_write(dev, LM3533_SINK_OUTPUT_CONFIG_1, 0x00); if (ret) @@ -77,10 +78,6 @@ static int lm3533_backlight_enable(struct udevice *dev) if (ret) return ret; - ret = dm_i2c_reg_write(dev, LM3533_OVP_FREQUENCY_PWM_POLARITY, 0x0A); - if (ret) - return ret; - return 0; } @@ -159,9 +156,29 @@ static int lm3533_backlight_of_to_plat(struct udevice *dev) static int lm3533_backlight_probe(struct udevice *dev) { + struct lm3533_backlight_priv *priv = dev_get_priv(dev); + int ret; + if (device_get_uclass_id(dev->parent) != UCLASS_I2C) return -EPROTONOSUPPORT; + dm_gpio_set_value(&priv->enable_gpio, 1); + mdelay(5); + + ret = dm_i2c_reg_clrset(dev, LM3533_OVP_FREQUENCY_PWM_POLARITY, + BOOST_FREQ_MASK, priv->boost_freq << BOOST_FREQ_SHIFT); + if (ret) { + log_debug("%s: freq config failed %d\n", __func__, ret); + return ret; + } + + ret = dm_i2c_reg_clrset(dev, LM3533_OVP_FREQUENCY_PWM_POLARITY, + BOOST_OVP_MASK, priv->boost_ovp << BOOST_OVP_SHIFT); + if (ret) { + log_debug("%s: ovp config failed %d\n", __func__, ret); + return ret; + } + return 0; } From 93930dee12a324b258a983ea9b55dc8da84cfc65 Mon Sep 17 00:00:00 2001 From: Svyatoslav Ryhel Date: Fri, 21 Feb 2025 17:47:36 +0200 Subject: [PATCH 37/47] video: backlight: lm3533: set up backlight according to device tree Configure backlight lm3533 child according to device tree description. Signed-off-by: Svyatoslav Ryhel --- drivers/video/lm3533_backlight.c | 56 +++++++++++++++++++------------- 1 file changed, 34 insertions(+), 22 deletions(-) diff --git a/drivers/video/lm3533_backlight.c b/drivers/video/lm3533_backlight.c index f97f17fec4e..7b87b6bd40b 100644 --- a/drivers/video/lm3533_backlight.c +++ b/drivers/video/lm3533_backlight.c @@ -18,9 +18,13 @@ #define LM3533_BL_MAX_BRIGHTNESS 0xFF #define LM3533_SINK_OUTPUT_CONFIG_1 0x10 -#define LM3533_CONTROL_BANK_A_PWM 0x14 +#define LM3533_CONTROL_PWM_BASE 0x14 +#define PWM_MAX GENMASK(5, 0) #define LM3533_CONTROL_BANK_AB_BRIGHTNESS 0x1A -#define LM3533_CONTROL_BANK_A_FULLSCALE_CURRENT 0x1F +#define LM3533_CONTROL_FULLSCALE_CURRENT_BASE 0x1F +#define MAX_CURRENT_MIN 5000 +#define MAX_CURRENT_MAX 29800 +#define MAX_CURRENT_STEP 800 #define LM3533_CONTROL_BANK_ENABLE 0x27 #define LM3533_OVP_FREQUENCY_PWM_POLARITY 0x2C #define BOOST_OVP_MASK GENMASK(2, 1) @@ -51,34 +55,42 @@ struct lm3533_backlight_priv { static int lm3533_backlight_enable(struct udevice *dev) { struct lm3533_backlight_priv *priv = dev_get_priv(dev); + u8 val, id = priv->reg; int ret; - /* HVLED 1 & 2 are controlled by Bank A */ - ret = dm_i2c_reg_write(dev, LM3533_SINK_OUTPUT_CONFIG_1, 0x00); + if (priv->linear) { + ret = dm_i2c_reg_clrset(dev, LM3533_CONTROL_BANK_AB_BRIGHTNESS, + BIT(2 * id + 1), BIT(2 * id + 1)); + if (ret) + return ret; + } + + if (priv->hvled) { + ret = dm_i2c_reg_clrset(dev, LM3533_SINK_OUTPUT_CONFIG_1, + BIT(0) | BIT(1), id | id << 1); + if (ret) + return ret; + } + + /* Set current */ + if (priv->max_current < MAX_CURRENT_MIN || priv->max_current > MAX_CURRENT_MAX) + return -EINVAL; + + val = (priv->max_current - MAX_CURRENT_MIN) / MAX_CURRENT_STEP; + ret = dm_i2c_reg_write(dev, LM3533_CONTROL_FULLSCALE_CURRENT_BASE + id, val); if (ret) return ret; - /* PWM input is disabled for CABC */ - ret = dm_i2c_reg_write(dev, LM3533_CONTROL_BANK_A_PWM, 0x00); + /* Set PWM mask */ + if (priv->pwm > PWM_MAX) + return -EINVAL; + + ret = dm_i2c_reg_write(dev, LM3533_CONTROL_PWM_BASE + id, priv->pwm); if (ret) return ret; - /* Linear & Control Bank A is configured for register Current control */ - ret = dm_i2c_reg_write(dev, LM3533_CONTROL_BANK_AB_BRIGHTNESS, 0x02); - if (ret) - return ret; - - /* Full-Scale Current (20.2mA) */ - ret = dm_i2c_reg_write(dev, LM3533_CONTROL_BANK_A_FULLSCALE_CURRENT, 0x13); - if (ret) - return ret; - - /* Control Bank A is enable */ - ret = dm_i2c_reg_write(dev, LM3533_CONTROL_BANK_ENABLE, 0x01); - if (ret) - return ret; - - return 0; + /* Enable Control Bank */ + return dm_i2c_reg_clrset(dev, LM3533_CONTROL_BANK_ENABLE, BIT(id), BIT(id)); } static int lm3533_backlight_set_brightness(struct udevice *dev, int percent) From 37a37ad608876a1dfe96c990d540260a3efb8050 Mon Sep 17 00:00:00 2001 From: Svyatoslav Ryhel Date: Thu, 13 Mar 2025 09:59:12 +0200 Subject: [PATCH 38/47] video: edid: guard standard timings EDID expansion behind kconfig Since EDID only indicates supported standard timings, a large table with detailed timing information is necessary, consuming significant space. To mitigate this, the table is made configurable via kconfig, allowing it to be excluded when not needed. Signed-off-by: Svyatoslav Ryhel --- common/edid.c | 6 ++++++ drivers/video/Kconfig | 6 ++++++ 2 files changed, 12 insertions(+) diff --git a/common/edid.c b/common/edid.c index e2ac7100a88..e5aa4ca494f 100644 --- a/common/edid.c +++ b/common/edid.c @@ -16,6 +16,7 @@ #include #include +#if CONFIG_IS_ENABLED(I2C_EDID_STANDARD) #define TIMING(c, ha, hfp, hbp, hsl, va, vfp, vbp, vsl, f) \ .pixelclock = { (c), (c), (c) }, \ .hactive = { (ha), (ha), (ha) }, \ @@ -206,6 +207,7 @@ static const struct display_timing dmt_timings[] = { { TIMING(556188000, 4096, 8, 32, 40, 2160, 48, 8, 6, DISPLAY_FLAGS_HSYNC_HIGH | DISPLAY_FLAGS_VSYNC_LOW) }, }; +#endif int edid_check_info(struct edid1_info *edid_info) { @@ -417,6 +419,7 @@ static bool edid_get_standard_timing(struct edid1_info *edid, int i, unsigned in return false; } +#if CONFIG_IS_ENABLED(I2C_EDID_STANDARD) static bool edid_find_valid_standard_timing(struct edid1_info *buf, struct display_timing *timing, bool (*mode_valid)(void *priv, @@ -446,6 +449,7 @@ static bool edid_find_valid_standard_timing(struct edid1_info *buf, return found; } +#endif int edid_get_timing_validate(u8 *buf, int buf_size, struct display_timing *timing, @@ -493,10 +497,12 @@ int edid_get_timing_validate(u8 *buf, int buf_size, } } +#if CONFIG_IS_ENABLED(I2C_EDID_STANDARD) /* Look for timing in Standard Timings */ if (!found) found = edid_find_valid_standard_timing(edid, timing, mode_valid, mode_valid_priv); +#endif if (!found) return -EINVAL; diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig index b1ef73f3e5c..11d17076a96 100644 --- a/drivers/video/Kconfig +++ b/drivers/video/Kconfig @@ -721,6 +721,12 @@ config I2C_EDID help This enables library for accessing EDID data from an LCD panel. +config I2C_EDID_STANDARD + bool "Enable standard timings EDID library expansion" + depends on I2C_EDID + help + This enables standard timings expansion for EDID data from an LCD panel. + config DISPLAY bool "Enable Display support" depends on DM From 578126b3694fdb0b43c0ad0f00d7355a0134a39f Mon Sep 17 00:00:00 2001 From: Svyatoslav Ryhel Date: Sat, 15 Feb 2025 19:49:23 +0200 Subject: [PATCH 39/47] ARM: tegra: lg_x3: upgrade video bindings Upgrade LG P895 and P880 device tree bindings according to preliminary upstream Linux tree. Once Linux catches up, LG X3 can be switched to OF_UPSTREAM without regressions. Signed-off-by: Svyatoslav Ryhel --- arch/arm/dts/tegra30-lg-p880.dts | 34 +++++++++---- arch/arm/dts/tegra30-lg-p895.dts | 47 +++++++++--------- arch/arm/dts/tegra30-lg-x3.dtsi | 82 +++++++++++++++++++++++++++++--- configs/x3_t30_defconfig | 1 + 4 files changed, 125 insertions(+), 39 deletions(-) diff --git a/arch/arm/dts/tegra30-lg-p880.dts b/arch/arm/dts/tegra30-lg-p880.dts index 1d5ca1459bc..ab5993150b2 100644 --- a/arch/arm/dts/tegra30-lg-p880.dts +++ b/arch/arm/dts/tegra30-lg-p880.dts @@ -101,6 +101,31 @@ }; }; + spi@7000dc00 { + bridge-spi@2 { + /* + * JDI 4.57" 720x1280 DX12D100VM0EAA MIPI DSI panel + */ + panel@0 { + compatible = "jdi,dx12d100vm0eaa"; + reg = <0>; + + reset-gpios = <&gpio TEGRA_GPIO(W, 0) GPIO_ACTIVE_LOW>; + + vdd-supply = <&vcc_3v0_lcd>; + vddio-supply = <&iovcc_1v8_lcd>; + + backlight = <&backlight>; + + port { + panel_input: endpoint { + remote-endpoint = <&bridge_output>; + }; + }; + }; + }; + }; + sdmmc3: sdhci@78000400 { status = "okay"; bus-width = <4>; @@ -118,13 +143,4 @@ linux,code = ; }; }; - - panel: panel { - compatible = "jdi,dx12d100vm0eaa"; - - enable-gpios = <&gpio TEGRA_GPIO(Y, 0) GPIO_ACTIVE_HIGH>; - reset-gpios = <&gpio TEGRA_GPIO(W, 0) GPIO_ACTIVE_HIGH>; - - backlight = <&backlight>; - }; }; diff --git a/arch/arm/dts/tegra30-lg-p895.dts b/arch/arm/dts/tegra30-lg-p895.dts index 43bb373a164..988e772172c 100644 --- a/arch/arm/dts/tegra30-lg-p895.dts +++ b/arch/arm/dts/tegra30-lg-p895.dts @@ -108,36 +108,37 @@ }; }; - panel: panel { - compatible = "hitachi,tx13d100vm0eaa"; + spi@7000dc00 { + bridge-spi@2 { + /* + * HITACHI/KOE 5" 768x1024 TX13D100VM0EAA MIPI DSI panel + */ + panel@0 { + compatible = "koe,tx13d100vm0eaa"; + reg = <0>; - reset-gpios = <&gpio TEGRA_GPIO(W, 0) GPIO_ACTIVE_HIGH>; + reset-gpios = <&gpio TEGRA_GPIO(W, 0) GPIO_ACTIVE_LOW>; - renesas,gamma = <3>; - renesas,inversion; - renesas,contrast; + renesas,gamma = <3>; + renesas,inversion; + renesas,contrast; - vcc-supply = <&vcc_3v0_lcd>; - iovcc-supply = <&iovcc_1v8_lcd>; + vcc-supply = <&vcc_3v0_lcd>; + iovcc-supply = <&iovcc_1v8_lcd>; - backlight = <&backlight>; + backlight = <&backlight>; + + port { + panel_input: endpoint { + remote-endpoint = <&bridge_output>; + }; + }; + }; + }; }; - vcc_3v0_lcd: regulator-lcd { - compatible = "regulator-fixed"; - regulator-name = "vcc_3v0_lcd"; - regulator-min-microvolt = <3000000>; - regulator-max-microvolt = <3000000>; + regulator-lcd3v { gpio = <&gpio TEGRA_GPIO(BB, 0) GPIO_ACTIVE_HIGH>; enable-active-high; }; - - iovcc_1v8_lcd: regulator-lcdvio { - compatible = "regulator-fixed"; - regulator-name = "iovcc_1v8_lcd"; - regulator-min-microvolt = <1800000>; - regulator-max-microvolt = <1800000>; - gpio = <&gpio TEGRA_GPIO(Y, 0) GPIO_ACTIVE_HIGH>; - enable-active-high; - }; }; diff --git a/arch/arm/dts/tegra30-lg-x3.dtsi b/arch/arm/dts/tegra30-lg-x3.dtsi index 30d6dcb6548..40b0ee07787 100644 --- a/arch/arm/dts/tegra30-lg-x3.dtsi +++ b/arch/arm/dts/tegra30-lg-x3.dtsi @@ -32,7 +32,12 @@ rgb { status = "okay"; - nvidia,panel = <&bridge>; + port { + dpi_output: endpoint { + remote-endpoint = <&bridge_input>; + bus-width = <24>; + }; + }; }; }; }; @@ -890,12 +895,22 @@ status = "okay"; clock-frequency = <400000>; - backlight: lm3533@36 { + backlight: led-controller@36 { compatible = "ti,lm3533"; reg = <0x36>; enable-gpios = <&gpio TEGRA_GPIO(N, 6) GPIO_ACTIVE_HIGH>; - default-brightness-level = <128>; + + ti,boost-ovp-microvolt = <24000000>; + ti,boost-freq-hz = <500000>; + + backlight-0 { + compatible = "ti,lm3533-backlight"; + + ti,max-current-microamp = <23400>; + ti,linear-mapping-mode; + ti,hardware-controlled; + }; }; muic@44 { @@ -969,18 +984,46 @@ compatible = "solomon,ssd2825"; reg = <2>; + #address-cells = <1>; + #size-cells = <0>; + spi-cpol; spi-cpha; spi-max-frequency = <1000000>; - power-gpios = <&gpio TEGRA_GPIO(B, 1) GPIO_ACTIVE_HIGH>; - reset-gpios = <&gpio TEGRA_GPIO(O, 2) GPIO_ACTIVE_HIGH>; + reset-gpios = <&gpio TEGRA_GPIO(O, 2) GPIO_ACTIVE_LOW>; + + dvdd-supply = <&vdd_1v2_rgb>; + avdd-supply = <&vdd_1v2_rgb>; + vddio-supply = <&vdd_1v8_vio>; + + solomon,hs-zero-delay-ns = <300>; + solomon,hs-prep-delay-ns = <65>; clocks = <&ssd2825_refclk>; - clock-names = "tx_clk"; - panel = <&panel>; + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + + bridge_input: endpoint { + remote-endpoint = <&dpi_output>; + bus-width = <24>; + }; + }; + + port@1 { + reg = <1>; + + bridge_output: endpoint { + remote-endpoint = <&panel_input>; + }; + }; + }; }; }; @@ -1036,4 +1079,29 @@ linux,code = ; }; }; + + vdd_1v2_rgb: regulator-rgb1v2 { + compatible = "regulator-fixed"; + regulator-name = "vdd_1v2_rgb"; + regulator-min-microvolt = <1200000>; + regulator-max-microvolt = <1200000>; + gpio = <&gpio TEGRA_GPIO(B, 1) GPIO_ACTIVE_HIGH>; + enable-active-high; + }; + + vcc_3v0_lcd: regulator-lcd3v { + compatible = "regulator-fixed"; + regulator-name = "vcc_3v0_lcd"; + regulator-min-microvolt = <3000000>; + regulator-max-microvolt = <3000000>; + }; + + iovcc_1v8_lcd: regulator-lcd1v8 { + compatible = "regulator-fixed"; + regulator-name = "iovcc_1v8_lcd"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + gpio = <&gpio TEGRA_GPIO(Y, 0) GPIO_ACTIVE_HIGH>; + enable-active-high; + }; }; diff --git a/configs/x3_t30_defconfig b/configs/x3_t30_defconfig index 2d72a3bd56f..d0326351488 100644 --- a/configs/x3_t30_defconfig +++ b/configs/x3_t30_defconfig @@ -82,6 +82,7 @@ CONFIG_USB_GADGET_VENDOR_NUM=0x1004 CONFIG_USB_GADGET_PRODUCT_NUM=0x7100 CONFIG_CI_UDC=y CONFIG_VIDEO=y +CONFIG_VIDEO_BRIDGE=y # CONFIG_VIDEO_LOGO is not set CONFIG_BACKLIGHT_LM3533=y CONFIG_VIDEO_BRIDGE_SOLOMON_SSD2825=y From c9fbc404a11b6f3f4c0fbf1e444ee40fae1a30ac Mon Sep 17 00:00:00 2001 From: Svyatoslav Ryhel Date: Sat, 1 Mar 2025 14:48:09 +0200 Subject: [PATCH 40/47] ARM: tegra: endeavoru: upgrade video bindings Upgrade HTC One X device tree to comply possible upstream Linux device tree. Once Linux catches up, HTC One X can be switched to OF_UPSTREAM. Signed-off-by: Svyatoslav Ryhel --- arch/arm/dts/tegra30-htc-endeavoru.dts | 17 ++++------------- configs/endeavoru_defconfig | 1 + 2 files changed, 5 insertions(+), 13 deletions(-) diff --git a/arch/arm/dts/tegra30-htc-endeavoru.dts b/arch/arm/dts/tegra30-htc-endeavoru.dts index 8a0ba3c07cc..db8ac457880 100644 --- a/arch/arm/dts/tegra30-htc-endeavoru.dts +++ b/arch/arm/dts/tegra30-htc-endeavoru.dts @@ -33,13 +33,11 @@ host1x@50000000 { dc@54200000 { - clocks = <&tegra_car TEGRA30_CLK_DISP1>, - <&tegra_car TEGRA30_CLK_PLL_D_OUT0>; + backlight: backlight { + compatible = "nvidia,tegra-pwm-backlight"; - rgb { - status = "okay"; - - nvidia,panel = <&dsia>; + nvidia,pwm-source = <1>; + nvidia,default-brightness = <0x8E>; }; }; @@ -1265,13 +1263,6 @@ nvidia,xcvr-lsrslew = <2>; }; - backlight: backlight { - compatible = "nvidia,tegra-pwm-backlight"; - - nvidia,pwm-source = <1>; - nvidia,default-brightness = <0x8E>; - }; - /* PMIC has a built-in 32KHz oscillator which is used by PMC */ clk32k_in: clock-32k { compatible = "fixed-clock"; diff --git a/configs/endeavoru_defconfig b/configs/endeavoru_defconfig index cc8777e4d83..a1c11c6435f 100644 --- a/configs/endeavoru_defconfig +++ b/configs/endeavoru_defconfig @@ -79,6 +79,7 @@ CONFIG_USB_GADGET_VENDOR_NUM=0x0bb4 CONFIG_USB_GADGET_PRODUCT_NUM=0x0c02 CONFIG_CI_UDC=y CONFIG_VIDEO=y +CONFIG_VIDEO_BRIDGE=y # CONFIG_VIDEO_LOGO is not set CONFIG_VIDEO_LCD_ENDEAVORU=y CONFIG_VIDEO_DSI_TEGRA30=y From 1f51562cdece5dcad99dda02957a48d5be042f79 Mon Sep 17 00:00:00 2001 From: Svyatoslav Ryhel Date: Tue, 4 Mar 2025 19:59:59 +0200 Subject: [PATCH 41/47] ARM: tegra: p1801-t: configure HDMI binding Bind HDMI for ASUS AiO P1801-t to provide full panel support and improve usability. Signed-off-by: Svyatoslav Ryhel --- arch/arm/dts/tegra30-asus-p1801-t.dts | 12 +----------- configs/transformer_t30_defconfig | 2 ++ 2 files changed, 3 insertions(+), 11 deletions(-) diff --git a/arch/arm/dts/tegra30-asus-p1801-t.dts b/arch/arm/dts/tegra30-asus-p1801-t.dts index 243ff2bda26..4b7b64b477b 100644 --- a/arch/arm/dts/tegra30-asus-p1801-t.dts +++ b/arch/arm/dts/tegra30-asus-p1801-t.dts @@ -34,20 +34,10 @@ host1x@50000000 { dc@54200000 { - clocks = <&tegra_car TEGRA30_CLK_DISP1>, - <&tegra_car TEGRA30_CLK_PLL_D_OUT0>; - - rgb { - status = "okay"; - - nvidia,panel = <&hdmi>; - }; + status = "disabled"; }; hdmi: hdmi@54280000 { - clocks = <&tegra_car TEGRA30_CLK_HDMI>, - <&tegra_car TEGRA30_CLK_PLL_D_OUT0>; - status = "okay"; hdmi-supply = <&hdmi_5v0_sys>; diff --git a/configs/transformer_t30_defconfig b/configs/transformer_t30_defconfig index 9d63755533a..f5a666d8a17 100644 --- a/configs/transformer_t30_defconfig +++ b/configs/transformer_t30_defconfig @@ -89,6 +89,8 @@ CONFIG_USB_GADGET_VENDOR_NUM=0x0b05 CONFIG_USB_GADGET_PRODUCT_NUM=0x4daf CONFIG_CI_UDC=y CONFIG_VIDEO=y +CONFIG_VIDEO_BRIDGE=y # CONFIG_VIDEO_LOGO is not set CONFIG_VIDEO_BRIDGE_TOSHIBA_TC358768=y CONFIG_VIDEO_TEGRA20=y +CONFIG_VIDEO_HDMI_TEGRA=y From 8a2846e7adeb2c9287ad4ed8c6ea8e7b2a5219c2 Mon Sep 17 00:00:00 2001 From: Svyatoslav Ryhel Date: Tue, 4 Mar 2025 20:08:55 +0200 Subject: [PATCH 42/47] ARM: tegra: tf700t: upgrade video bindings Align TF700T bindings with existing upstream device trees. OF_UPSTREAM migration is possible already but resulting size of binary exceeds maximum allowed size with full size trees. Signed-off-by: Svyatoslav Ryhel --- arch/arm/dts/tegra30-asus-tf700t.dts | 96 +++++++++++++++++++--------- 1 file changed, 67 insertions(+), 29 deletions(-) diff --git a/arch/arm/dts/tegra30-asus-tf700t.dts b/arch/arm/dts/tegra30-asus-tf700t.dts index 6dc760b90d6..47606ede9d6 100644 --- a/arch/arm/dts/tegra30-asus-tf700t.dts +++ b/arch/arm/dts/tegra30-asus-tf700t.dts @@ -15,7 +15,14 @@ rgb { status = "okay"; - nvidia,panel = <&tc358768>; + /delete-property/ nvidia,panel; + + port { + dpi_output: endpoint { + remote-endpoint = <&bridge_input>; + bus-width = <24>; + }; + }; }; }; }; @@ -118,38 +125,69 @@ vddio-supply = <&vdd_1v8_vio>; vddmipi-supply = <&vdd_1v2_mipi>; - panel = <&panel>; + /* + * Panasonic VVX10F004B00 or HYDIS HV101WU1-1E1 + * LCD SuperIPS+ Full HD panel. + */ + panel@1 { + compatible = "panasonic,vvx10f004b00"; + reg = <1>; + + power-supply = <&vdd_pnl_reg>; + backlight = <&backlight>; + + display-timings { + timing@0 { + /* 1920x1200@60Hz */ + clock-frequency = <154000000>; + + hactive = <1920>; + hfront-porch = <48>; + hback-porch = <80>; + hsync-len = <32>; + hsync-active = <1>; + + vactive = <1200>; + vfront-porch = <3>; + vback-porch = <26>; + vsync-len = <6>; + vsync-active = <1>; + }; + }; + + port { + panel_input: endpoint { + remote-endpoint = <&bridge_output>; + }; + }; + }; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + + bridge_input: endpoint { + remote-endpoint = <&dpi_output>; + bus-width = <24>; + }; + }; + + port@1 { + reg = <1>; + + bridge_output: endpoint { + remote-endpoint = <&panel_input>; + }; + }; + }; }; }; }; - panel: panel { - compatible = "panasonic,vvx10f004b00"; - - power-supply = <&vdd_pnl_reg>; - backlight = <&backlight>; - - /delete-property/ enable-gpios; - - display-timings { - timing@0 { - /* 1920x1200@60Hz */ - clock-frequency = <154000000>; - - hactive = <1920>; - hfront-porch = <48>; - hback-porch = <80>; - hsync-len = <32>; - hsync-active = <1>; - - vactive = <1200>; - vfront-porch = <3>; - vback-porch = <26>; - vsync-len = <6>; - vsync-active = <1>; - }; - }; - }; + /delete-node/ panel; vdd_1v2_mipi: regulator-mipi { compatible = "regulator-fixed"; From 59bc30822177de6b79851b8bc1da4b8283273509 Mon Sep 17 00:00:00 2001 From: Svyatoslav Ryhel Date: Thu, 13 Mar 2025 10:48:06 +0200 Subject: [PATCH 43/47] pinctrl: tegra: adjust default values of pins The current default pin and drive values were more of temporary placeholders. They have to be replaced with accurate default values as specified in the TRM and header file. Signed-off-by: Svyatoslav Ryhel --- drivers/pinctrl/tegra/pinctrl-tegra.c | 34 +++++++++++++-------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/drivers/pinctrl/tegra/pinctrl-tegra.c b/drivers/pinctrl/tegra/pinctrl-tegra.c index e6b957f5537..b04be168bc8 100644 --- a/drivers/pinctrl/tegra/pinctrl-tegra.c +++ b/drivers/pinctrl/tegra/pinctrl-tegra.c @@ -23,18 +23,18 @@ static void tegra_pinctrl_set_drive(struct udevice *config, int drvcnt) return; } - drive_group[0].slwf = dev_read_u32_default(config, "nvidia,slew-rate-falling", 0); - drive_group[0].slwr = dev_read_u32_default(config, "nvidia,slew-rate-rising", 0); - drive_group[0].drvup = dev_read_u32_default(config, "nvidia,pull-up-strength", 0); - drive_group[0].drvdn = dev_read_u32_default(config, "nvidia,pull-down-strength", 0); + drive_group[0].slwf = dev_read_u32_default(config, "nvidia,slew-rate-falling", PMUX_SLWF_NONE); + drive_group[0].slwr = dev_read_u32_default(config, "nvidia,slew-rate-rising", PMUX_SLWR_NONE); + drive_group[0].drvup = dev_read_u32_default(config, "nvidia,pull-up-strength", PMUX_DRVUP_NONE); + drive_group[0].drvdn = dev_read_u32_default(config, "nvidia,pull-down-strength", PMUX_DRVDN_NONE); #ifdef TEGRA_PMX_GRPS_HAVE_LPMD - drive_group[0].lpmd = dev_read_u32_default(config, "nvidia,low-power-mode", 0); + drive_group[0].lpmd = dev_read_u32_default(config, "nvidia,low-power-mode", PMUX_LPMD_NONE); #endif #ifdef TEGRA_PMX_GRPS_HAVE_SCHMT - drive_group[0].schmt = dev_read_u32_default(config, "nvidia,schmitt", 0); + drive_group[0].schmt = dev_read_u32_default(config, "nvidia,schmitt", PMUX_SCHMT_NONE); #endif #ifdef TEGRA_PMX_GRPS_HAVE_HSM - drive_group[0].hsm = dev_read_u32_default(config, "nvidia,high-speed-mode", 0); + drive_group[0].hsm = dev_read_u32_default(config, "nvidia,high-speed-mode", PMUX_HSM_NONE); #endif for (i = 1; i < drvcnt; i++) @@ -142,31 +142,31 @@ static void tegra_pinctrl_set_pin(struct udevice *config, int pincnt) pinmux_group[0].func = i; - pinmux_group[0].pull = dev_read_u32_default(config, "nvidia,pull", 0); - pinmux_group[0].tristate = dev_read_u32_default(config, "nvidia,tristate", 0); + pinmux_group[0].pull = dev_read_u32_default(config, "nvidia,pull", PMUX_PULL_NORMAL); + pinmux_group[0].tristate = dev_read_u32_default(config, "nvidia,tristate", PMUX_TRI_TRISTATE); #ifdef TEGRA_PMX_PINS_HAVE_E_INPUT - pinmux_group[0].io = dev_read_u32_default(config, "nvidia,enable-input", 0); + pinmux_group[0].io = dev_read_u32_default(config, "nvidia,enable-input", PMUX_PIN_NONE); #endif #ifdef TEGRA_PMX_PINS_HAVE_LOCK - pinmux_group[0].lock = dev_read_u32_default(config, "nvidia,lock", 0); + pinmux_group[0].lock = dev_read_u32_default(config, "nvidia,lock", PMUX_PIN_LOCK_DEFAULT); #endif #ifdef TEGRA_PMX_PINS_HAVE_OD - pinmux_group[0].od = dev_read_u32_default(config, "nvidia,open-drain", 0); + pinmux_group[0].od = dev_read_u32_default(config, "nvidia,open-drain", PMUX_PIN_OD_DEFAULT); #endif #ifdef TEGRA_PMX_PINS_HAVE_IO_RESET - pinmux_group[0].ioreset = dev_read_u32_default(config, "nvidia,io-reset", 0); + pinmux_group[0].ioreset = dev_read_u32_default(config, "nvidia,io-reset", PMUX_PIN_IO_RESET_DEFAULT); #endif #ifdef TEGRA_PMX_PINS_HAVE_RCV_SEL - pinmux_group[0].rcv_sel = dev_read_u32_default(config, "nvidia,rcv-sel", 0); + pinmux_group[0].rcv_sel = dev_read_u32_default(config, "nvidia,rcv-sel", PMUX_PIN_RCV_SEL_DEFAULT); #endif #ifdef TEGRA_PMX_PINS_HAVE_E_IO_HV - pinmux_group[0].e_io_hv = dev_read_u32_default(config, "nvidia,io-hv", 0); + pinmux_group[0].e_io_hv = dev_read_u32_default(config, "nvidia,io-hv", PMUX_PIN_E_IO_HV_DEFAULT); #endif #ifdef TEGRA_PMX_PINS_HAVE_SCHMT - pinmux_group[0].schmt = dev_read_u32_default(config, "nvidia,schmitt", 0); + pinmux_group[0].schmt = dev_read_u32_default(config, "nvidia,schmitt", PMUX_SCHMT_NONE); #endif #ifdef TEGRA_PMX_PINS_HAVE_HSM - pinmux_group[0].hsm = dev_read_u32_default(config, "nvidia,high-speed-mode", 0); + pinmux_group[0].hsm = dev_read_u32_default(config, "nvidia,high-speed-mode", PMUX_HSM_NONE); #endif for (i = 1; i < pincnt; i++) From 65e4869a10dc7484924172149e9d7757a9ae5702 Mon Sep 17 00:00:00 2001 From: Svyatoslav Ryhel Date: Thu, 13 Mar 2025 11:02:35 +0200 Subject: [PATCH 44/47] pinctrl: tegra: adjust pin state lists Modify the pin state lists for lock, io-reset, rcv-sel, and e-io-hv properties by repositioning the default value to the end. This change addresses conflicts with device tree representations of TEGRA_PIN_DISABLE and TEGRA_PIN_ENABLE. Signed-off-by: Svyatoslav Ryhel --- arch/arm/include/asm/arch-tegra/pinmux.h | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/arch/arm/include/asm/arch-tegra/pinmux.h b/arch/arm/include/asm/arch-tegra/pinmux.h index 4b6e8419504..9a5cc93884c 100644 --- a/arch/arm/include/asm/arch-tegra/pinmux.h +++ b/arch/arm/include/asm/arch-tegra/pinmux.h @@ -34,41 +34,41 @@ enum pmux_pin_io { #ifdef TEGRA_PMX_PINS_HAVE_LOCK enum pmux_pin_lock { - PMUX_PIN_LOCK_DEFAULT = 0, - PMUX_PIN_LOCK_DISABLE, + PMUX_PIN_LOCK_DISABLE = 0, PMUX_PIN_LOCK_ENABLE, + PMUX_PIN_LOCK_DEFAULT, }; #endif #ifdef TEGRA_PMX_PINS_HAVE_OD enum pmux_pin_od { - PMUX_PIN_OD_DEFAULT = 0, - PMUX_PIN_OD_DISABLE, + PMUX_PIN_OD_DISABLE = 0, PMUX_PIN_OD_ENABLE, + PMUX_PIN_OD_DEFAULT, }; #endif #ifdef TEGRA_PMX_PINS_HAVE_IO_RESET enum pmux_pin_ioreset { - PMUX_PIN_IO_RESET_DEFAULT = 0, - PMUX_PIN_IO_RESET_DISABLE, + PMUX_PIN_IO_RESET_DISABLE = 0, PMUX_PIN_IO_RESET_ENABLE, + PMUX_PIN_IO_RESET_DEFAULT, }; #endif #ifdef TEGRA_PMX_PINS_HAVE_RCV_SEL enum pmux_pin_rcv_sel { - PMUX_PIN_RCV_SEL_DEFAULT = 0, - PMUX_PIN_RCV_SEL_NORMAL, + PMUX_PIN_RCV_SEL_NORMAL = 0, PMUX_PIN_RCV_SEL_HIGH, + PMUX_PIN_RCV_SEL_DEFAULT, }; #endif #ifdef TEGRA_PMX_PINS_HAVE_E_IO_HV enum pmux_pin_e_io_hv { - PMUX_PIN_E_IO_HV_DEFAULT = 0, - PMUX_PIN_E_IO_HV_NORMAL, + PMUX_PIN_E_IO_HV_NORMAL = 0, PMUX_PIN_E_IO_HV_HIGH, + PMUX_PIN_E_IO_HV_DEFAULT, }; #endif From 6494be8c722aa5e1d7bc9ea8d9e0b29d6dfe9b04 Mon Sep 17 00:00:00 2001 From: Svyatoslav Ryhel Date: Fri, 14 Mar 2025 12:29:28 +0200 Subject: [PATCH 45/47] pinctrl: tegra20: fix function naming mismatches The names used for displaya, displayb and i2c1 do not align with their corresponding Linux counterparts. This inconsistency can cause pins to be configured incorrectly, potentially breaking existing functionality. Signed-off-by: Svyatoslav Ryhel --- arch/arm/include/asm/arch-tegra20/pinmux.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/arch/arm/include/asm/arch-tegra20/pinmux.h b/arch/arm/include/asm/arch-tegra20/pinmux.h index 8c8579e87e3..9598851b100 100644 --- a/arch/arm/include/asm/arch-tegra20/pinmux.h +++ b/arch/arm/include/asm/arch-tegra20/pinmux.h @@ -467,14 +467,14 @@ static const char * const tegra_pinctrl_to_func[] = { [PMUX_FUNC_DAP3] = "dap3", [PMUX_FUNC_DAP4] = "dap4", [PMUX_FUNC_DAP5] = "dap5", - [PMUX_FUNC_DISPA] = "dispa", - [PMUX_FUNC_DISPB] = "dispb", + [PMUX_FUNC_DISPA] = "displaya", + [PMUX_FUNC_DISPB] = "displayb", [PMUX_FUNC_EMC_TEST0_DLL] = "emc_test0_dll", [PMUX_FUNC_EMC_TEST1_DLL] = "emc_test1_dll", [PMUX_FUNC_GMI] = "gmi", [PMUX_FUNC_GMI_INT] = "gmi_int", [PMUX_FUNC_HDMI] = "hdmi", - [PMUX_FUNC_I2C] = "i2c", + [PMUX_FUNC_I2C] = "i2c1", [PMUX_FUNC_I2C2] = "i2c2", [PMUX_FUNC_I2C3] = "i2c3", [PMUX_FUNC_IDE] = "ide", From 13af58edb29d3ef840ff06e23fd7311b8c8aad9f Mon Sep 17 00:00:00 2001 From: Svyatoslav Ryhel Date: Thu, 13 Mar 2025 13:11:00 +0200 Subject: [PATCH 46/47] ARM: tegra: dts: fix lock, io-reset and open-drain properties Signed-off-by: Svyatoslav Ryhel --- arch/arm/dts/tegra124-xiaomi-mocha.dts | 14 +++--- arch/arm/dts/tegra30-asus-p1801-t.dts | 28 +++++------ arch/arm/dts/tegra30-asus-tf600t.dts | 44 +++++++++--------- arch/arm/dts/tegra30-asus-transformer.dtsi | 26 +++++------ .../dts/tegra30-lenovo-ideapad-yoga-11.dts | 46 +++++++++---------- arch/arm/dts/tegra30-microsoft-surface-rt.dts | 38 +++++++-------- arch/arm/dts/tegra30-wexler-qc750.dts | 10 ++-- 7 files changed, 103 insertions(+), 103 deletions(-) diff --git a/arch/arm/dts/tegra124-xiaomi-mocha.dts b/arch/arm/dts/tegra124-xiaomi-mocha.dts index 6cb1781566f..64386f2b7b7 100644 --- a/arch/arm/dts/tegra124-xiaomi-mocha.dts +++ b/arch/arm/dts/tegra124-xiaomi-mocha.dts @@ -215,8 +215,8 @@ nvidia,pull = ; nvidia,tristate = ; nvidia,enable-input = ; - nvidia,lock = <1>; - nvidia,open-drain = <1>; + nvidia,lock = ; + nvidia,open-drain = ; }; gen2-i2c { nvidia,pins = "gen2_i2c_scl_pt5", @@ -225,8 +225,8 @@ nvidia,pull = ; nvidia,tristate = ; nvidia,enable-input = ; - nvidia,lock = <1>; - nvidia,open-drain = <1>; + nvidia,lock = ; + nvidia,open-drain = ; }; cam-i2c { nvidia,pins = "cam_i2c_scl_pbb1", @@ -235,8 +235,8 @@ nvidia,pull = ; nvidia,tristate = ; nvidia,enable-input = ; - nvidia,lock = <1>; - nvidia,open-drain = <1>; + nvidia,lock = ; + nvidia,open-drain = ; }; ddc-i2c { nvidia,pins = "ddc_scl_pv4", @@ -253,7 +253,7 @@ nvidia,pull = ; nvidia,tristate = ; nvidia,enable-input = ; - nvidia,open-drain = <1>; + nvidia,open-drain = ; }; dsi-b { diff --git a/arch/arm/dts/tegra30-asus-p1801-t.dts b/arch/arm/dts/tegra30-asus-p1801-t.dts index 4b7b64b477b..58f1499cb92 100644 --- a/arch/arm/dts/tegra30-asus-p1801-t.dts +++ b/arch/arm/dts/tegra30-asus-p1801-t.dts @@ -108,8 +108,8 @@ nvidia,pull = ; nvidia,tristate = ; nvidia,enable-input = ; - nvidia,lock = <1>; - nvidia,io-reset = <1>; + nvidia,lock = ; + nvidia,io-reset = ; }; /* SDMMC3 pinmux */ @@ -193,7 +193,7 @@ nvidia,tristate = ; nvidia,enable-input = ; nvidia,open-drain = ; - nvidia,lock = <1>; + nvidia,lock = ; }; gen2_i2c { nvidia,pins = "gen2_i2c_scl_pt5", @@ -203,7 +203,7 @@ nvidia,tristate = ; nvidia,enable-input = ; nvidia,open-drain = ; - nvidia,lock = <1>; + nvidia,lock = ; }; cam_i2c { nvidia,pins = "cam_i2c_scl_pbb1", @@ -213,7 +213,7 @@ nvidia,tristate = ; nvidia,enable-input = ; nvidia,open-drain = ; - nvidia,lock = <1>; + nvidia,lock = ; }; ddc_i2c { nvidia,pins = "ddc_scl_pv4", @@ -222,7 +222,7 @@ nvidia,pull = ; nvidia,tristate = ; nvidia,enable-input = ; - nvidia,lock = <1>; + nvidia,lock = ; }; pwr_i2c { nvidia,pins = "pwr_i2c_scl_pz6", @@ -232,7 +232,7 @@ nvidia,tristate = ; nvidia,enable-input = ; nvidia,open-drain = ; - nvidia,lock = <1>; + nvidia,lock = ; }; hotplug_i2c { nvidia,pins = "pu4"; @@ -250,7 +250,7 @@ nvidia,tristate = ; nvidia,enable-input = ; nvidia,open-drain = ; - nvidia,lock = <1>; + nvidia,lock = ; }; hdmi_hpd { nvidia,pins = "hdmi_int_pn7"; @@ -622,8 +622,8 @@ nvidia,pull = ; nvidia,tristate = ; nvidia,enable-input = ; - nvidia,lock = <1>; - nvidia,io-reset = <1>; + nvidia,lock = ; + nvidia,io-reset = ; }; /* GPIO keys pinmux */ @@ -708,8 +708,8 @@ nvidia,pull = ; nvidia,tristate = ; nvidia,enable-input = ; - nvidia,lock = <1>; - nvidia,io-reset = <1>; + nvidia,lock = ; + nvidia,io-reset = ; }; vi_d10_pt2 { nvidia,pins = "vi_d10_pt2", @@ -828,8 +828,8 @@ nvidia,pull = ; nvidia,tristate = ; nvidia,enable-input = ; - nvidia,lock = <1>; - nvidia,io-reset = <1>; + nvidia,lock = ; + nvidia,io-reset = ; }; vi_mclk_pt1 { nvidia,pins = "vi_mclk_pt1"; diff --git a/arch/arm/dts/tegra30-asus-tf600t.dts b/arch/arm/dts/tegra30-asus-tf600t.dts index 3ddd78b3df6..1b5729c65f4 100644 --- a/arch/arm/dts/tegra30-asus-tf600t.dts +++ b/arch/arm/dts/tegra30-asus-tf600t.dts @@ -90,8 +90,8 @@ nvidia,pull = ; nvidia,tristate = ; nvidia,enable-input = ; - nvidia,lock = <1>; - nvidia,io-reset = <1>; + nvidia,lock = ; + nvidia,io-reset = ; }; /* SDMMC2 pinmux */ @@ -107,8 +107,8 @@ nvidia,pull = ; nvidia,tristate = ; nvidia,enable-input = ; - nvidia,lock = <1>; - nvidia,io-reset = <1>; + nvidia,lock = ; + nvidia,io-reset = ; }; /* SDMMC3 pinmux */ @@ -142,8 +142,8 @@ nvidia,pull = ; nvidia,tristate = ; nvidia,enable-input = ; - nvidia,lock = <1>; - nvidia,io-reset = <1>; + nvidia,lock = ; + nvidia,io-reset = ; }; sdmmc4_cmd { nvidia,pins = "sdmmc4_cmd_pt7", @@ -159,8 +159,8 @@ nvidia,pull = ; nvidia,tristate = ; nvidia,enable-input = ; - nvidia,lock = <1>; - nvidia,io-reset = <1>; + nvidia,lock = ; + nvidia,io-reset = ; }; sdmmc4_rst_n { nvidia,pins = "sdmmc4_rst_n_pcc3"; @@ -186,7 +186,7 @@ nvidia,tristate = ; nvidia,enable-input = ; nvidia,open-drain = ; - nvidia,lock = <0>; + nvidia,lock = ; }; gen2_i2c { nvidia,pins = "gen2_i2c_scl_pt5", @@ -196,7 +196,7 @@ nvidia,tristate = ; nvidia,enable-input = ; nvidia,open-drain = ; - nvidia,lock = <0>; + nvidia,lock = ; }; cam_i2c { nvidia,pins = "cam_i2c_scl_pbb1", @@ -206,7 +206,7 @@ nvidia,tristate = ; nvidia,enable-input = ; nvidia,open-drain = ; - nvidia,lock = <0>; + nvidia,lock = ; }; ddc_i2c { nvidia,pins = "ddc_scl_pv4", @@ -215,7 +215,7 @@ nvidia,pull = ; nvidia,tristate = ; nvidia,enable-input = ; - nvidia,lock = <0>; + nvidia,lock = ; }; pwr_i2c { nvidia,pins = "pwr_i2c_scl_pz6", @@ -225,7 +225,7 @@ nvidia,tristate = ; nvidia,enable-input = ; nvidia,open-drain = ; - nvidia,lock = <0>; + nvidia,lock = ; }; hotplug_i2c { nvidia,pins = "pu4"; @@ -243,7 +243,7 @@ nvidia,tristate = ; nvidia,enable-input = ; nvidia,open-drain = ; - nvidia,lock = <0>; + nvidia,lock = ; }; hdmi_hpd { nvidia,pins = "hdmi_int_pn7"; @@ -613,8 +613,8 @@ nvidia,pull = ; nvidia,tristate = ; nvidia,enable-input = ; - nvidia,lock = <1>; - nvidia,io-reset = <1>; + nvidia,lock = ; + nvidia,io-reset = ; }; /* GPIO keys pinmux */ @@ -701,8 +701,8 @@ nvidia,pull = ; nvidia,tristate = ; nvidia,enable-input = ; - nvidia,lock = <1>; - nvidia,io-reset = <1>; + nvidia,lock = ; + nvidia,io-reset = ; }; pbb0 { nvidia,pins = "pbb0"; @@ -827,8 +827,8 @@ nvidia,pull = ; nvidia,tristate = ; nvidia,enable-input = ; - nvidia,lock = <1>; - nvidia,io-reset = <1>; + nvidia,lock = ; + nvidia,io-reset = ; }; vi_mclk_pt1 { nvidia,pins = "vi_mclk_pt1"; @@ -836,8 +836,8 @@ nvidia,pull = ; nvidia,tristate = ; nvidia,enable-input = ; - nvidia,lock = <1>; - nvidia,io-reset = <1>; + nvidia,lock = ; + nvidia,io-reset = ; }; jtag { diff --git a/arch/arm/dts/tegra30-asus-transformer.dtsi b/arch/arm/dts/tegra30-asus-transformer.dtsi index 03ba8fb9604..032fb3d00ac 100644 --- a/arch/arm/dts/tegra30-asus-transformer.dtsi +++ b/arch/arm/dts/tegra30-asus-transformer.dtsi @@ -99,8 +99,8 @@ nvidia,pull = ; nvidia,tristate = ; nvidia,enable-input = ; - nvidia,lock = <1>; - nvidia,io-reset = <1>; + nvidia,lock = ; + nvidia,io-reset = ; }; /* SDMMC3 pinmux */ @@ -189,7 +189,7 @@ nvidia,tristate = ; nvidia,enable-input = ; nvidia,open-drain = ; - nvidia,lock = <1>; + nvidia,lock = ; }; gen2_i2c { @@ -200,7 +200,7 @@ nvidia,tristate = ; nvidia,enable-input = ; nvidia,open-drain = ; - nvidia,lock = <1>; + nvidia,lock = ; }; cam_i2c { @@ -211,7 +211,7 @@ nvidia,tristate = ; nvidia,enable-input = ; nvidia,open-drain = ; - nvidia,lock = <1>; + nvidia,lock = ; }; ddc_i2c { @@ -221,7 +221,7 @@ nvidia,pull = ; nvidia,tristate = ; nvidia,enable-input = ; - nvidia,lock = <1>; + nvidia,lock = ; }; pwr_i2c { @@ -232,7 +232,7 @@ nvidia,tristate = ; nvidia,enable-input = ; nvidia,open-drain = ; - nvidia,lock = <1>; + nvidia,lock = ; }; hotplug_i2c { @@ -647,8 +647,8 @@ nvidia,pull = ; nvidia,tristate = ; nvidia,enable-input = ; - nvidia,lock = <1>; - nvidia,io-reset = <1>; + nvidia,lock = ; + nvidia,io-reset = ; }; /* GPIO keys pinmux */ @@ -741,8 +741,8 @@ nvidia,pull = ; nvidia,tristate = ; nvidia,enable-input = ; - nvidia,lock = <1>; - nvidia,io-reset = <1>; + nvidia,lock = ; + nvidia,io-reset = ; }; vi_d10_pt2 { @@ -879,8 +879,8 @@ nvidia,pull = ; nvidia,tristate = ; nvidia,enable-input = ; - nvidia,lock = <1>; - nvidia,io-reset = <1>; + nvidia,lock = ; + nvidia,io-reset = ; }; vi_mclk_pt1 { diff --git a/arch/arm/dts/tegra30-lenovo-ideapad-yoga-11.dts b/arch/arm/dts/tegra30-lenovo-ideapad-yoga-11.dts index 9a1e8c0601e..876fac7b661 100644 --- a/arch/arm/dts/tegra30-lenovo-ideapad-yoga-11.dts +++ b/arch/arm/dts/tegra30-lenovo-ideapad-yoga-11.dts @@ -109,8 +109,8 @@ nvidia,pull = ; nvidia,tristate = ; nvidia,enable-input = ; - nvidia,lock = <1>; - nvidia,io-reset = <1>; + nvidia,lock = ; + nvidia,io-reset = ; }; sdmmc4-cmd { nvidia,pins = "sdmmc4_cmd_pt7", @@ -127,8 +127,8 @@ nvidia,pull = ; nvidia,tristate = ; nvidia,enable-input = ; - nvidia,lock = <1>; - nvidia,io-reset = <1>; + nvidia,lock = ; + nvidia,io-reset = ; }; cam-mclk { nvidia,pins = "cam_mclk_pcc0"; @@ -147,7 +147,7 @@ nvidia,tristate = ; nvidia,enable-input = ; nvidia,open-drain = ; - nvidia,lock = <1>; + nvidia,lock = ; }; gen2-i2c { nvidia,pins = "gen2_i2c_scl_pt5", @@ -157,7 +157,7 @@ nvidia,tristate = ; nvidia,enable-input = ; nvidia,open-drain = ; - nvidia,lock = <1>; + nvidia,lock = ; }; cam-i2c { nvidia,pins = "cam_i2c_scl_pbb1", @@ -167,7 +167,7 @@ nvidia,tristate = ; nvidia,enable-input = ; nvidia,open-drain = ; - nvidia,lock = <1>; + nvidia,lock = ; }; ddc-i2c { nvidia,pins = "ddc_scl_pv4", @@ -176,7 +176,7 @@ nvidia,pull = ; nvidia,tristate = ; nvidia,enable-input = ; - nvidia,lock = <1>; + nvidia,lock = ; }; pwr-i2c { nvidia,pins = "pwr_i2c_scl_pz6", @@ -186,7 +186,7 @@ nvidia,tristate = ; nvidia,enable-input = ; nvidia,open-drain = ; - nvidia,lock = <1>; + nvidia,lock = ; }; /* HDMI pinmux */ @@ -724,8 +724,8 @@ nvidia,pull = ; nvidia,tristate = ; nvidia,enable-input = ; - nvidia,lock = <1>; - nvidia,io-reset = <1>; + nvidia,lock = ; + nvidia,io-reset = ; }; vi-vsync-pd6 { nvidia,pins = "vi_vsync_pd6", @@ -736,8 +736,8 @@ nvidia,pull = ; nvidia,tristate = ; nvidia,enable-input = ; - nvidia,lock = <1>; - nvidia,io-reset = <2>; + nvidia,lock = ; + nvidia,io-reset = ; }; vi-hsync-pd7 { nvidia,pins = "vi_hsync_pd7", @@ -749,8 +749,8 @@ nvidia,pull = ; nvidia,tristate = ; nvidia,enable-input = ; - nvidia,lock = <1>; - nvidia,io-reset = <1>; + nvidia,lock = ; + nvidia,io-reset = ; }; vi-d2-pl0 { nvidia,pins = "vi_d2_pl0", @@ -760,8 +760,8 @@ nvidia,pull = ; nvidia,tristate = ; nvidia,enable-input = ; - nvidia,lock = <1>; - nvidia,io-reset = <1>; + nvidia,lock = ; + nvidia,io-reset = ; }; vi-mclk-pt1 { nvidia,pins = "vi_mclk_pt1"; @@ -769,8 +769,8 @@ nvidia,pull = ; nvidia,tristate = ; nvidia,enable-input = ; - nvidia,lock = <1>; - nvidia,io-reset = <2>; + nvidia,lock = ; + nvidia,io-reset = ; }; vi-d11-pt3 { nvidia,pins = "vi_d11_pt3"; @@ -778,8 +778,8 @@ nvidia,pull = ; nvidia,tristate = ; nvidia,enable-input = ; - nvidia,lock = <1>; - nvidia,io-reset = <1>; + nvidia,lock = ; + nvidia,io-reset = ; }; vi-d5-pl3 { nvidia,pins = "vi_d5_pl3"; @@ -787,8 +787,8 @@ nvidia,pull = ; nvidia,tristate = ; nvidia,enable-input = ; - nvidia,lock = <1>; - nvidia,io-reset = <1>; + nvidia,lock = ; + nvidia,io-reset = ; }; /* PORT U */ diff --git a/arch/arm/dts/tegra30-microsoft-surface-rt.dts b/arch/arm/dts/tegra30-microsoft-surface-rt.dts index 6810350a90b..2d22d3e0bb1 100644 --- a/arch/arm/dts/tegra30-microsoft-surface-rt.dts +++ b/arch/arm/dts/tegra30-microsoft-surface-rt.dts @@ -103,8 +103,8 @@ nvidia,pull = ; nvidia,tristate = ; nvidia,enable-input = ; - nvidia,lock = <1>; - nvidia,io-reset = <1>; + nvidia,lock = ; + nvidia,io-reset = ; }; sdmmc4-cmd { nvidia,pins = "sdmmc4_cmd_pt7", @@ -121,8 +121,8 @@ nvidia,pull = ; nvidia,tristate = ; nvidia,enable-input = ; - nvidia,lock = <1>; - nvidia,io-reset = <1>; + nvidia,lock = ; + nvidia,io-reset = ; }; cam-mclk { nvidia,pins = "cam_mclk_pcc0"; @@ -141,7 +141,7 @@ nvidia,tristate = ; nvidia,enable-input = ; nvidia,open-drain = ; - nvidia,lock = <0>; + nvidia,lock = ; }; gen2-i2c { nvidia,pins = "gen2_i2c_scl_pt5", @@ -151,7 +151,7 @@ nvidia,tristate = ; nvidia,enable-input = ; nvidia,open-drain = ; - nvidia,lock = <0>; + nvidia,lock = ; }; cam-i2c { nvidia,pins = "cam_i2c_scl_pbb1", @@ -161,7 +161,7 @@ nvidia,tristate = ; nvidia,enable-input = ; nvidia,open-drain = ; - nvidia,lock = <0>; + nvidia,lock = ; }; ddc-i2c { nvidia,pins = "ddc_scl_pv4", @@ -170,7 +170,7 @@ nvidia,pull = ; nvidia,tristate = ; nvidia,enable-input = ; - nvidia,lock = <0>; + nvidia,lock = ; }; pwr-i2c { nvidia,pins = "pwr_i2c_scl_pz6", @@ -180,7 +180,7 @@ nvidia,tristate = ; nvidia,enable-input = ; nvidia,open-drain = ; - nvidia,lock = <0>; + nvidia,lock = ; }; /* HDMI pinmux */ @@ -703,8 +703,8 @@ nvidia,pull = ; nvidia,tristate = ; nvidia,enable-input = ; - nvidia,lock = <1>; - nvidia,io-reset = <1>; + nvidia,lock = ; + nvidia,io-reset = ; }; vi-d3-pl1 { nvidia,pins = "vi_d3_pl1"; @@ -712,8 +712,8 @@ nvidia,pull = ; nvidia,tristate = ; nvidia,enable-input = ; - nvidia,lock = <1>; - nvidia,io-reset = <1>; + nvidia,lock = ; + nvidia,io-reset = ; }; vi-hsync-pd7 { nvidia,pins = "vi_hsync_pd7", @@ -724,8 +724,8 @@ nvidia,pull = ; nvidia,tristate = ; nvidia,enable-input = ; - nvidia,lock = <1>; - nvidia,io-reset = <1>; + nvidia,lock = ; + nvidia,io-reset = ; }; vi-mclk-pt1 { nvidia,pins = "vi_mclk_pt1"; @@ -733,8 +733,8 @@ nvidia,pull = ; nvidia,tristate = ; nvidia,enable-input = ; - nvidia,lock = <1>; - nvidia,io-reset = <1>; + nvidia,lock = ; + nvidia,io-reset = ; }; vi-d11-pt3 { nvidia,pins = "vi_d11_pt3"; @@ -742,8 +742,8 @@ nvidia,pull = ; nvidia,tristate = ; nvidia,enable-input = ; - nvidia,lock = <1>; - nvidia,io-reset = <1>; + nvidia,lock = ; + nvidia,io-reset = ; }; /* PORT U */ diff --git a/arch/arm/dts/tegra30-wexler-qc750.dts b/arch/arm/dts/tegra30-wexler-qc750.dts index 87c2a4072e1..b376b91a7fa 100644 --- a/arch/arm/dts/tegra30-wexler-qc750.dts +++ b/arch/arm/dts/tegra30-wexler-qc750.dts @@ -157,7 +157,7 @@ nvidia,tristate = ; nvidia,enable-input = ; nvidia,open-drain = ; - nvidia,lock = <0>; + nvidia,lock = ; }; gen2-i2c { nvidia,pins = "gen2_i2c_scl_pt5", @@ -167,7 +167,7 @@ nvidia,tristate = ; nvidia,enable-input = ; nvidia,open-drain = ; - nvidia,lock = <0>; + nvidia,lock = ; }; cam-i2c { nvidia,pins = "cam_i2c_scl_pbb1", @@ -177,7 +177,7 @@ nvidia,tristate = ; nvidia,enable-input = ; nvidia,open-drain = ; - nvidia,lock = <0>; + nvidia,lock = ; }; ddc-i2c { nvidia,pins = "ddc_scl_pv4", @@ -186,7 +186,7 @@ nvidia,pull = ; nvidia,tristate = ; nvidia,enable-input = ; - nvidia,lock = <0>; + nvidia,lock = ; }; pwr-i2c { nvidia,pins = "pwr_i2c_scl_pz6", @@ -196,7 +196,7 @@ nvidia,tristate = ; nvidia,enable-input = ; nvidia,open-drain = ; - nvidia,lock = <0>; + nvidia,lock = ; }; /* HDMI pinmux */ From 03f61b153965101f21783e8e6a1e5e86496598ff Mon Sep 17 00:00:00 2001 From: Svyatoslav Ryhel Date: Wed, 5 Mar 2025 15:05:30 +0200 Subject: [PATCH 47/47] board: ouya: add Ouya Game Console support The Ouya microconsole is build on Nvidia Tegra 3 (T33) SoC, featuring a quad-core 1.7 GHz ARM Cortex-A9 CPU and a ULP GeForce GPU, paired with 1GB of DDR3 RAM and 8GB of internal flash storage. Running a modified Android 4.1 (Jelly Bean) OS with a custom launcher, it aimed for open-source gaming via a digital storefront. This implementation is mostly based on upstream Linux device tree and fragments of work done by previous developers. Co-developed-by: Peter Geis Signed-off-by: Peter Geis Signed-off-by: Svyatoslav Ryhel --- arch/arm/dts/Makefile | 1 + arch/arm/dts/tegra30-ouya.dts | 2063 +++++++++++++++++++++++++++ arch/arm/mach-tegra/tegra30/Kconfig | 5 + board/ouya/ouya/Kconfig | 12 + board/ouya/ouya/MAINTAINERS | 8 + board/ouya/ouya/Makefile | 11 + board/ouya/ouya/ouya-spl.c | 41 + board/ouya/ouya/ouya.c | 21 + board/ouya/ouya/ouya.env | 12 + configs/ouya_defconfig | 86 ++ doc/board/index.rst | 1 + doc/board/ouya/index.rst | 9 + doc/board/ouya/ouya.rst | 124 ++ include/configs/ouya.h | 23 + include/env/nvidia/prod_upd.env | 5 +- 15 files changed, 2420 insertions(+), 2 deletions(-) create mode 100644 arch/arm/dts/tegra30-ouya.dts create mode 100644 board/ouya/ouya/Kconfig create mode 100644 board/ouya/ouya/MAINTAINERS create mode 100644 board/ouya/ouya/Makefile create mode 100644 board/ouya/ouya/ouya-spl.c create mode 100644 board/ouya/ouya/ouya.c create mode 100644 board/ouya/ouya/ouya.env create mode 100644 configs/ouya_defconfig create mode 100644 doc/board/ouya/index.rst create mode 100644 doc/board/ouya/ouya.rst create mode 100644 include/configs/ouya.h diff --git a/arch/arm/dts/Makefile b/arch/arm/dts/Makefile index 73231824526..bad582c66b0 100644 --- a/arch/arm/dts/Makefile +++ b/arch/arm/dts/Makefile @@ -113,6 +113,7 @@ dtb-$(CONFIG_ARCH_TEGRA) += \ tegra30-lg-p880.dtb \ tegra30-lg-p895.dtb \ tegra30-microsoft-surface-rt.dtb \ + tegra30-ouya.dtb \ tegra30-tec-ng.dtb \ tegra30-wexler-qc750.dtb \ tegra114-dalmore.dtb \ diff --git a/arch/arm/dts/tegra30-ouya.dts b/arch/arm/dts/tegra30-ouya.dts new file mode 100644 index 00000000000..04453eb2432 --- /dev/null +++ b/arch/arm/dts/tegra30-ouya.dts @@ -0,0 +1,2063 @@ +// SPDX-License-Identifier: GPL-2.0 +/dts-v1/; + +#include +#include "tegra30.dtsi" + +/ { + model = "Ouya Game Console"; + compatible = "ouya,ouya", "nvidia,tegra30"; + + chosen { + stdout-path = &uartd; + }; + + aliases { + i2c0 = &pwr_i2c; + i2c1 = &hdmi_ddc; + + mmc0 = &sdmmc4; + + rtc0 = &pmic; + rtc1 = "/rtc@7000e000"; + + usb0 = µ_usb; + usb1 = ðernet_usb; + usb2 = &fullsize_usb; + }; + + memory { + device_type = "memory"; + reg = <0x80000000 0x40000000>; + }; + + host1x@50000000 { + dc@54200000 { + status = "disabled"; + }; + + hdmi: hdmi@54280000 { + status = "okay"; + + hdmi-supply = <&sys_3v3_reg>; + pll-supply = <&ldo7_reg>; + vdd-supply = <&vdd_vid_reg>; + + nvidia,hpd-gpio = <&gpio TEGRA_GPIO(N, 7) GPIO_ACTIVE_HIGH>; + nvidia,ddc-i2c-bus = <&hdmi_ddc>; + }; + }; + + gpio@6000d000 { + fan-en-hog { + gpio-hog; + gpios = ; + output-high; + }; + }; + + pinmux@70000868 { + pinctrl-names = "default"; + pinctrl-0 = <&state_default>; + + state_default: pinmux { + clk_32k_out_pa0 { + nvidia,pins = "clk_32k_out_pa0"; + nvidia,function = "blink"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + }; + + uart3_cts_n_pa1 { + nvidia,pins = "uart3_cts_n_pa1"; + nvidia,function = "uartc"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + }; + + dap2_fs_pa2 { + nvidia,pins = "dap2_fs_pa2"; + nvidia,function = "i2s1"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + }; + + dap2_sclk_pa3 { + nvidia,pins = "dap2_sclk_pa3"; + nvidia,function = "i2s1"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + }; + + dap2_din_pa4 { + nvidia,pins = "dap2_din_pa4"; + nvidia,function = "i2s1"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + }; + + dap2_dout_pa5 { + nvidia,pins = "dap2_dout_pa5"; + nvidia,function = "i2s1"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + }; + + sdmmc3_clk_pa6 { + nvidia,pins = "sdmmc3_clk_pa6"; + nvidia,function = "sdmmc3"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + }; + + sdmmc3_cmd_pa7 { + nvidia,pins = "sdmmc3_cmd_pa7"; + nvidia,function = "sdmmc3"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + }; + + gmi_a17_pb0 { + nvidia,pins = "gmi_a17_pb0"; + nvidia,function = "spi4"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + }; + + gmi_a18_pb1 { + nvidia,pins = "gmi_a18_pb1"; + nvidia,function = "spi4"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + }; + + lcd_pwr0_pb2 { + nvidia,pins = "lcd_pwr0_pb2"; + nvidia,function = "displaya"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + }; + + lcd_pclk_pb3 { + nvidia,pins = "lcd_pclk_pb3"; + nvidia,function = "displaya"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + }; + + sdmmc3_dat3_pb4 { + nvidia,pins = "sdmmc3_dat3_pb4"; + nvidia,function = "sdmmc3"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + }; + + sdmmc3_dat2_pb5 { + nvidia,pins = "sdmmc3_dat2_pb5"; + nvidia,function = "sdmmc3"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + }; + + sdmmc3_dat1_pb6 { + nvidia,pins = "sdmmc3_dat1_pb6"; + nvidia,function = "sdmmc3"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + }; + + sdmmc3_dat0_pb7 { + nvidia,pins = "sdmmc3_dat0_pb7"; + nvidia,function = "sdmmc3"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + }; + + uart3_rts_n_pc0 { + nvidia,pins = "uart3_rts_n_pc0"; + nvidia,function = "uartc"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + }; + + lcd_pwr1_pc1 { + nvidia,pins = "lcd_pwr1_pc1"; + nvidia,function = "displaya"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + }; + + uart2_txd_pc2 { + nvidia,pins = "uart2_txd_pc2"; + nvidia,function = "uartb"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + }; + + uart2_rxd_pc3 { + nvidia,pins = "uart2_rxd_pc3"; + nvidia,function = "uartb"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + }; + + gen1_i2c_scl_pc4 { + nvidia,pins = "gen1_i2c_scl_pc4"; + nvidia,function = "i2c1"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + nvidia,open-drain = ; + }; + + gen1_i2c_sda_pc5 { + nvidia,pins = "gen1_i2c_sda_pc5"; + nvidia,function = "i2c1"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + nvidia,open-drain = ; + }; + + lcd_pwr2_pc6 { + nvidia,pins = "lcd_pwr2_pc6"; + nvidia,function = "displaya"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + }; + + gmi_wp_n_pc7 { + nvidia,pins = "gmi_wp_n_pc7"; + nvidia,function = "gmi"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + }; + + sdmmc3_dat5_pd0 { + nvidia,pins = "sdmmc3_dat5_pd0"; + nvidia,function = "sdmmc3"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + }; + + sdmmc3_dat4_pd1 { + nvidia,pins = "sdmmc3_dat4_pd1"; + nvidia,function = "sdmmc3"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + }; + + lcd_dc1_pd2 { + nvidia,pins = "lcd_dc1_pd2"; + nvidia,function = "displaya"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + }; + + sdmmc3_dat6_pd3 { + nvidia,pins = "sdmmc3_dat6_pd3"; + nvidia,function = "spi4"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + }; + + sdmmc3_dat7_pd4 { + nvidia,pins = "sdmmc3_dat7_pd4"; + nvidia,function = "spi4"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + }; + + vi_d1_pd5 { + nvidia,pins = "vi_d1_pd5"; + nvidia,function = "sdmmc2"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + }; + + vi_vsync_pd6 { + nvidia,pins = "vi_vsync_pd6"; + nvidia,function = "ddr"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + }; + + vi_hsync_pd7 { + nvidia,pins = "vi_hsync_pd7"; + nvidia,function = "ddr"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + }; + + lcd_d0_pe0 { + nvidia,pins = "lcd_d0_pe0"; + nvidia,function = "displaya"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + }; + + lcd_d1_pe1 { + nvidia,pins = "lcd_d1_pe1"; + nvidia,function = "displaya"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + }; + + lcd_d2_pe2 { + nvidia,pins = "lcd_d2_pe2"; + nvidia,function = "displaya"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + }; + + lcd_d3_pe3 { + nvidia,pins = "lcd_d3_pe3"; + nvidia,function = "displaya"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + }; + + lcd_d4_pe4 { + nvidia,pins = "lcd_d4_pe4"; + nvidia,function = "displaya"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + }; + + lcd_d5_pe5 { + nvidia,pins = "lcd_d5_pe5"; + nvidia,function = "displaya"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + }; + + lcd_d6_pe6 { + nvidia,pins = "lcd_d6_pe6"; + nvidia,function = "displaya"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + }; + + lcd_d7_pe7 { + nvidia,pins = "lcd_d7_pe7"; + nvidia,function = "displaya"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + }; + + lcd_d8_pf0 { + nvidia,pins = "lcd_d8_pf0"; + nvidia,function = "displaya"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + }; + + lcd_d9_pf1 { + nvidia,pins = "lcd_d9_pf1"; + nvidia,function = "displaya"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + }; + + lcd_d10_pf2 { + nvidia,pins = "lcd_d10_pf2"; + nvidia,function = "displaya"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + }; + + lcd_d11_pf3 { + nvidia,pins = "lcd_d11_pf3"; + nvidia,function = "displaya"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + }; + + lcd_d12_pf4 { + nvidia,pins = "lcd_d12_pf4"; + nvidia,function = "displaya"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + }; + + lcd_d13_pf5 { + nvidia,pins = "lcd_d13_pf5"; + nvidia,function = "displaya"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + }; + + lcd_d14_pf6 { + nvidia,pins = "lcd_d14_pf6"; + nvidia,function = "displaya"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + }; + + lcd_d15_pf7 { + nvidia,pins = "lcd_d15_pf7"; + nvidia,function = "displaya"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + }; + + gmi_ad0_pg0 { + nvidia,pins = "gmi_ad0_pg0"; + nvidia,function = "nand"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + }; + + gmi_ad1_pg1 { + nvidia,pins = "gmi_ad1_pg1"; + nvidia,function = "nand"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + }; + + gmi_ad2_pg2 { + nvidia,pins = "gmi_ad2_pg2"; + nvidia,function = "nand"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + }; + + gmi_ad3_pg3 { + nvidia,pins = "gmi_ad3_pg3"; + nvidia,function = "nand"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + }; + + gmi_ad4_pg4 { + nvidia,pins = "gmi_ad4_pg4"; + nvidia,function = "nand"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + }; + + gmi_ad5_pg5 { + nvidia,pins = "gmi_ad5_pg5"; + nvidia,function = "nand"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + }; + + gmi_ad6_pg6 { + nvidia,pins = "gmi_ad6_pg6"; + nvidia,function = "nand"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + }; + + gmi_ad7_pg7 { + nvidia,pins = "gmi_ad7_pg7"; + nvidia,function = "nand"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + }; + + gmi_ad8_ph0 { + nvidia,pins = "gmi_ad8_ph0"; + nvidia,function = "pwm0"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + }; + + gmi_ad9_ph1 { + nvidia,pins = "gmi_ad9_ph1"; + nvidia,function = "pwm1"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + }; + + gmi_ad10_ph2 { + nvidia,pins = "gmi_ad10_ph2"; + nvidia,function = "pwm2"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + }; + + gmi_ad11_ph3 { + nvidia,pins = "gmi_ad11_ph3"; + nvidia,function = "nand"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + }; + + gmi_ad12_ph4 { + nvidia,pins = "gmi_ad12_ph4"; + nvidia,function = "nand"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + }; + + gmi_ad13_ph5 { + nvidia,pins = "gmi_ad13_ph5"; + nvidia,function = "nand"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + }; + + gmi_ad14_ph6 { + nvidia,pins = "gmi_ad14_ph6"; + nvidia,function = "nand"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + }; + + gmi_wr_n_pi0 { + nvidia,pins = "gmi_wr_n_pi0"; + nvidia,function = "nand"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + }; + + gmi_oe_n_pi1 { + nvidia,pins = "gmi_oe_n_pi1"; + nvidia,function = "nand"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + }; + + gmi_dqs_pi2 { + nvidia,pins = "gmi_dqs_pi2"; + nvidia,function = "nand"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + }; + + gmi_iordy_pi5 { + nvidia,pins = "gmi_iordy_pi5"; + nvidia,function = "rsvd1"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + }; + + gmi_cs7_n_pi6 { + nvidia,pins = "gmi_cs7_n_pi6"; + nvidia,function = "nand"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + }; + + gmi_wait_pi7 { + nvidia,pins = "gmi_wait_pi7"; + nvidia,function = "nand"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + }; + + lcd_de_pj1 { + nvidia,pins = "lcd_de_pj1"; + nvidia,function = "displaya"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + }; + + gmi_cs1_n_pj2 { + nvidia,pins = "gmi_cs1_n_pj2"; + nvidia,function = "rsvd1"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + }; + + lcd_hsync_pj3 { + nvidia,pins = "lcd_hsync_pj3"; + nvidia,function = "displaya"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + }; + + lcd_vsync_pj4 { + nvidia,pins = "lcd_vsync_pj4"; + nvidia,function = "displaya"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + }; + + uart2_cts_n_pj5 { + nvidia,pins = "uart2_cts_n_pj5"; + nvidia,function = "uartb"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + }; + + uart2_rts_n_pj6 { + nvidia,pins = "uart2_rts_n_pj6"; + nvidia,function = "uartb"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + }; + + gmi_a16_pj7 { + nvidia,pins = "gmi_a16_pj7"; + nvidia,function = "spi4"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + }; + + gmi_adv_n_pk0 { + nvidia,pins = "gmi_adv_n_pk0"; + nvidia,function = "nand"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + }; + + gmi_clk_pk1 { + nvidia,pins = "gmi_clk_pk1"; + nvidia,function = "nand"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + }; + + gmi_cs2_n_pk3 { + nvidia,pins = "gmi_cs2_n_pk3"; + nvidia,function = "rsvd1"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + }; + + gmi_cs3_n_pk4 { + nvidia,pins = "gmi_cs3_n_pk4"; + nvidia,function = "nand"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + }; + + spdif_out_pk5 { + nvidia,pins = "spdif_out_pk5"; + nvidia,function = "spdif"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + }; + + spdif_in_pk6 { + nvidia,pins = "spdif_in_pk6"; + nvidia,function = "spdif"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + }; + + gmi_a19_pk7 { + nvidia,pins = "gmi_a19_pk7"; + nvidia,function = "spi4"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + }; + + vi_d2_pl0 { + nvidia,pins = "vi_d2_pl0"; + nvidia,function = "sdmmc2"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + }; + + vi_d3_pl1 { + nvidia,pins = "vi_d3_pl1"; + nvidia,function = "sdmmc2"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + }; + + vi_d4_pl2 { + nvidia,pins = "vi_d4_pl2"; + nvidia,function = "vi"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + }; + + vi_d5_pl3 { + nvidia,pins = "vi_d5_pl3"; + nvidia,function = "sdmmc2"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + }; + + vi_d6_pl4 { + nvidia,pins = "vi_d6_pl4"; + nvidia,function = "vi"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + }; + + vi_d7_pl5 { + nvidia,pins = "vi_d7_pl5"; + nvidia,function = "sdmmc2"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + }; + + vi_d8_pl6 { + nvidia,pins = "vi_d8_pl6"; + nvidia,function = "sdmmc2"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + }; + + vi_d9_pl7 { + nvidia,pins = "vi_d9_pl7"; + nvidia,function = "sdmmc2"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + }; + + lcd_d16_pm0 { + nvidia,pins = "lcd_d16_pm0"; + nvidia,function = "displaya"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + }; + + lcd_d17_pm1 { + nvidia,pins = "lcd_d17_pm1"; + nvidia,function = "displaya"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + }; + + lcd_d18_pm2 { + nvidia,pins = "lcd_d18_pm2"; + nvidia,function = "displaya"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + }; + + lcd_d19_pm3 { + nvidia,pins = "lcd_d19_pm3"; + nvidia,function = "displaya"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + }; + + lcd_d20_pm4 { + nvidia,pins = "lcd_d20_pm4"; + nvidia,function = "displaya"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + }; + + lcd_d21_pm5 { + nvidia,pins = "lcd_d21_pm5"; + nvidia,function = "displaya"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + }; + + lcd_d22_pm6 { + nvidia,pins = "lcd_d22_pm6"; + nvidia,function = "displaya"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + }; + + lcd_d23_pm7 { + nvidia,pins = "lcd_d23_pm7"; + nvidia,function = "displaya"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + }; + + dap1_fs_pn0 { + nvidia,pins = "dap1_fs_pn0"; + nvidia,function = "i2s0"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + }; + + dap1_din_pn1 { + nvidia,pins = "dap1_din_pn1"; + nvidia,function = "i2s0"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + }; + + dap1_dout_pn2 { + nvidia,pins = "dap1_dout_pn2"; + nvidia,function = "i2s0"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + }; + + dap1_sclk_pn3 { + nvidia,pins = "dap1_sclk_pn3"; + nvidia,function = "i2s0"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + }; + + lcd_cs0_n_pn4 { + nvidia,pins = "lcd_cs0_n_pn4"; + nvidia,function = "displaya"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + }; + + lcd_sdout_pn5 { + nvidia,pins = "lcd_sdout_pn5"; + nvidia,function = "displaya"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + }; + + lcd_dc0_pn6 { + nvidia,pins = "lcd_dc0_pn6"; + nvidia,function = "displaya"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + }; + + hdmi_int_pn7 { + nvidia,pins = "hdmi_int_pn7"; + nvidia,function = "hdmi"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + }; + + ulpi_data7_po0 { + nvidia,pins = "ulpi_data7_po0"; + nvidia,function = "uarta"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + }; + + ulpi_data0_po1 { + nvidia,pins = "ulpi_data0_po1"; + nvidia,function = "uarta"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + }; + + ulpi_data1_po2 { + nvidia,pins = "ulpi_data1_po2"; + nvidia,function = "uarta"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + }; + + ulpi_data2_po3 { + nvidia,pins = "ulpi_data2_po3"; + nvidia,function = "uarta"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + }; + + ulpi_data3_po4 { + nvidia,pins = "ulpi_data3_po4"; + nvidia,function = "uarta"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + }; + + ulpi_data4_po5 { + nvidia,pins = "ulpi_data4_po5"; + nvidia,function = "uarta"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + }; + + ulpi_data5_po6 { + nvidia,pins = "ulpi_data5_po6"; + nvidia,function = "uarta"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + }; + + ulpi_data6_po7 { + nvidia,pins = "ulpi_data6_po7"; + nvidia,function = "uarta"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + }; + + dap3_fs_pp0 { + nvidia,pins = "dap3_fs_pp0"; + nvidia,function = "i2s2"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + }; + + dap3_din_pp1 { + nvidia,pins = "dap3_din_pp1"; + nvidia,function = "i2s2"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + }; + + dap3_dout_pp2 { + nvidia,pins = "dap3_dout_pp2"; + nvidia,function = "i2s2"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + }; + + dap3_sclk_pp3 { + nvidia,pins = "dap3_sclk_pp3"; + nvidia,function = "i2s2"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + }; + + dap4_fs_pp4 { + nvidia,pins = "dap4_fs_pp4"; + nvidia,function = "i2s3"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + }; + + dap4_din_pp5 { + nvidia,pins = "dap4_din_pp5"; + nvidia,function = "i2s3"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + }; + + dap4_dout_pp6 { + nvidia,pins = "dap4_dout_pp6"; + nvidia,function = "i2s3"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + }; + + dap4_sclk_pp7 { + nvidia,pins = "dap4_sclk_pp7"; + nvidia,function = "i2s3"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + }; + + kb_col0_pq0 { + nvidia,pins = "kb_col0_pq0"; + nvidia,function = "kbc"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + }; + + kb_col1_pq1 { + nvidia,pins = "kb_col1_pq1"; + nvidia,function = "kbc"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + }; + + kb_col2_pq2 { + nvidia,pins = "kb_col2_pq2"; + nvidia,function = "kbc"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + }; + + kb_col3_pq3 { + nvidia,pins = "kb_col3_pq3"; + nvidia,function = "kbc"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + }; + + kb_col4_pq4 { + nvidia,pins = "kb_col4_pq4"; + nvidia,function = "kbc"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + }; + + kb_col5_pq5 { + nvidia,pins = "kb_col5_pq5"; + nvidia,function = "kbc"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + }; + + kb_col6_pq6 { + nvidia,pins = "kb_col6_pq6"; + nvidia,function = "kbc"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + }; + + kb_col7_pq7 { + nvidia,pins = "kb_col7_pq7"; + nvidia,function = "kbc"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + }; + + kb_row0_pr0 { + nvidia,pins = "kb_row0_pr0"; + nvidia,function = "kbc"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + }; + + kb_row1_pr1 { + nvidia,pins = "kb_row1_pr1"; + nvidia,function = "kbc"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + }; + + kb_row2_pr2 { + nvidia,pins = "kb_row2_pr2"; + nvidia,function = "kbc"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + }; + + kb_row3_pr3 { + nvidia,pins = "kb_row3_pr3"; + nvidia,function = "kbc"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + }; + + kb_row4_pr4 { + nvidia,pins = "kb_row4_pr4"; + nvidia,function = "kbc"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + }; + + kb_row5_pr5 { + nvidia,pins = "kb_row5_pr5"; + nvidia,function = "kbc"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + }; + + kb_row6_pr6 { + nvidia,pins = "kb_row6_pr6"; + nvidia,function = "kbc"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + }; + + kb_row7_pr7 { + nvidia,pins = "kb_row7_pr7"; + nvidia,function = "kbc"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + }; + + kb_row8_ps0 { + nvidia,pins = "kb_row8_ps0"; + nvidia,function = "kbc"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + }; + + kb_row9_ps1 { + nvidia,pins = "kb_row9_ps1"; + nvidia,function = "kbc"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + }; + + kb_row10_ps2 { + nvidia,pins = "kb_row10_ps2"; + nvidia,function = "kbc"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + }; + + kb_row11_ps3 { + nvidia,pins = "kb_row11_ps3"; + nvidia,function = "kbc"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + }; + + kb_row12_ps4 { + nvidia,pins = "kb_row12_ps4"; + nvidia,function = "kbc"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + }; + + kb_row13_ps5 { + nvidia,pins = "kb_row13_ps5"; + nvidia,function = "kbc"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + }; + + kb_row14_ps6 { + nvidia,pins = "kb_row14_ps6"; + nvidia,function = "kbc"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + }; + + kb_row15_ps7 { + nvidia,pins = "kb_row15_ps7"; + nvidia,function = "kbc"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + }; + + vi_pclk_pt0 { + nvidia,pins = "vi_pclk_pt0"; + nvidia,function = "rsvd1"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + }; + + vi_mclk_pt1 { + nvidia,pins = "vi_mclk_pt1"; + nvidia,function = "vi"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + }; + + vi_d10_pt2 { + nvidia,pins = "vi_d10_pt2"; + nvidia,function = "ddr"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + }; + + vi_d11_pt3 { + nvidia,pins = "vi_d11_pt3"; + nvidia,function = "ddr"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + }; + + vi_d0_pt4 { + nvidia,pins = "vi_d0_pt4"; + nvidia,function = "ddr"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + }; + + gen2_i2c_scl_pt5 { + nvidia,pins = "gen2_i2c_scl_pt5"; + nvidia,function = "i2c2"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + nvidia,open-drain = ; + }; + + gen2_i2c_sda_pt6 { + nvidia,pins = "gen2_i2c_sda_pt6"; + nvidia,function = "i2c2"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + nvidia,open-drain = ; + }; + + pu0 { + nvidia,pins = "pu0"; + nvidia,function = "owr"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + }; + + pu1 { + nvidia,pins = "pu1"; + nvidia,function = "rsvd1"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + }; + + pu2 { + nvidia,pins = "pu2"; + nvidia,function = "rsvd1"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + }; + + pu3 { + nvidia,pins = "pu3"; + nvidia,function = "pwm0"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + }; + + pu4 { + nvidia,pins = "pu4"; + nvidia,function = "pwm1"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + }; + + pu5 { + nvidia,pins = "pu5"; + nvidia,function = "rsvd4"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + }; + + pu6 { + nvidia,pins = "pu6"; + nvidia,function = "pwm3"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + }; + + jtag_rtck_pu7 { + nvidia,pins = "jtag_rtck_pu7"; + nvidia,function = "rtck"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + }; + + pv0 { + nvidia,pins = "pv0"; + nvidia,function = "rsvd1"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + }; + + pv1 { + nvidia,pins = "pv1"; + nvidia,function = "rsvd1"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + }; + + pv2 { + nvidia,pins = "pv2"; + nvidia,function = "owr"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + }; + + pv3 { + nvidia,pins = "pv3"; + nvidia,function = "clk_12m_out"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + }; + + ddc_scl_pv4 { + nvidia,pins = "ddc_scl_pv4"; + nvidia,function = "i2c4"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + }; + + ddc_sda_pv5 { + nvidia,pins = "ddc_sda_pv5"; + nvidia,function = "i2c4"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + }; + + crt_hsync_pv6 { + nvidia,pins = "crt_hsync_pv6"; + nvidia,function = "crt"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + }; + + crt_vsync_pv7 { + nvidia,pins = "crt_vsync_pv7"; + nvidia,function = "crt"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + }; + + lcd_cs1_n_pw0 { + nvidia,pins = "lcd_cs1_n_pw0"; + nvidia,function = "displaya"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + }; + + lcd_m1_pw1 { + nvidia,pins = "lcd_m1_pw1"; + nvidia,function = "displaya"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + }; + + spi2_cs1_n_pw2 { + nvidia,pins = "spi2_cs1_n_pw2"; + nvidia,function = "spi2"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + }; + + clk1_out_pw4 { + nvidia,pins = "clk1_out_pw4"; + nvidia,function = "extperiph1"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + }; + + clk2_out_pw5 { + nvidia,pins = "clk2_out_pw5"; + nvidia,function = "extperiph2"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + }; + + uart3_txd_pw6 { + nvidia,pins = "uart3_txd_pw6"; + nvidia,function = "uartc"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + }; + + uart3_rxd_pw7 { + nvidia,pins = "uart3_rxd_pw7"; + nvidia,function = "uartc"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + }; + + spi2_sck_px2 { + nvidia,pins = "spi2_sck_px2"; + nvidia,function = "gmi"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + }; + + spi1_mosi_px4 { + nvidia,pins = "spi1_mosi_px4"; + nvidia,function = "spi1"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + }; + + spi1_sck_px5 { + nvidia,pins = "spi1_sck_px5"; + nvidia,function = "spi1"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + }; + + spi1_cs0_n_px6 { + nvidia,pins = "spi1_cs0_n_px6"; + nvidia,function = "spi1"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + }; + + spi1_miso_px7 { + nvidia,pins = "spi1_miso_px7"; + nvidia,function = "spi1"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + }; + + ulpi_clk_py0 { + nvidia,pins = "ulpi_clk_py0"; + nvidia,function = "uartd"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + }; + + ulpi_dir_py1 { + nvidia,pins = "ulpi_dir_py1"; + nvidia,function = "uartd"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + }; + + ulpi_nxt_py2 { + nvidia,pins = "ulpi_nxt_py2"; + nvidia,function = "uartd"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + }; + + ulpi_stp_py3 { + nvidia,pins = "ulpi_stp_py3"; + nvidia,function = "uartd"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + }; + + sdmmc1_dat3_py4 { + nvidia,pins = "sdmmc1_dat3_py4"; + nvidia,function = "sdmmc1"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + }; + + sdmmc1_dat2_py5 { + nvidia,pins = "sdmmc1_dat2_py5"; + nvidia,function = "sdmmc1"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + }; + + sdmmc1_dat1_py6 { + nvidia,pins = "sdmmc1_dat1_py6"; + nvidia,function = "sdmmc1"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + }; + + sdmmc1_dat0_py7 { + nvidia,pins = "sdmmc1_dat0_py7"; + nvidia,function = "sdmmc1"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + }; + + sdmmc1_clk_pz0 { + nvidia,pins = "sdmmc1_clk_pz0"; + nvidia,function = "sdmmc1"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + }; + + sdmmc1_cmd_pz1 { + nvidia,pins = "sdmmc1_cmd_pz1"; + nvidia,function = "sdmmc1"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + }; + + lcd_sdin_pz2 { + nvidia,pins = "lcd_sdin_pz2"; + nvidia,function = "displaya"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + }; + + lcd_wr_n_pz3 { + nvidia,pins = "lcd_wr_n_pz3"; + nvidia,function = "displaya"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + }; + + lcd_sck_pz4 { + nvidia,pins = "lcd_sck_pz4"; + nvidia,function = "displaya"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + }; + + sys_clk_req_pz5 { + nvidia,pins = "sys_clk_req_pz5"; + nvidia,function = "sysclk"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + }; + + pwr_i2c_scl_pz6 { + nvidia,pins = "pwr_i2c_scl_pz6"; + nvidia,function = "i2cpwr"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + nvidia,open-drain = ; + }; + + pwr_i2c_sda_pz7 { + nvidia,pins = "pwr_i2c_sda_pz7"; + nvidia,function = "i2cpwr"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + nvidia,open-drain = ; + }; + + pbb0 { + nvidia,pins = "pbb0"; + nvidia,function = "i2s4"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + }; + + cam_i2c_scl_pbb1 { + nvidia,pins = "cam_i2c_scl_pbb1"; + nvidia,function = "i2c3"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + nvidia,open-drain = ; + }; + + cam_i2c_sda_pbb2 { + nvidia,pins = "cam_i2c_sda_pbb2"; + nvidia,function = "i2c3"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + nvidia,open-drain = ; + }; + + pbb3 { + nvidia,pins = "pbb3"; + nvidia,function = "vgp3"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + }; + + pbb4 { + nvidia,pins = "pbb4"; + nvidia,function = "vgp4"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + }; + + pbb5 { + nvidia,pins = "pbb5"; + nvidia,function = "vgp5"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + }; + + pbb6 { + nvidia,pins = "pbb6"; + nvidia,function = "vgp6"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + }; + + pbb7 { + nvidia,pins = "pbb7"; + nvidia,function = "i2s4"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + }; + + pcc1 { + nvidia,pins = "pcc1"; + nvidia,function = "i2s4"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + }; + + pcc2 { + nvidia,pins = "pcc2"; + nvidia,function = "i2s4"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + }; + + clk2_req_pcc5 { + nvidia,pins = "clk2_req_pcc5"; + nvidia,function = "dap"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + }; + + pex_l2_rst_n_pcc6 { + nvidia,pins = "pex_l2_rst_n_pcc6"; + nvidia,function = "pcie"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + }; + + pex_l2_clkreq_n_pcc7 { + nvidia,pins = "pex_l2_clkreq_n_pcc7"; + nvidia,function = "pcie"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + }; + + pex_l0_prsnt_n_pdd0 { + nvidia,pins = "pex_l0_prsnt_n_pdd0"; + nvidia,function = "pcie"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + }; + + pex_l0_rst_n_pdd1 { + nvidia,pins = "pex_l0_rst_n_pdd1"; + nvidia,function = "pcie"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + }; + + pex_l0_clkreq_n_pdd2 { + nvidia,pins = "pex_l0_clkreq_n_pdd2"; + nvidia,function = "pcie"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + }; + + pex_wake_n_pdd3 { + nvidia,pins = "pex_wake_n_pdd3"; + nvidia,function = "pcie"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + }; + + pex_l1_prsnt_n_pdd4 { + nvidia,pins = "pex_l1_prsnt_n_pdd4"; + nvidia,function = "pcie"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + }; + + pex_l1_rst_n_pdd5 { + nvidia,pins = "pex_l1_rst_n_pdd5"; + nvidia,function = "pcie"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + }; + + pex_l1_clkreq_n_pdd6 { + nvidia,pins = "pex_l1_clkreq_n_pdd6"; + nvidia,function = "pcie"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + }; + + pex_l2_prsnt_n_pdd7 { + nvidia,pins = "pex_l2_prsnt_n_pdd7"; + nvidia,function = "pcie"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + }; + + clk3_out_pee0 { + nvidia,pins = "clk3_out_pee0"; + nvidia,function = "extperiph3"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + }; + + clk3_req_pee1 { + nvidia,pins = "clk3_req_pee1"; + nvidia,function = "dev3"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + }; + + clk1_req_pee2 { + nvidia,pins = "clk1_req_pee2"; + nvidia,function = "dap"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + }; + + hdmi_cec_pee3 { + nvidia,pins = "hdmi_cec_pee3"; + nvidia,function = "cec"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + nvidia,open-drain = ; + }; + + owr { + nvidia,pins = "owr"; + nvidia,function = "owr"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + }; + + /* SDMMC4 pinmux */ + sdmmc4_clk { + nvidia,pins = "sdmmc4_clk_pcc4"; + nvidia,function = "sdmmc4"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + nvidia,lock = ; + nvidia,io-reset = ; + }; + sdmmc4_cmd { + nvidia,pins = "sdmmc4_cmd_pt7", + "sdmmc4_dat0_paa0", + "sdmmc4_dat1_paa1", + "sdmmc4_dat2_paa2", + "sdmmc4_dat3_paa3", + "sdmmc4_dat4_paa4", + "sdmmc4_dat5_paa5", + "sdmmc4_dat6_paa6", + "sdmmc4_dat7_paa7"; + nvidia,function = "sdmmc4"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + nvidia,lock = ; + nvidia,io-reset = ; + }; + sdmmc4_rst_n { + nvidia,pins = "sdmmc4_rst_n_pcc3"; + nvidia,function = "rsvd2"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + }; + cam_mclk { + nvidia,pins = "cam_mclk_pcc0"; + nvidia,function = "vi_alt3"; + nvidia,pull = ; + nvidia,tristate = ; + nvidia,enable-input = ; + }; + + drive_groups { + nvidia,pins = "drive_gma", + "drive_gmb", + "drive_gmc", + "drive_gmd"; + nvidia,pull-down-strength = <9>; + nvidia,pull-up-strength = <9>; + nvidia,slew-rate-rising = ; + nvidia,slew-rate-falling = ; + }; + }; + }; + + uartd: serial@70006300 { + status = "okay"; + }; + + hdmi_ddc: i2c@7000c700 { + status = "okay"; + clock-frequency = <100000>; + }; + + pwr_i2c: i2c@7000d000 { + status = "okay"; + clock-frequency = <400000>; + + pmic: pmic@2d { + compatible = "ti,tps65911"; + reg = <0x2d>; + + interrupts = ; + #interrupt-cells = <2>; + interrupt-controller; + wakeup-source; + + ti,en-gpio-sleep = <0 1 1 1 1 1 0 0 1>; + ti,system-power-controller; + ti,sleep-keep-ck32k; + ti,sleep-enable; + + #gpio-cells = <2>; + gpio-controller; + + regulators { + vdd_1v8: vddio { + regulator-name = "vdd_1v8_gen"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-always-on; + regulator-boot-on; + }; + + ldo7_reg: ldo7 { + regulator-name = "vdd_pllm,x,u,a_p_c_s"; + regulator-min-microvolt = <1200000>; + regulator-max-microvolt = <1200000>; + regulator-boot-on; + }; + }; + }; + }; + + sdmmc4: sdhci@78000600 { + status = "okay"; + bus-width = <8>; + non-removable; + + vmmc-supply = <&sys_3v3_reg>; + vqmmc-supply = <&vdd_1v8>; + }; + + micro_usb: usb@7d000000 { + status = "okay"; + dr_mode = "otg"; + }; + + usb-phy@7d000000 { + status = "okay"; + }; + + ethernet_usb: usb@7d004000 { + status = "okay"; + nvidia,vbus-gpio = <&gpio TEGRA_GPIO(DD, 5) GPIO_ACTIVE_HIGH>; + + #address-cells = <1>; + #size-cells = <0>; + + /* SMSC 10/100T Ethernet Controller */ + ethernet@2 { + compatible = "usb424,9e00"; + reg = <2>; + local-mac-address = [00 11 22 33 44 55]; + }; + }; + + usb-phy@7d004000 { + status = "okay"; + }; + + fullsize_usb: usb@7d008000 { + status = "okay"; + nvidia,vbus-gpio = <&gpio TEGRA_GPIO(DD, 4) GPIO_ACTIVE_HIGH>; + }; + + usb-phy@7d008000 { + status = "okay"; + }; + + /* PMIC has a built-in 32KHz oscillator which is used by PMC */ + clk32k_in: clock { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <32768>; + clock-output-names = "pmic-oscillator"; + }; + + gpio-keys { + compatible = "gpio-keys"; + + key-power { + label = "Power"; + gpios = <&gpio TEGRA_GPIO(V, 0) GPIO_ACTIVE_LOW>; + linux,code = ; + }; + }; + + leds { + compatible = "gpio-leds"; + + led-power { + label = "power-led"; + gpios = <&gpio TEGRA_GPIO(H, 2) GPIO_ACTIVE_HIGH>; + default-state = "on"; + linux,default-trigger = "heartbeat"; + retain-state-suspended; + }; + }; + + sys_3v3_reg: regulator-sys-3v3 { + compatible = "regulator-fixed"; + regulator-name = "sys_3v3"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-always-on; + regulator-boot-on; + }; + + vdd_vid_reg: regulator-vdd-vid { + compatible = "regulator-fixed"; + regulator-name = "vddio_vid"; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + regulator-boot-on; + gpio = <&gpio TEGRA_GPIO(T, 0) GPIO_ACTIVE_HIGH>; + enable-active-high; + }; +}; diff --git a/arch/arm/mach-tegra/tegra30/Kconfig b/arch/arm/mach-tegra/tegra30/Kconfig index e0f054af8e0..b5099ce67fc 100644 --- a/arch/arm/mach-tegra/tegra30/Kconfig +++ b/arch/arm/mach-tegra/tegra30/Kconfig @@ -32,6 +32,10 @@ config TARGET_IDEAPAD_YOGA_11 bool "Lenovo Ideapad Yoga 11 board" select BOARD_LATE_INIT +config TARGET_OUYA + bool "Ouya Game Console board" + select BOARD_LATE_INIT + config TARGET_QC750 bool "Wexler QC750 board" select BOARD_LATE_INIT @@ -64,6 +68,7 @@ source "board/toradex/colibri_t30/Kconfig" source "board/htc/endeavoru/Kconfig" source "board/asus/grouper/Kconfig" source "board/lenovo/ideapad-yoga-11/Kconfig" +source "board/ouya/ouya/Kconfig" source "board/wexler/qc750/Kconfig" source "board/microsoft/surface-rt/Kconfig" source "board/avionic-design/tec-ng/Kconfig" diff --git a/board/ouya/ouya/Kconfig b/board/ouya/ouya/Kconfig new file mode 100644 index 00000000000..6bab40ce933 --- /dev/null +++ b/board/ouya/ouya/Kconfig @@ -0,0 +1,12 @@ +if TARGET_OUYA + +config SYS_BOARD + default "ouya" + +config SYS_VENDOR + default "ouya" + +config SYS_CONFIG_NAME + default "ouya" + +endif diff --git a/board/ouya/ouya/MAINTAINERS b/board/ouya/ouya/MAINTAINERS new file mode 100644 index 00000000000..7f664b2e65f --- /dev/null +++ b/board/ouya/ouya/MAINTAINERS @@ -0,0 +1,8 @@ +OUYA BOARD +M: Svyatoslav Ryhel +M: Peter Geis +S: Maintained +F: board/ouya/ouya/ +F: configs/ouya_defconfig +F: doc/board/ouya/ouya.rst +F: include/configs/ouya.h diff --git a/board/ouya/ouya/Makefile b/board/ouya/ouya/Makefile new file mode 100644 index 00000000000..d479ec83e5e --- /dev/null +++ b/board/ouya/ouya/Makefile @@ -0,0 +1,11 @@ +# SPDX-License-Identifier: GPL-2.0+ +# +# (C) Copyright 2010-2012 +# NVIDIA Corporation +# +# (C) Copyright 2021 +# Svyatoslav Ryhel + +obj-$(CONFIG_XPL_BUILD) += ouya-spl.o + +obj-y += ouya.o diff --git a/board/ouya/ouya/ouya-spl.c b/board/ouya/ouya/ouya-spl.c new file mode 100644 index 00000000000..1f45853c8be --- /dev/null +++ b/board/ouya/ouya/ouya-spl.c @@ -0,0 +1,41 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * T30 Ouya SPL stage configuration + * + * (C) Copyright 2010-2013 + * NVIDIA Corporation + * + * (C) Copyright 2025 + * Svyatoslav Ryhel + */ + +#include +#include +#include + +#define TPS65911_I2C_ADDR (0x2D << 1) +#define TPS65911_VDDCTRL_OP_REG 0x28 +#define TPS65911_VDDCTRL_SR_REG 0x27 +#define TPS65911_VDDCTRL_OP_DATA (0x2400 | TPS65911_VDDCTRL_OP_REG) +#define TPS65911_VDDCTRL_SR_DATA (0x0100 | TPS65911_VDDCTRL_SR_REG) + +#define TPS62361B_I2C_ADDR (0x60 << 1) +#define TPS62361B_SET3_REG 0x03 +#define TPS62361B_SET3_DATA (0x4600 | TPS62361B_SET3_REG) + +void pmic_enable_cpu_vdd(void) +{ + /* Set VDD_CORE to 1.200V. */ + tegra_i2c_ll_write(TPS62361B_I2C_ADDR, TPS62361B_SET3_DATA); + + udelay(1000); + + /* + * Bring up CPU VDD via the TPS65911x PMIC on the DVC I2C bus. + * First set VDD to 1.0125V, then enable the VDD regulator. + */ + tegra_i2c_ll_write(TPS65911_I2C_ADDR, TPS65911_VDDCTRL_OP_DATA); + udelay(1000); + tegra_i2c_ll_write(TPS65911_I2C_ADDR, TPS65911_VDDCTRL_SR_DATA); + udelay(10 * 1000); +} diff --git a/board/ouya/ouya/ouya.c b/board/ouya/ouya/ouya.c new file mode 100644 index 00000000000..6d6eb54afe2 --- /dev/null +++ b/board/ouya/ouya/ouya.c @@ -0,0 +1,21 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * (C) Copyright 2010-2013 + * NVIDIA Corporation + * + * (C) Copyright 2025 + * Svyatoslav Ryhel + */ + +#include + +#if defined(CONFIG_OF_LIBFDT) && defined(CONFIG_OF_BOARD_SETUP) +int ft_board_setup(void *blob, struct bd_info *bd) +{ + /* Remove TrustZone nodes */ + fdt_del_node_and_alias(blob, "/firmware"); + fdt_del_node_and_alias(blob, "/reserved-memory/trustzone@bfe00000"); + + return 0; +} +#endif diff --git a/board/ouya/ouya/ouya.env b/board/ouya/ouya/ouya.env new file mode 100644 index 00000000000..6ec881b910a --- /dev/null +++ b/board/ouya/ouya/ouya.env @@ -0,0 +1,12 @@ +#include + +partitions=name=emmc,start=0,size=-,uuid=${uuid_gpt_rootfs} +boot_interface=usb + +bootmenu_0=mount internal storage=usb start && ums 0 mmc 0; bootmenu +bootmenu_1=fastboot=echo Starting Fastboot protocol ...; fastboot usb 0; bootmenu +bootmenu_2=update bootloader=run flash_uboot +bootmenu_3=reboot RCM=enterrcm +bootmenu_4=reboot=reset +bootmenu_5=power off=poweroff +bootmenu_delay=-1 diff --git a/configs/ouya_defconfig b/configs/ouya_defconfig new file mode 100644 index 00000000000..ccd6ae4d36f --- /dev/null +++ b/configs/ouya_defconfig @@ -0,0 +1,86 @@ +CONFIG_ARM=y +CONFIG_ARCH_TEGRA=y +CONFIG_SUPPORT_PASSING_ATAGS=y +CONFIG_CMDLINE_TAG=y +CONFIG_INITRD_TAG=y +CONFIG_TEXT_BASE=0x80110000 +CONFIG_NR_DRAM_BANKS=2 +CONFIG_ENV_SOURCE_FILE="ouya" +CONFIG_ENV_SIZE=0x3000 +CONFIG_ENV_OFFSET=0xFFFFD000 +CONFIG_DEFAULT_DEVICE_TREE="tegra30-ouya" +CONFIG_SPL_STACK=0x800ffffc +CONFIG_SPL_TEXT_BASE=0x80108000 +CONFIG_SYS_LOAD_ADDR=0x82000000 +CONFIG_TEGRA30=y +CONFIG_TARGET_OUYA=y +CONFIG_TEGRA_ENABLE_UARTD=y +CONFIG_CMD_EBTUPDATE=y +CONFIG_BUTTON_CMD=y +CONFIG_BOOTDELAY=3 +CONFIG_OF_BOARD_SETUP=y +CONFIG_OF_SYSTEM_SETUP=y +CONFIG_BOOTCOMMAND="bootflow scan; echo 'Boot configuration not found... Power off in 3 sec'; sleep 3; poweroff" +CONFIG_USE_PREBOOT=y +CONFIG_SYS_PBSIZE=2084 +CONFIG_SPL_FOOTPRINT_LIMIT=y +CONFIG_SPL_MAX_FOOTPRINT=0x8000 +# CONFIG_SPL_SHARES_INIT_SP_ADDR is not set +CONFIG_SPL_SYS_MALLOC=y +CONFIG_SPL_HAS_CUSTOM_MALLOC_START=y +CONFIG_SPL_CUSTOM_SYS_MALLOC_ADDR=0x80090000 +CONFIG_SPL_SYS_MALLOC_SIZE=0x10000 +CONFIG_SYS_PROMPT="Tegra30 (Ouya) # " +# CONFIG_CMD_BOOTEFI_BOOTMGR is not set +CONFIG_CMD_BOOTMENU=y +# CONFIG_CMD_IMI is not set +CONFIG_CMD_GPIO=y +CONFIG_CMD_GPT=y +CONFIG_CMD_GPT_RENAME=y +CONFIG_CMD_I2C=y +CONFIG_CMD_MMC=y +CONFIG_CMD_POWEROFF=y +CONFIG_CMD_USB=y +CONFIG_CMD_USB_MASS_STORAGE=y +CONFIG_CMD_UMS_ABORT_KEYED=y +# CONFIG_CMD_SETEXPR is not set +CONFIG_CMD_PAUSE=y +CONFIG_CMD_REGULATOR=y +CONFIG_CMD_EXT4_WRITE=y +# CONFIG_SPL_DOS_PARTITION is not set +# CONFIG_SPL_EFI_PARTITION is not set +CONFIG_ENV_OVERWRITE=y +CONFIG_SYS_RELOC_GD_ENV_ADDR=y +CONFIG_SYS_MMC_ENV_PART=2 +CONFIG_BUTTON=y +CONFIG_USB_FUNCTION_FASTBOOT=y +CONFIG_FASTBOOT_BUF_ADDR=0x91000000 +CONFIG_FASTBOOT_BUF_SIZE=0x10000000 +CONFIG_FASTBOOT_FLASH=y +CONFIG_FASTBOOT_FLASH_MMC_DEV=0 +CONFIG_FASTBOOT_CMD_OEM_FORMAT=y +CONFIG_GPIO_HOG=y +CONFIG_SYS_I2C_TEGRA=y +CONFIG_BUTTON_KEYBOARD=y +CONFIG_LED=y +CONFIG_LED_BLINK=y +CONFIG_LED_GPIO=y +CONFIG_DM_PMIC=y +CONFIG_DM_PMIC_TPS65910=y +CONFIG_DM_REGULATOR=y +CONFIG_DM_REGULATOR_FIXED=y +CONFIG_DM_REGULATOR_TPS65911=y +CONFIG_PWM_TEGRA=y +CONFIG_SYS_NS16550=y +CONFIG_SYSRESET_TPS65910=y +CONFIG_USB=y +CONFIG_USB_EHCI_HCD=y +CONFIG_USB_EHCI_TEGRA=y +CONFIG_USB_KEYBOARD=y +CONFIG_USB_GADGET=y +CONFIG_CI_UDC=y +CONFIG_VIDEO=y +# CONFIG_VIDEO_LOGO is not set +CONFIG_I2C_EDID_STANDARD=y +CONFIG_VIDEO_BRIDGE=y +CONFIG_VIDEO_HDMI_TEGRA=y diff --git a/doc/board/index.rst b/doc/board/index.rst index 84c135e02c1..7ad1137c94a 100644 --- a/doc/board/index.rst +++ b/doc/board/index.rst @@ -43,6 +43,7 @@ Board-specific doc microsoft/index nxp/index openpiton/index + ouya/index phytec/index purism/index qualcomm/index diff --git a/doc/board/ouya/index.rst b/doc/board/ouya/index.rst new file mode 100644 index 00000000000..7413240a1b8 --- /dev/null +++ b/doc/board/ouya/index.rst @@ -0,0 +1,9 @@ +.. SPDX-License-Identifier: GPL-2.0+ + +OUYA +==== + +.. toctree:: + :maxdepth: 2 + + ouya diff --git a/doc/board/ouya/ouya.rst b/doc/board/ouya/ouya.rst new file mode 100644 index 00000000000..641affc6294 --- /dev/null +++ b/doc/board/ouya/ouya.rst @@ -0,0 +1,124 @@ +.. SPDX-License-Identifier: GPL-2.0+ + +U-Boot for the Ouya Game Console (ouya) +======================================= + +``DISCLAMER!`` Moving your Ouya to use U-Boot assumes replacement of the +vendor bootloader. Vendor android firmwares will no longer be able to run on the +device. This replacement IS reversible. + +Quick Start +----------- + +- Build U-Boot +- Process U-Boot +- Flashing U-Boot into the eMMC +- Boot +- Self Upgrading + +Build U-Boot +------------ + +.. code-block:: bash + + $ export CROSS_COMPILE=arm-none-eabi- + $ make ouya_defconfig + $ make + +After the build succeeds, you will obtain the final ``u-boot-dtb-tegra.bin`` +image, ready for further processing. + +Process U-Boot +-------------- + +``DISCLAMER!`` All questions related to the re-crypt work should be asked +in re-crypt repo issues. NOT HERE! + +re-crypt is a tool that processes the ``u-boot-dtb-tegra.bin`` binary into form +usable by device. This process is required only on the first installation or +to recover the device in case of a failed update. + +Permanent installation can be performed either by using the nv3p protocol or by +pre-loading just built U-Boot into RAM. + +Processing for the NV3P protocol +******************************** + +.. code-block:: bash + + $ git clone https://gitlab.com/grate-driver/re-crypt.git + $ cd re-crypt # place your u-boot-dtb-tegra.bin here + $ ./re-crypt.py --dev ouya + +The script will produce a ``repart-block.bin`` ready to flash. + +Processing for pre-loaded U-Boot +******************************** + +The procedure is the same, but the ``--split`` argument is used with the +``re-crypt.py``. The script will produce ``bct.img`` and ``ebt.img`` ready +to flash. + +Flashing U-Boot into the eMMC +----------------------------- + +Permanent installation can be performed either by using the nv3p protocol or by +pre-loading just built U-Boot into RAM. Regardless of the method bct and bootloader +will end up in boot0 and boot1 partitions of eMMC. + +Flashing with the NV3P protocol +******************************* + +``DISCLAMER!`` All questions related to NvFlash should be asked in the proper +place. NOT HERE! Flashing U-Boot will erase all eMMC, so make a backup before! + +Nv3p is a custom Nvidia protocol used to recover bricked devices. Devices can +enter it by pre-loading vendor bootloader with the Fusée Gelée. + +With nv3p, ``repart-block.bin`` is used. It contains BCT and a bootloader in +encrypted state in form, which can just be written RAW at the start of eMMC. + +.. code-block:: bash + + $ ./run_bootloader.sh -s T30 -t ./bct/ouya.bct -b android_bootloader.bin + $ ./utiils/nvflash_v1.13.87205 --resume --rawdevicewrite 0 1024 repart-block.bin + +When flashing is done, reboot the device. + +Flashing with a pre-loaded U-Boot +********************************* + +U-Boot pre-loaded into RAM acts the same as when it was booted "cold". Currently +U-Boot supports bootmenu entry fastboot, which allows to write a processed copy +of U-Boot permanently into eMMC. + +While pre-loading U-Boot, interrupt bootflow by pressing ``CTRL + C`` (USB keyboard +must be plugged in before U-Boot is preloaded, else it will not work), input +``bootmenu`` from the keyboard and hit enter. The bootmenu will appear. There, select +``fastboot`` using the up and down arrows and enter key. After, on host PC, do: + +.. code-block:: bash + + $ fastboot flash 0.1 bct.img + $ fastboot flash 0.2 ebt.img + $ fastboot reboot + +Device will reboot. + +Boot +---- + +To boot Linux, U-Boot will look for an ``extlinux.conf`` on eMMC. Additionally, +bootmenu provides entries to mount eMMC as mass storage, fastboot, reboot, +reboot RCM, poweroff, enter U-Boot console and update bootloader (check +the next chapter). + +Flashing ``repart-block.bin`` eliminates vendor restrictions on eMMC and allows +the user to use/partition it in any way the user desires. + +Self Upgrading +-------------- + +Place your ``u-boot-dtb-tegra.bin`` on the first partition of the USB. Enter +bootmenu, choose update bootloader option with Enter and U-Boot should update +itself. Once the process is completed, U-Boot will ask to press any button to reboot. diff --git a/include/configs/ouya.h b/include/configs/ouya.h new file mode 100644 index 00000000000..cc86c1002e3 --- /dev/null +++ b/include/configs/ouya.h @@ -0,0 +1,23 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * (C) Copyright 2010,2012 + * NVIDIA Corporation + * + * (C) Copyright 2025 + * Svyatoslav Ryhel + */ + +#ifndef __CONFIG_H +#define __CONFIG_H + +#include "tegra30-common.h" + +/* High-level configuration options */ +#define CFG_TEGRA_BOARD_STRING "Ouya Game Console" + +/* Board-specific serial config */ +#define CFG_SYS_NS16550_COM1 NV_PA_APB_UARTD_BASE + +#include "tegra-common-post.h" + +#endif /* __CONFIG_H */ diff --git a/include/env/nvidia/prod_upd.env b/include/env/nvidia/prod_upd.env index f4e381994be..6a457d1b75b 100644 --- a/include/env/nvidia/prod_upd.env +++ b/include/env/nvidia/prod_upd.env @@ -3,6 +3,7 @@ boot_block_size=0x1000 bootloader_file=u-boot-dtb-tegra.bin spi_size=0x400000 boot_dev=0 +boot_interface=mmc flash_uboot=echo Preparing RAM; mw ${kernel_addr_r} 0 ${boot_block_size_r}; @@ -11,9 +12,9 @@ flash_uboot=echo Preparing RAM; mmc dev 0 1; mmc read ${kernel_addr_r} 0 ${boot_block_size}; echo Reading bootloader; - if load mmc ${boot_dev}:1 ${ramdisk_addr_r} ${bootloader_file}; + if load ${boot_interface} ${boot_dev}:1 ${ramdisk_addr_r} ${bootloader_file}; then echo Calculating bootloader size; - size mmc ${boot_dev}:1 ${bootloader_file}; + size ${boot_interface} ${boot_dev}:1 ${bootloader_file}; ebtupdate ${kernel_addr_r} ${ramdisk_addr_r} ${filesize}; echo Writing bootloader to eMMC; mmc dev 0 1;