Please pull u-boot-tegra staging
Dear Tom, The following changes since commit 1dd659fd626204bb6a6b4f330c27b11a7823bbb0: Merge tag 'video-20240421' of https://source.denx.de/u-boot/custodians/u-boot-video (2024-04-21 08:54:20 -0600) are available in the Git repository at: https://source.denx.de/u-boot/custodians/u-boot-tegra.git staging for you to fetch changes up to 6898cc823413ff01661e7db74ad764da58b682d9: board: tegra30: switch to button cmd (2024-04-22 12:17:21 +0300) Jonas Schwöbel (2): board: asus: lg_x3: endeavoru: remove CONFIG_SYS_L2CACHE_OFF ARM: tegra: Enable UART-E for T20 and T30 Svyatoslav Ryhel (12): ARM: dts: paz00: remove display-timings node ARM: tegra: move to standard boot board: tegra30: switch to standard boot board: asus: tf600t: configure SPI pinmux board: asus: tf600t: adjust LV pinmux board: asus: transformer-t30: set the correct pinmux lock and io-reset board: asus: tf600t: enable TEGRA20_SLINK only for TF600T board: asus: transformer-t30: enable I2C_MUX only for TF700T board: asus: tf700t: bind tc358768 bridge and panel ARM: tegra: grouper: bind Hall sensor ARM: tegra: transformer-t30: bind Hall sensor board: tegra30: switch to button cmd arch/arm/Kconfig | 2 +- arch/arm/dts/tegra20-paz00.dts| 16 arch/arm/dts/tegra30-asus-grouper-common.dtsi | 6 ++ arch/arm/dts/tegra30-asus-p1801-t.dts | 28 +++--- arch/arm/dts/tegra30-asus-tf600t.dts | 101 +++-- arch/arm/dts/tegra30-asus-tf700t.dts | 102 +- arch/arm/dts/tegra30-asus-transformer.dtsi| 36 +--- arch/arm/mach-tegra/Kconfig | 4 + board/asus/transformer-t30/configs/p1801-t.config | 1 + board/asus/transformer-t30/configs/tf201.config | 1 + board/asus/transformer-t30/configs/tf300t.config | 1 + board/asus/transformer-t30/configs/tf300tg.config | 1 + board/asus/transformer-t30/configs/tf300tl.config | 1 + board/asus/transformer-t30/configs/tf600t.config | 2 + board/asus/transformer-t30/configs/tf700t.config | 2 + configs/endeavoru_defconfig | 4 +- configs/grouper_common_defconfig | 4 +- configs/paz00_defconfig | 1 + configs/transformer_t30_defconfig | 5 +- configs/x3_t30_defconfig | 4 +- include/configs/endeavoru.h | 3 +- include/configs/grouper.h | 5 +- include/configs/tegra-common-post.h | 30 +-- include/configs/transformer-common.h | 12 +-- include/configs/x3-t30.h | 3 +- 25 files changed, 255 insertions(+), 120 deletions(-) Branch contains minor internal improvemets for endeavoru, lg_x3, grouper, transformers and paz00 as well as migration to standard boot. All commits passed U-Boot checks and buildman for tegra. Thanks, Svyatoslav Ryhel.
Re: [PATCH v6 01/18] video: tegra20: dc: diverge DC per-SOC
пт, 19 квіт. 2024 р. о 19:26 Thierry Reding пише: > > On Tue Jan 23, 2024 at 6:16 PM CET, Svyatoslav Ryhel wrote: > [...] > > diff --git a/arch/arm/include/asm/arch-tegra114/display.h > > b/arch/arm/include/asm/arch-tegra114/display.h > > new file mode 100644 > > index 00..9411525799 > > --- /dev/null > > +++ b/arch/arm/include/asm/arch-tegra114/display.h > > @@ -0,0 +1,28 @@ > > +/* SPDX-License-Identifier: GPL-2.0+ */ > > +/* > > + * (C) Copyright 2010 > > + * NVIDIA Corporation > > + */ > > + > > +#ifndef __ASM_ARCH_TEGRA_DISPLAY_H > > +#define __ASM_ARCH_TEGRA_DISPLAY_H > > + > > +#include > > + > > +/* This holds information about a window which can be displayed */ > > +struct disp_ctl_win { > > + enum win_color_depth_id fmt;/* Color depth/format */ > > + unsigned intbpp;/* Bits per pixel */ > > + phys_addr_t phys_addr; /* Physical address in memory */ > > + unsigned intx; /* Horizontal address offset (bytes) > > */ > > + unsigned inty; /* Veritical address offset (bytes) */ > > + unsigned intw; /* Width of source window */ > > + unsigned inth; /* Height of source window */ > > + unsigned intstride; /* Number of bytes per line */ > > + unsigned intout_x; /* Left edge of output window (col) */ > > + unsigned intout_y; /* Top edge of output window (row) */ > > + unsigned intout_w; /* Width of output window in pixels */ > > + unsigned intout_h; /* Height of output window in pixels > > */ > > +}; > > + > > +#endif /*__ASM_ARCH_TEGRA_DISPLAY_H*/ > > One of the earlier patches in the series gets rid of this per-SoC header > file in favor of a common one. Did this end up here by mistake? It > doesn't seem to be used. > > > diff --git a/drivers/video/tegra20/tegra-dc.c > > b/drivers/video/tegra20/tegra-dc.c > > index f53ad46397..7605e77bc1 100644 > > --- a/drivers/video/tegra20/tegra-dc.c > > +++ b/drivers/video/tegra20/tegra-dc.c > > @@ -3,7 +3,6 @@ > > * Copyright (c) 2011 The Chromium OS Authors. > > */ > > > > -#include > > #include > > #include > > #include > > @@ -23,10 +22,15 @@ > > #include > > #include > > #include > > -#include > > > > DECLARE_GLOBAL_DATA_PTR; > > > > +/* Holder of Tegra per-SOC DC differences */ > > +struct tegra_dc_soc_info { > > + bool has_timer; > > + bool has_rgb; > > +}; > > + > > /* Information about the display controller */ > > struct tegra_lcd_priv { > > int width; /* width in pixels */ > > @@ -35,6 +39,7 @@ struct tegra_lcd_priv { > > struct display_timing timing; > > struct udevice *panel; > > struct dc_ctlr *dc; /* Display controller regmap */ > > + const struct tegra_dc_soc_info *soc; > > fdt_addr_t frame_buffer;/* Address of frame buffer */ > > unsigned pixel_clock; /* Pixel clock in Hz */ > > int dc_clk[2]; /* Contains clk and its parent */ > > @@ -43,8 +48,8 @@ struct tegra_lcd_priv { > > > > enum { > > /* Maximum LCD size we support */ > > - LCD_MAX_WIDTH = 1920, > > - LCD_MAX_HEIGHT = 1200, > > + LCD_MAX_WIDTH = 2560, > > + LCD_MAX_HEIGHT = 1600, > > LCD_MAX_LOG2_BPP= VIDEO_BPP16, > > }; > > > > @@ -110,9 +115,9 @@ static void update_window(struct tegra_lcd_priv *priv, > > writel(val, >cmd.state_ctrl); > > } > > > > -static int update_display_mode(struct dc_disp_reg *disp, > > -struct tegra_lcd_priv *priv) > > +static int update_display_mode(struct tegra_lcd_priv *priv) > > { > > + struct dc_disp_reg *disp = >dc->disp; > > struct display_timing *dt = >timing; > > unsigned long val; > > unsigned long rate; > > @@ -128,14 +133,16 @@ static int update_display_mode(struct dc_disp_reg > > *disp, > > >front_porch); > > writel(dt->hactive.typ | (dt->vactive.typ << 16), >disp_active); > > > > - val = DE_SELECT_ACTIVE << DE_SELECT_SHIFT; > > - val |= DE_CONTROL_NORMAL << DE_CONTROL_SHIFT; > > - writel(val, &g
Re: [PATCH v6 04/18] video: tegra20: dc: pass DC id to internal devices
пт, 19 квіт. 2024 р. о 19:58 Thierry Reding пише: > > On Fri Apr 19, 2024 at 6:44 PM CEST, Svyatoslav Ryhel wrote: > > пт, 19 квіт. 2024 р. о 19:38 Thierry Reding пише: > > > > > > On Tue Jan 23, 2024 at 6:16 PM CET, Svyatoslav Ryhel wrote: > > > > Tegra SoC has 2 independent display controllers called DC_A and > > > > DC_B, they are handled differently by internal video devices like > > > > DSI and HDMI controllers so it is important for last to know > > > > which display controller is used to properly set up registers. > > > > To achieve this, a pipe field was added to pdata to pass display > > > > controller id to internal Tegra SoC devices. > > > > > > > > Tested-by: Agneli # Toshiba AC100 T20 > > > > Tested-by: Robert Eckelmann # ASUS TF101 > > > > Tested-by: Andreas Westman Dorcsak # ASUS Grouper > > > > E1565 > > > > Tested-by: Ion Agorria # HTC One X > > > > Tested-by: Svyatoslav Ryhel # Nvidia Tegratab T114 > > > > Signed-off-by: Svyatoslav Ryhel > > > > --- > > > > drivers/video/tegra20/tegra-dc.c | 6 ++ > > > > drivers/video/tegra20/tegra-dc.h | 3 +++ > > > > 2 files changed, 9 insertions(+) > > > > > > > > diff --git a/drivers/video/tegra20/tegra-dc.c > > > > b/drivers/video/tegra20/tegra-dc.c > > > > index 5d8874f323..0e94e665ef 100644 > > > > --- a/drivers/video/tegra20/tegra-dc.c > > > > +++ b/drivers/video/tegra20/tegra-dc.c > > > > @@ -45,6 +45,7 @@ struct tegra_lcd_priv { > > > > unsigned pixel_clock; /* Pixel clock in Hz */ > > > > int dc_clk[2]; /* Contains clk and its parent */ > > > > bool rotation; /* 180 degree panel turn */ > > > > + bool pipe; /* DC controller: 0 for A, 1 for > > > > B */ > > > > > > Bool is a poor choice, even if there's only two of them. This is a > > > proper index, so it should be some sort of integer. > > > > > > Also, the device tree bindings for the display controller specify a > > > "nvidia,head" property that can be used to identify these. If you add > > > that to the U-Boot DT you can avoid looking up by name to map this > > > value. > > > > > > > Thanks for pointing to this property. May we apply this patch set as is > > since it is well tested and confirmed to work and I will prepare a follow > > up patches to adjust device tree relations? Would what be ok? > > Well, there's a few other things that I think should be addressed, but > if you'd like to keep this one patch as-is and clean this up later, I > guess that's fine. May you send me a list of stuff which you think may be improved? I would gladly adjust whatever I can in follow up. > Thierry
Re: [PATCH v6 06/18] video: tegra20: dc: add reset support
пт, 19 квіт. 2024 р. о 19:46 Thierry Reding пише: > > On Fri Apr 19, 2024 at 6:37 PM CEST, Svyatoslav Ryhel wrote: > > пт, 19 квіт. 2024 р. о 19:05 Thierry Reding пише: > > > > > > On Tue Jan 23, 2024 at 6:16 PM CET, Svyatoslav Ryhel wrote: > > > > Implement reset use to discard any changes which could have been > > > > applied to DC before and can interfere with current configuration. > > > > > > > > Tested-by: Agneli # Toshiba AC100 T20 > > > > Tested-by: Robert Eckelmann # ASUS TF101 > > > > Tested-by: Andreas Westman Dorcsak # ASUS Grouper > > > > E1565 > > > > Tested-by: Ion Agorria # HTC One X > > > > Tested-by: Svyatoslav Ryhel # Nvidia Tegratab T114 > > > > Signed-off-by: Svyatoslav Ryhel > > > > --- > > > > drivers/video/tegra20/tegra-dc.c | 17 + > > > > 1 file changed, 17 insertions(+) > > > > > > > > diff --git a/drivers/video/tegra20/tegra-dc.c > > > > b/drivers/video/tegra20/tegra-dc.c > > > > index 56a23b3c97..35abb6fe46 100644 > > > > --- a/drivers/video/tegra20/tegra-dc.c > > > > +++ b/drivers/video/tegra20/tegra-dc.c > > > > @@ -10,7 +10,9 @@ > > > > #include > > > > #include > > > > #include > > > > +#include > > > > #include > > > > +#include > > > > #include > > > > #include > > > > #include > > > > @@ -342,6 +344,7 @@ static int tegra_lcd_probe(struct udevice *dev) > > > > struct video_uc_plat *plat = dev_get_uclass_plat(dev); > > > > struct video_priv *uc_priv = dev_get_uclass_priv(dev); > > > > struct tegra_lcd_priv *priv = dev_get_priv(dev); > > > > + struct reset_ctl reset_ctl; > > > > int ret; > > > > > > > > /* Initialize the Tegra display controller */ > > > > @@ -349,6 +352,20 @@ static int tegra_lcd_probe(struct udevice *dev) > > > > funcmux_select(PERIPH_ID_DISP1, FUNCMUX_DEFAULT); > > > > #endif > > > > > > > > + ret = reset_get_by_name(dev, "dc", _ctl); > > > > + if (ret) { > > > > + log_err("reset_get_by_name() failed: %d\n", ret); > > > > + return ret; > > > > + } > > > > + > > > > + clock_disable(priv->dc_clk[0]); > > > > + > > > > + /* Reset everything set before */ > > > > + reset_assert(_ctl); > > > > + mdelay(4); > > > > + reset_deassert(_ctl); > > > > + mdelay(4); > > > > > > Are you sure this works as intended? It's been a long time since I > > > worked on this, but I seem to recall that most of these resets are > > > actually synchronous, so in order for them to do what they're supposed > > > to the clock needs to be kept running. > > > > > > The Linux driver certainly does this differently. > > > > You have point, but I have tried to mostly adapt Linux tegra dc driver, > > which has same logic in probe. Maybe I have not understood it properly. > > Testing on T20, T30 and T114 passed without issues so far. > > Maybe look again. What it does is (basically): > > clock_enable(); > mdelay(4); > reset_assert(); > mdelay(4); > clock_disable(); > > That should ensure that it's completely reset at that point. Now before > any subsequent register accesses happen it will do this: > > clock_enable(); > reset_deassert(); > > to take it out of reset again. Perhaps that's something you want to keep > doing in probe() in U-Boot. In that case maybe you want something like > this instead: > > clock_enable(); > mdelay(4); > reset_assert(); > mdelay(4); > reset_deassert(); > You are correct. I assume This patch may be dropped entirely. Thanks. > Thierry
Re: [PATCH v6 04/18] video: tegra20: dc: pass DC id to internal devices
пт, 19 квіт. 2024 р. о 19:38 Thierry Reding пише: > > On Tue Jan 23, 2024 at 6:16 PM CET, Svyatoslav Ryhel wrote: > > Tegra SoC has 2 independent display controllers called DC_A and > > DC_B, they are handled differently by internal video devices like > > DSI and HDMI controllers so it is important for last to know > > which display controller is used to properly set up registers. > > To achieve this, a pipe field was added to pdata to pass display > > controller id to internal Tegra SoC devices. > > > > Tested-by: Agneli # Toshiba AC100 T20 > > Tested-by: Robert Eckelmann # ASUS TF101 > > Tested-by: Andreas Westman Dorcsak # ASUS Grouper E1565 > > Tested-by: Ion Agorria # HTC One X > > Tested-by: Svyatoslav Ryhel # Nvidia Tegratab T114 > > Signed-off-by: Svyatoslav Ryhel > > --- > > drivers/video/tegra20/tegra-dc.c | 6 ++ > > drivers/video/tegra20/tegra-dc.h | 3 +++ > > 2 files changed, 9 insertions(+) > > > > diff --git a/drivers/video/tegra20/tegra-dc.c > > b/drivers/video/tegra20/tegra-dc.c > > index 5d8874f323..0e94e665ef 100644 > > --- a/drivers/video/tegra20/tegra-dc.c > > +++ b/drivers/video/tegra20/tegra-dc.c > > @@ -45,6 +45,7 @@ struct tegra_lcd_priv { > > unsigned pixel_clock; /* Pixel clock in Hz */ > > int dc_clk[2]; /* Contains clk and its parent */ > > bool rotation; /* 180 degree panel turn */ > > + bool pipe; /* DC controller: 0 for A, 1 for B */ > > Bool is a poor choice, even if there's only two of them. This is a > proper index, so it should be some sort of integer. > > Also, the device tree bindings for the display controller specify a > "nvidia,head" property that can be used to identify these. If you add > that to the U-Boot DT you can avoid looking up by name to map this > value. > Thanks for pointing to this property. May we apply this patch set as is since it is well tested and confirmed to work and I will prepare a follow up patches to adjust device tree relations? Would what be ok? > Thierry
Re: [PATCH v6 06/18] video: tegra20: dc: add reset support
пт, 19 квіт. 2024 р. о 19:05 Thierry Reding пише: > > On Tue Jan 23, 2024 at 6:16 PM CET, Svyatoslav Ryhel wrote: > > Implement reset use to discard any changes which could have been > > applied to DC before and can interfere with current configuration. > > > > Tested-by: Agneli # Toshiba AC100 T20 > > Tested-by: Robert Eckelmann # ASUS TF101 > > Tested-by: Andreas Westman Dorcsak # ASUS Grouper E1565 > > Tested-by: Ion Agorria # HTC One X > > Tested-by: Svyatoslav Ryhel # Nvidia Tegratab T114 > > Signed-off-by: Svyatoslav Ryhel > > --- > > drivers/video/tegra20/tegra-dc.c | 17 + > > 1 file changed, 17 insertions(+) > > > > diff --git a/drivers/video/tegra20/tegra-dc.c > > b/drivers/video/tegra20/tegra-dc.c > > index 56a23b3c97..35abb6fe46 100644 > > --- a/drivers/video/tegra20/tegra-dc.c > > +++ b/drivers/video/tegra20/tegra-dc.c > > @@ -10,7 +10,9 @@ > > #include > > #include > > #include > > +#include > > #include > > +#include > > #include > > #include > > #include > > @@ -342,6 +344,7 @@ static int tegra_lcd_probe(struct udevice *dev) > > struct video_uc_plat *plat = dev_get_uclass_plat(dev); > > struct video_priv *uc_priv = dev_get_uclass_priv(dev); > > struct tegra_lcd_priv *priv = dev_get_priv(dev); > > + struct reset_ctl reset_ctl; > > int ret; > > > > /* Initialize the Tegra display controller */ > > @@ -349,6 +352,20 @@ static int tegra_lcd_probe(struct udevice *dev) > > funcmux_select(PERIPH_ID_DISP1, FUNCMUX_DEFAULT); > > #endif > > > > + ret = reset_get_by_name(dev, "dc", _ctl); > > + if (ret) { > > + log_err("reset_get_by_name() failed: %d\n", ret); > > + return ret; > > + } > > + > > + clock_disable(priv->dc_clk[0]); > > + > > + /* Reset everything set before */ > > + reset_assert(_ctl); > > + mdelay(4); > > + reset_deassert(_ctl); > > + mdelay(4); > > Are you sure this works as intended? It's been a long time since I > worked on this, but I seem to recall that most of these resets are > actually synchronous, so in order for them to do what they're supposed > to the clock needs to be kept running. > > The Linux driver certainly does this differently. You have point, but I have tried to mostly adapt Linux tegra dc driver, which has same logic in probe. Maybe I have not understood it properly. Testing on T20, T30 and T114 passed without issues so far. > Thierry
Re: [PATCH v6 00/18] Add T114 video support
Hello Tom! This patch set is hanging in patchwork for 3 month without any comments. If no one has anything to say, may you pick it into master? Best regards, Svyatoslav R. вт, 23 січ. 2024 р. о 19:17 Svyatoslav Ryhel пише: > > T114 is not that different from T30 and all T30 drivers will work > on T114 as well with some adjustments. > > Patches propose general improvements for existing Tegra DC and DSI > drivers as well Tegra 114 video support (experimentl). > > Commits pass buildman for tegra. > > --- > Changes from v5: > - backlight enable moved to the last step of setup for DSI > - parameterized V- and H-sync polarities > - added framebuffer clearing on probe to avoid glitches > - backlight enable moved after DC is fully configured > - fixed printing framebuffer pointer instead of address > - moved scdiv calculation to tegra DSI if it is used > > Changes from v4: > - fixed typo in max rate to be divided (400KHz > 400MHz) > > Changes from v3: > - fixed the clock divider calculation if PLLD/D2 is used > - removed unnecessary pre-configuration > - set correct video FIFO depth for DSI > > Changes from v2: > - fixed image distortion on devices with 180deg rotation > > Changes from v1: > - reworked patchset entirely > - diverged DC configuration per-SOC > - consolidated dc headers from different SOC gen > - initial support of DC detection (tegra has 2 DC) > - added PLLD2 support, resets and powergating > - added T114+ MIPI calibration > - added DSI detection (tegra has 2 DSI) and resets > --- > > Jonas Schwöbel (6): > video: tegra20: dc: fix printing of framebuffer address > video: tegra20: dc: enable backlight after DC is configured > video: tegra20: dc: clean framebuffer memory block > video: tegra20: dsi: remove pre-configuration > video: tegra20: dsi: set correct fifo depth > video: tegra20: dsi: use set_backlight for backlight only > > Svyatoslav Ryhel (12): > video: tegra20: dc: diverge DC per-SOC > video: tegra20: dc: fix image shift on rotated panels > video: tegra20: consolidate DC header > video: tegra20: dc: pass DC id to internal devices > video: tegra20: dc: add PLLD2 parent support > video: tegra20: dc: add reset support > video: tegra20: dc: add powergate > video: tegra20: dc: configure behavior if PLLD/D2 is used > video: tegra20: dc: parameterize V- and H-sync polarities > video: tegra20: add MIPI calibration driver > video: tegra20: dsi: add T114 support > video: tegra20: dsi: add reset support > > arch/arm/dts/tegra114-u-boot.dtsi | 13 + > arch/arm/dts/tegra114.dtsi| 4 +- > arch/arm/dts/tegra30-u-boot.dtsi | 4 + > arch/arm/dts/tegra30.dtsi | 2 +- > arch/arm/include/asm/arch-tegra/dc.h | 13 +- > arch/arm/include/asm/arch-tegra114/pwm.h | 13 + > arch/arm/include/asm/arch-tegra20/display.h | 28 -- > arch/arm/include/asm/arch-tegra30/display.h | 28 -- > drivers/video/tegra20/Makefile| 2 +- > drivers/video/tegra20/tegra-dc.c | 239 +- > drivers/video/tegra20/tegra-dc.h | 45 > drivers/video/tegra20/tegra-dsi.c | 122 - > .../video/tegra20/tegra-dsi.h | 24 +- > drivers/video/tegra20/tegra-mipi.c| 188 ++ > drivers/video/tegra20/tegra-pwm-backlight.c | 3 +- > 15 files changed, 583 insertions(+), 145 deletions(-) > create mode 100644 arch/arm/include/asm/arch-tegra114/pwm.h > delete mode 100644 arch/arm/include/asm/arch-tegra20/display.h > delete mode 100644 arch/arm/include/asm/arch-tegra30/display.h > create mode 100644 drivers/video/tegra20/tegra-dc.h > rename arch/arm/include/asm/arch-tegra30/dsi.h => > drivers/video/tegra20/tegra-dsi.h (90%) > create mode 100644 drivers/video/tegra20/tegra-mipi.c > > -- > 2.40.1 >
Re: [PATCH v2 0/7] Tegra panel improvements
Hello Tom! This patch set is hanging in patchwork for 3 month without any comments. If no one has anything to say, may you pick it into master? Best regards, Svyatoslav R. ср, 31 січ. 2024 р. о 08:57 Svyatoslav Ryhel пише: > > The current patch set improves the logic of existing panels and > bridge used by Tegra 3 devices and brings support for additional > DSI panels used by Tegra 4 devices. > > New and existing drivers are fully reusable, contain no device > specific parts, and are written according to existing datasheets. > > --- > Changes from v1: > - improved ssd2825 code style > - added TC358768 RGB to DSI bridge bringup commit (used by TF700T) > - added Parade DP501 transmitter bringup (used by Lenovo Ideapad Yoga 11) > --- > > Anton Bambura (1): > video: panel: add Samsung LTL106HL02 MIPI DSI panel driver > > Jonas Schwöbel (1): > video: bridge: add basic support for the Parade DP501 transmitter > > Svyatoslav Ryhel (5): > video: panel: add LG LG070WX3 MIPI DSI panel driver > video: bridge: add Toshiba TC358768 RGB to DSI bridge support > video: endeavoru-panel: shift the init sequence by one step earlier > video: bridge: ssd2825: shift the init sequence by one step earlier > video: renesas: shift the init sequence by one step earlier > > drivers/video/Kconfig | 17 + > drivers/video/Makefile | 2 + > drivers/video/bridge/Kconfig | 19 + > drivers/video/bridge/Makefile | 2 + > drivers/video/bridge/dp501.c | 579 + > drivers/video/bridge/ssd2825.c | 86 +-- > drivers/video/bridge/tc358768.c| 985 + > drivers/video/endeavoru-panel.c| 128 ++-- > drivers/video/lg-ld070wx3.c| 186 ++ > drivers/video/renesas-r61307.c | 93 +-- > drivers/video/renesas-r69328.c | 81 +-- > drivers/video/samsung-ltl106hl02.c | 157 + > 12 files changed, 2155 insertions(+), 180 deletions(-) > create mode 100644 drivers/video/bridge/dp501.c > create mode 100644 drivers/video/bridge/tc358768.c > create mode 100644 drivers/video/lg-ld070wx3.c > create mode 100644 drivers/video/samsung-ltl106hl02.c > > -- > 2.40.1 >
Re: [PATCH v2 0/1] Fix booting kernels with ATAGS and extlinux
чт, 25 січ. 2024 р. о 22:17 Svyatoslav Ryhel пише: > > Currently, if boot with extlinux.conf and do not set the fdt > U-Boot will provide its own device tree. This behavior is > beneficial if the U-Boot device tree is in sync with Linux, > but it totally halts the booting of pre-dtb kernels (3.4 for > example) since it uses ATAGs. To fix this, pass `-` in the > fdt extlinux field as a signal that no tree should be used. > > Tested with 3.4 legacy kernel and mainline 6.7 kernel on > P895 (lg_x3 board). > > --- > Changes form v1 > - Added CONFIG guards > - Clarified documentation > --- > > Svyatoslav Ryhel (1): > boot: pxe_utils: skip fdt setup in case legacy kernel is booted > > boot/pxe_utils.c | 27 ++- > doc/develop/distro.rst | 6 ++ > 2 files changed, 28 insertions(+), 5 deletions(-) > > -- > 2.40.1 > Hello, Tom! A month passed since v2 was pushed without any actions, should I re-send it or maybe some adjustments are needed?
Re: [PATCH v1 5/7] toradex: common: Add sysinfo driver
вт, 20 лют. 2024 р. о 20:29 Francesco Dolcini пише: > > From: Emanuele Ghidoli > > This commit introduces support for the Toradex sysinfo driver in U-Boot, > which uses information from Toradex config block to print correct > board model. > In case the Toradex config block is not present sysinfo prints the model > of the board provided by device tree removing per board specific prints. > > Signed-off-by: Emanuele Ghidoli > Signed-off-by: Francesco Dolcini > --- > arch/arm/dts/fsl-imx8qm-apalis-u-boot.dtsi| 6 +++ > arch/arm/dts/fsl-imx8qxp-colibri-u-boot.dtsi | 6 +++ > .../dts/imx6dl-colibri-eval-v3-u-boot.dtsi| 4 ++ > arch/arm/dts/imx6q-apalis-eval-u-boot.dtsi| 4 ++ > .../dts/imx6ull-colibri-eval-v3-u-boot.dtsi | 4 ++ > .../arm/dts/imx7d-colibri-eval-v3-u-boot.dtsi | 4 ++ > .../dts/imx8mm-verdin-wifi-dev-u-boot.dtsi| 4 ++ > .../dts/imx8mp-verdin-wifi-dev-u-boot.dtsi| 4 ++ > .../dts/k3-am625-verdin-wifi-dev-u-boot.dtsi | 4 ++ > arch/arm/dts/tegra124-apalis-u-boot.dtsi | 12 + > arch/arm/dts/tegra20-colibri-u-boot.dtsi | 12 + > arch/arm/dts/tegra30-apalis-u-boot.dtsi | 12 + > arch/arm/dts/tegra30-colibri-u-boot.dtsi | 12 + > .../arm/dts/vf610-colibri-eval-v3-u-boot.dtsi | 4 ++ > board/toradex/common/Kconfig | 1 + > board/toradex/common/tdx-common.c | 50 --- > 16 files changed, 136 insertions(+), 7 deletions(-) > create mode 100644 arch/arm/dts/tegra124-apalis-u-boot.dtsi > create mode 100644 arch/arm/dts/tegra20-colibri-u-boot.dtsi > create mode 100644 arch/arm/dts/tegra30-apalis-u-boot.dtsi > create mode 100644 arch/arm/dts/tegra30-colibri-u-boot.dtsi > Greetings! Thank you for contribution but may you at split patches according to SoC vendor at least? For imx, tegra and ti since it would be hard to both review and pick them to correct custodian trees. > diff --git a/arch/arm/dts/fsl-imx8qm-apalis-u-boot.dtsi > b/arch/arm/dts/fsl-imx8qm-apalis-u-boot.dtsi > index c54a59e89c5d..d73be74d2112 100644 > --- a/arch/arm/dts/fsl-imx8qm-apalis-u-boot.dtsi > +++ b/arch/arm/dts/fsl-imx8qm-apalis-u-boot.dtsi > @@ -3,6 +3,12 @@ > * Copyright 2019 Toradex AG > */ > > +/ { > + sysinfo { > + compatible = "toradex,sysinfo"; > + }; > +}; > + > { > bootph-some-ram; > }; > diff --git a/arch/arm/dts/fsl-imx8qxp-colibri-u-boot.dtsi > b/arch/arm/dts/fsl-imx8qxp-colibri-u-boot.dtsi > index 6ab6b1f9ee69..60c4cd6fc01f 100644 > --- a/arch/arm/dts/fsl-imx8qxp-colibri-u-boot.dtsi > +++ b/arch/arm/dts/fsl-imx8qxp-colibri-u-boot.dtsi > @@ -3,6 +3,12 @@ > * Copyright 2019 Toradex AG > */ > > +/ { > + sysinfo { > + compatible = "toradex,sysinfo"; > + }; > +}; > + > &{/imx8qx-pm} { > > bootph-some-ram; > diff --git a/arch/arm/dts/imx6dl-colibri-eval-v3-u-boot.dtsi > b/arch/arm/dts/imx6dl-colibri-eval-v3-u-boot.dtsi > index 0eea4d1862ae..5a91d0aca204 100644 > --- a/arch/arm/dts/imx6dl-colibri-eval-v3-u-boot.dtsi > +++ b/arch/arm/dts/imx6dl-colibri-eval-v3-u-boot.dtsi > @@ -16,6 +16,10 @@ > mmc0 = > mmc1 = > }; > + > + sysinfo { > + compatible = "toradex,sysinfo"; > + }; > }; > > { > diff --git a/arch/arm/dts/imx6q-apalis-eval-u-boot.dtsi > b/arch/arm/dts/imx6q-apalis-eval-u-boot.dtsi > index 3c6e503d043b..59412635420a 100644 > --- a/arch/arm/dts/imx6q-apalis-eval-u-boot.dtsi > +++ b/arch/arm/dts/imx6q-apalis-eval-u-boot.dtsi > @@ -19,6 +19,10 @@ > mmc1 = > mmc2 = > }; > + > + sysinfo { > + compatible = "toradex,sysinfo"; > + }; > }; > > { > diff --git a/arch/arm/dts/imx6ull-colibri-eval-v3-u-boot.dtsi > b/arch/arm/dts/imx6ull-colibri-eval-v3-u-boot.dtsi > index 6823b42d4514..731814216e1f 100644 > --- a/arch/arm/dts/imx6ull-colibri-eval-v3-u-boot.dtsi > +++ b/arch/arm/dts/imx6ull-colibri-eval-v3-u-boot.dtsi > @@ -9,6 +9,10 @@ > usb0 = /* required for ums */ > display0 = > }; > + > + sysinfo { > + compatible = "toradex,sysinfo"; > + }; > }; > > _uart1 { > diff --git a/arch/arm/dts/imx7d-colibri-eval-v3-u-boot.dtsi > b/arch/arm/dts/imx7d-colibri-eval-v3-u-boot.dtsi > index b2c12a413daf..68142769d360 100644 > --- a/arch/arm/dts/imx7d-colibri-eval-v3-u-boot.dtsi > +++ b/arch/arm/dts/imx7d-colibri-eval-v3-u-boot.dtsi > @@ -11,6 +11,10 @@ > mmc0 = > mmc1 = > }; > + > + sysinfo { > + compatible = "toradex,sysinfo"; > + }; > }; > > { > diff --git a/arch/arm/dts/imx8mm-verdin-wifi-dev-u-boot.dtsi > b/arch/arm/dts/imx8mm-verdin-wifi-dev-u-boot.dtsi > index 515f195ab759..38db56059d69 100644 > --- a/arch/arm/dts/imx8mm-verdin-wifi-dev-u-boot.dtsi > +++ b/arch/arm/dts/imx8mm-verdin-wifi-dev-u-boot.dtsi > @@ -12,6 +12,10 @@ > eeprom2 =
[PATCH v2 7/7] video: renesas: shift the init sequence by one step earlier
Shift all setup stages one step earlier to better fit the existing uclass. Signed-off-by: Svyatoslav Ryhel --- drivers/video/renesas-r61307.c | 93 +++--- drivers/video/renesas-r69328.c | 81 +++-- 2 files changed, 95 insertions(+), 79 deletions(-) diff --git a/drivers/video/renesas-r61307.c b/drivers/video/renesas-r61307.c index 426fdc6224..1eccaf6b1b 100644 --- a/drivers/video/renesas-r61307.c +++ b/drivers/video/renesas-r61307.c @@ -118,42 +118,6 @@ static struct display_timing default_timing = { }; static int renesas_r61307_enable_backlight(struct udevice *dev) -{ - struct renesas_r61307_priv *priv = dev_get_priv(dev); - int ret; - - ret = regulator_set_enable_if_allowed(priv->vcc, 1); - if (ret) { - log_err("enabling vcc-supply failed (%d)\n", ret); - return ret; - } - mdelay(5); - - ret = regulator_set_enable_if_allowed(priv->iovcc, 1); - if (ret) { - log_err("enabling iovcc-supply failed (%d)\n", ret); - return ret; - } - - ret = dm_gpio_set_value(>reset_gpio, 0); - if (ret) { - log_err("changing reset-gpio failed (%d)\n", ret); - return ret; - } - mdelay(5); - - ret = dm_gpio_set_value(>reset_gpio, 1); - if (ret) { - log_err("changing reset-gpio failed (%d)\n", ret); - return ret; - } - - mdelay(5); - - return 0; -} - -static int renesas_r61307_set_backlight(struct udevice *dev, int percent) { struct renesas_r61307_priv *priv = dev_get_priv(dev); struct mipi_dsi_panel_plat *plat = dev_get_plat(dev); @@ -205,18 +169,23 @@ static int renesas_r61307_set_backlight(struct udevice *dev, int percent) log_err("failed to set display on: %d\n", ret); return ret; } - mdelay(50); + return 0; +} + +static int renesas_r61307_set_backlight(struct udevice *dev, int percent) +{ + struct renesas_r61307_priv *priv = dev_get_priv(dev); + int ret; + ret = backlight_enable(priv->backlight); if (ret) return ret; - ret = backlight_set_brightness(priv->backlight, percent); - if (ret) - return ret; + mdelay(5); - return 0; + return backlight_set_brightness(priv->backlight, percent); } static int renesas_r61307_timings(struct udevice *dev, @@ -266,6 +235,46 @@ static int renesas_r61307_of_to_plat(struct udevice *dev) return 0; } +static int renesas_r61307_hw_init(struct udevice *dev) +{ + struct renesas_r61307_priv *priv = dev_get_priv(dev); + int ret; + + ret = regulator_set_enable_if_allowed(priv->vcc, 1); + if (ret) { + log_debug("%s: enabling vcc-supply failed (%d)\n", + __func__, ret); + return ret; + } + mdelay(5); + + ret = regulator_set_enable_if_allowed(priv->iovcc, 1); + if (ret) { + log_debug("%s: enabling iovcc-supply failed (%d)\n", + __func__, ret); + return ret; + } + + ret = dm_gpio_set_value(>reset_gpio, 0); + if (ret) { + log_debug("%s: changing reset-gpio failed (%d)\n", + __func__, ret); + return ret; + } + mdelay(5); + + ret = dm_gpio_set_value(>reset_gpio, 1); + if (ret) { + log_debug("%s: changing reset-gpio failed (%d)\n", + __func__, ret); + return ret; + } + + mdelay(5); + + return 0; +} + static int renesas_r61307_probe(struct udevice *dev) { struct mipi_dsi_panel_plat *plat = dev_get_plat(dev); @@ -275,7 +284,7 @@ static int renesas_r61307_probe(struct udevice *dev) plat->format = MIPI_DSI_FMT_RGB888; plat->mode_flags = MIPI_DSI_MODE_VIDEO; - return 0; + return renesas_r61307_hw_init(dev); } static const struct panel_ops renesas_r61307_ops = { diff --git a/drivers/video/renesas-r69328.c b/drivers/video/renesas-r69328.c index d2f7169468..ecf89ec021 100644 --- a/drivers/video/renesas-r69328.c +++ b/drivers/video/renesas-r69328.c @@ -65,37 +65,6 @@ static struct display_timing default_timing = { static int renesas_r69328_enable_backlight(struct udevice *dev) { - struct renesas_r69328_priv *priv = dev_get_priv(dev); - int ret; - - ret = dm_gpio_set_value(>enable_gpio, 1); - if (ret) { - log_err("error changing enable-gpios (%d)\n", ret); - return ret; - } - mdelay(5); - - ret = dm_gpio_set_value(>reset_gpio, 0); - if (ret) { - log_err("error changing
[PATCH v2 6/7] video: bridge: ssd2825: shift the init sequence by one step earlier
Shift all setup stages one step earlier to better fit the existing uclass. Signed-off-by: Svyatoslav Ryhel --- drivers/video/bridge/ssd2825.c | 86 ++ 1 file changed, 45 insertions(+), 41 deletions(-) diff --git a/drivers/video/bridge/ssd2825.c b/drivers/video/bridge/ssd2825.c index cea20dcffa..f0ef3dafb9 100644 --- a/drivers/video/bridge/ssd2825.c +++ b/drivers/video/bridge/ssd2825.c @@ -349,39 +349,6 @@ static int ssd2825_bridge_enable_panel(struct udevice *dev) struct ssd2825_bridge_priv *priv = dev_get_priv(dev); struct mipi_dsi_device *device = >device; struct display_timing *dt = >timing; - int ret; - - ret = clk_prepare_enable(priv->tx_clk); - if (ret) { - log_err("error enabling tx_clk (%d)\n", ret); - return ret; - } - - ret = dm_gpio_set_value(>power_gpio, 1); - if (ret) { - log_err("error changing power-gpios (%d)\n", ret); - return ret; - } - mdelay(10); - - ret = dm_gpio_set_value(>reset_gpio, 0); - if (ret) { - log_err("error changing reset-gpios (%d)\n", ret); - return ret; - } - mdelay(10); - - ret = dm_gpio_set_value(>reset_gpio, 1); - if (ret) { - log_err("error changing reset-gpios (%d)\n", ret); - return ret; - } - mdelay(10); - - /* Perform panel HW setup */ - ret = panel_enable_backlight(priv->panel); - if (ret) - return ret; /* Perform SW reset */ ssd2825_write_register(dev, SSD2825_OPERATION_CTRL_REG, 0x0100); @@ -417,17 +384,15 @@ static int ssd2825_bridge_enable_panel(struct udevice *dev) SSD2825_CONF_REG_ECD | SSD2825_CONF_REG_EOT); ssd2825_write_register(dev, SSD2825_VC_CTRL_REG, 0x); - /* Set up SW panel configuration */ - ret = panel_set_backlight(priv->panel, BACKLIGHT_DEFAULT); - if (ret) - return ret; - - return 0; + /* Perform panel setup */ + return panel_enable_backlight(priv->panel); } static int ssd2825_bridge_set_panel(struct udevice *dev, int percent) { - return 0; + struct ssd2825_bridge_priv *priv = dev_get_priv(dev); + + return panel_set_backlight(priv->panel, percent); } static int ssd2825_bridge_panel_timings(struct udevice *dev, @@ -440,6 +405,45 @@ static int ssd2825_bridge_panel_timings(struct udevice *dev, return 0; } +static int ssd2825_bridge_hw_init(struct udevice *dev) +{ + struct ssd2825_bridge_priv *priv = dev_get_priv(dev); + int ret; + + ret = clk_prepare_enable(priv->tx_clk); + if (ret) { + log_debug("%s: error enabling tx_clk (%d)\n", + __func__, ret); + return ret; + } + + ret = dm_gpio_set_value(>power_gpio, 1); + if (ret) { + log_debug("%s: error changing power-gpios (%d)\n", + __func__, ret); + return ret; + } + mdelay(10); + + ret = dm_gpio_set_value(>reset_gpio, 0); + if (ret) { + log_debug("%s: error changing reset-gpios (%d)\n", + __func__, ret); + return ret; + } + mdelay(10); + + ret = dm_gpio_set_value(>reset_gpio, 1); + if (ret) { + log_debug("%s: error changing reset-gpios (%d)\n", + __func__, ret); + return ret; + } + mdelay(10); + + return 0; +} + static int ssd2825_bridge_probe(struct udevice *dev) { struct ssd2825_bridge_priv *priv = dev_get_priv(dev); @@ -496,7 +500,7 @@ static int ssd2825_bridge_probe(struct udevice *dev) return PTR_ERR(priv->tx_clk); } - return 0; + return ssd2825_bridge_hw_init(dev); } static const struct panel_ops ssd2825_bridge_ops = { -- 2.40.1
[PATCH v2 5/7] video: endeavoru-panel: shift the init sequence by one step earlier
Shift all setup stages one step earlier to better fit the existing uclass. Signed-off-by: Svyatoslav Ryhel --- drivers/video/endeavoru-panel.c | 128 +--- 1 file changed, 68 insertions(+), 60 deletions(-) diff --git a/drivers/video/endeavoru-panel.c b/drivers/video/endeavoru-panel.c index 79a272128b..1bff641434 100644 --- a/drivers/video/endeavoru-panel.c +++ b/drivers/video/endeavoru-panel.c @@ -57,61 +57,8 @@ static void dcs_write_one(struct mipi_dsi_device *dsi, u8 cmd, u8 data) static int endeavoru_panel_enable_backlight(struct udevice *dev) { - struct endeavoru_panel_priv *priv = dev_get_priv(dev); - int ret; - - ret = dm_gpio_set_value(>reset_gpio, 1); - if (ret) { - log_err("error changing reset-gpios (%d)\n", ret); - return ret; - } - mdelay(5); - - ret = regulator_set_enable_if_allowed(priv->vddio, 1); - if (ret) { - log_err("error enabling iovcc-supply (%d)\n", ret); - return ret; - } - mdelay(1); - - ret = regulator_set_enable_if_allowed(priv->vdd, 1); - if (ret) { - log_err("error enabling vcc-supply (%d)\n", ret); - return ret; - } - mdelay(20); - - ret = dm_gpio_set_value(>reset_gpio, 0); - if (ret) { - log_err("error changing reset-gpios (%d)\n", ret); - return ret; - } - mdelay(2); - - /* Reset panel */ - ret = dm_gpio_set_value(>reset_gpio, 1); - if (ret) { - log_err("error changing reset-gpios (%d)\n", ret); - return ret; - } - mdelay(1); - - ret = dm_gpio_set_value(>reset_gpio, 0); - if (ret) { - log_err("error changing reset-gpios (%d)\n", ret); - return ret; - } - mdelay(25); - - return 0; -} - -static int endeavoru_panel_set_backlight(struct udevice *dev, int percent) -{ - struct endeavoru_panel_priv *priv = dev_get_priv(dev); struct mipi_dsi_panel_plat *plat = dev_get_plat(dev); struct mipi_dsi_device *dsi = plat->device; - int ret; dcs_write_one(dsi, 0xc2, 0x08); @@ -160,18 +107,22 @@ static int endeavoru_panel_set_backlight(struct udevice *dev, int percent) dcs_write_one(dsi, 0x55, 0x80); dcs_write_one(dsi, 0x5e, 0x06); - ret = backlight_enable(priv->backlight); - if (ret) - return ret; - /* Set backlight */ dcs_write_one(dsi, 0x51, 0x96); - ret = backlight_set_brightness(priv->backlight, percent); + return 0; +} + +static int endeavoru_panel_set_backlight(struct udevice *dev, int percent) +{ + struct endeavoru_panel_priv *priv = dev_get_priv(dev); + int ret; + + ret = backlight_enable(priv->backlight); if (ret) return ret; - return 0; + return backlight_set_brightness(priv->backlight, percent); } static int endeavoru_panel_timings(struct udevice *dev, @@ -217,6 +168,63 @@ static int endeavoru_panel_of_to_plat(struct udevice *dev) return 0; } +static int endeavoru_panel_hw_init(struct udevice *dev) +{ + struct endeavoru_panel_priv *priv = dev_get_priv(dev); + int ret; + + ret = dm_gpio_set_value(>reset_gpio, 1); + if (ret) { + log_debug("%s: error changing reset-gpios (%d)\n", + __func__, ret); + return ret; + } + mdelay(5); + + ret = regulator_set_enable_if_allowed(priv->vddio, 1); + if (ret) { + log_debug("%s: error enabling iovcc-supply (%d)\n", + __func__, ret); + return ret; + } + mdelay(1); + + ret = regulator_set_enable_if_allowed(priv->vdd, 1); + if (ret) { + log_debug("%s: error enabling vcc-supply (%d)\n", + __func__, ret); + return ret; + } + mdelay(20); + + ret = dm_gpio_set_value(>reset_gpio, 0); + if (ret) { + log_debug("%s: error changing reset-gpios (%d)\n", + __func__, ret); + return ret; + } + mdelay(2); + + /* Reset panel */ + ret = dm_gpio_set_value(>reset_gpio, 1); + if (ret) { + log_debug("%s: error changing reset-gpios (%d)\n", + __func__, ret); + return ret; + } + mdelay(1); + + ret = dm_gpio_set_value(>reset_gpio, 0); + if (ret) { + log_debug("%s: error changing reset-gpios (%d)\n", + __func__, ret); + return ret; + } + mdelay(25); + + return 0; +} + static int ende
[PATCH v2 3/7] video: bridge: add Toshiba TC358768 RGB to DSI bridge support
Add initial support for the Toshiba TC358768 RGB to DSI bridge. The driver is based on the mainline Linux Toshiba TC358768 bridge driver and implements the same set of features. Tested-by: Andreas Westman Dorcsak # ASUS TF700T Signed-off-by: Svyatoslav Ryhel --- drivers/video/bridge/Kconfig| 9 + drivers/video/bridge/Makefile | 1 + drivers/video/bridge/tc358768.c | 985 3 files changed, 995 insertions(+) create mode 100644 drivers/video/bridge/tc358768.c diff --git a/drivers/video/bridge/Kconfig b/drivers/video/bridge/Kconfig index 2311ca2d1a..6a9e7c1454 100644 --- a/drivers/video/bridge/Kconfig +++ b/drivers/video/bridge/Kconfig @@ -40,3 +40,12 @@ config VIDEO_BRIDGE_SOLOMON_SSD2825 select VIDEO_MIPI_DSI help Solomon SSD2824 SPI RGB-DSI bridge driver wrapped into panel uClass. + +config VIDEO_BRIDGE_TOSHIBA_TC358768 + bool "Support Toshiba TC358768 MIPI DSI bridge" + depends on PANEL && DM_GPIO + select VIDEO_MIPI_DSI + select DM_I2C + help + Toshiba TC358768AXBG/TC358778XBG DSI bridge chip driver. + Found in Asus Transformer Infinity TF700T. diff --git a/drivers/video/bridge/Makefile b/drivers/video/bridge/Makefile index 22625c8bc6..ed3e7e9ce1 100644 --- a/drivers/video/bridge/Makefile +++ b/drivers/video/bridge/Makefile @@ -8,3 +8,4 @@ obj-$(CONFIG_VIDEO_BRIDGE_PARADE_PS862X) += ps862x.o obj-$(CONFIG_VIDEO_BRIDGE_NXP_PTN3460) += ptn3460.o obj-$(CONFIG_VIDEO_BRIDGE_ANALOGIX_ANX6345) += anx6345.o obj-$(CONFIG_VIDEO_BRIDGE_SOLOMON_SSD2825) += ssd2825.o +obj-$(CONFIG_VIDEO_BRIDGE_TOSHIBA_TC358768) += tc358768.o diff --git a/drivers/video/bridge/tc358768.c b/drivers/video/bridge/tc358768.c new file mode 100644 index 00..19b6ca29d3 --- /dev/null +++ b/drivers/video/bridge/tc358768.c @@ -0,0 +1,985 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) 2020 Texas Instruments Incorporated + * Copyright (C) 2022 Svyatoslav Ryhel + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +/* Global (16-bit addressable) */ +#define TC358768_CHIPID0x +#define TC358768_SYSCTL0x0002 +#define TC358768_CONFCTL 0x0004 +#define TC358768_VSDLY 0x0006 +#define TC358768_DATAFMT 0x0008 +#define TC358768_GPIOEN0x000E +#define TC358768_GPIODIR 0x0010 +#define TC358768_GPIOIN0x0012 +#define TC358768_GPIOOUT 0x0014 +#define TC358768_PLLCTL0 0x0016 +#define TC358768_PLLCTL1 0x0018 +#define TC358768_CMDBYTE 0x0022 +#define TC358768_PP_MISC 0x0032 +#define TC358768_DSITX_DT 0x0050 +#define TC358768_FIFOSTATUS0x00F8 + +/* Debug (16-bit addressable) */ +#define TC358768_VBUFCTRL 0x00E0 +#define TC358768_DBG_WIDTH 0x00E2 +#define TC358768_DBG_VBLANK0x00E4 +#define TC358768_DBG_DATA 0x00E8 + +/* TX PHY (32-bit addressable) */ +#define TC358768_CLW_DPHYCONTTX0x0100 +#define TC358768_D0W_DPHYCONTTX0x0104 +#define TC358768_D1W_DPHYCONTTX0x0108 +#define TC358768_D2W_DPHYCONTTX0x010C +#define TC358768_D3W_DPHYCONTTX0x0110 +#define TC358768_CLW_CNTRL 0x0140 +#define TC358768_D0W_CNTRL 0x0144 +#define TC358768_D1W_CNTRL 0x0148 +#define TC358768_D2W_CNTRL 0x014C +#define TC358768_D3W_CNTRL 0x0150 + +/* TX PPI (32-bit addressable) */ +#define TC358768_STARTCNTRL0x0204 +#define TC358768_DSITXSTATUS 0x0208 +#define TC358768_LINEINITCNT 0x0210 +#define TC358768_LPTXTIMECNT 0x0214 +#define TC358768_TCLK_HEADERCNT0x0218 +#define TC358768_TCLK_TRAILCNT 0x021C +#define TC358768_THS_HEADERCNT 0x0220 +#define TC358768_TWAKEUP 0x0224 +#define TC358768_TCLK_POSTCNT 0x0228 +#define TC358768_THS_TRAILCNT 0x022C +#define TC358768_HSTXVREGCNT 0x0230 +#define TC358768_HSTXVREGEN0x0234 +#define TC358768_TXOPTIONCNTRL 0x0238 +#define TC358768_BTACNTRL1 0x023C + +/* TX CTRL (32-bit addressable) */ +#define TC358768_DSI_CONTROL 0x040C +#define TC358768_DSI_STATUS0x0410 +#define TC358768_DSI_INT 0x0414 +#define TC358768_DSI_INT_ENA 0x0418 +#define TC358768_DSICMD_RDFIFO 0x0430 +#define TC358768_DSI_ACKERR0x0434 +#define TC358768_DSI_ACKERR_INTENA 0x0438 +#define TC358768_DSI_ACKERR_HALT 0x043c +#define TC358768_DSI_RXERR 0x0440 +#define TC358768_DSI_RXERR_INTENA 0x0444 +#define TC358768_DSI_RXERR_HALT0x0448 +#defin
[PATCH v2 4/7] video: bridge: add basic support for the Parade DP501 transmitter
From: Jonas Schwöbel The Parade DP501 is a DP & DVI/HDMI dual-mode transmitter. It enables an RGB/Parallel SOC output to be converted, packed and serialized into either DP or TMDS output device. Only DisplayPort functionality of this transmitter has been implemented and tested. Signed-off-by: Jonas Schwöbel Signed-off-by: Svyatoslav Ryhel --- drivers/video/bridge/Kconfig | 10 + drivers/video/bridge/Makefile | 1 + drivers/video/bridge/dp501.c | 579 ++ 3 files changed, 590 insertions(+) create mode 100644 drivers/video/bridge/dp501.c diff --git a/drivers/video/bridge/Kconfig b/drivers/video/bridge/Kconfig index 6a9e7c1454..ab91727372 100644 --- a/drivers/video/bridge/Kconfig +++ b/drivers/video/bridge/Kconfig @@ -7,6 +7,16 @@ config VIDEO_BRIDGE requires LVDS, an eDP->LVDS bridge chip can be used to provide the necessary conversion. This option enables support for these devices. +config VIDEO_BRIDGE_PARADE_DP501 + bool "Support Parade DP501 DP & DVI/HDMI dual mode transmitter" + depends on PANEL && DM_GPIO + select DM_I2C + help + The Parade DP501 is a DP & DVI/HDMI dual-mode transmitter. It + enables an RGB/Parallel SOC output to be converted, packed and + serialized into either DP or TMDS output device. Only DisplayPort + functionality of this transmitter has been implemented and tested. + config VIDEO_BRIDGE_PARADE_PS862X bool "Support Parade PS862X DP->LVDS bridge" depends on VIDEO_BRIDGE diff --git a/drivers/video/bridge/Makefile b/drivers/video/bridge/Makefile index ed3e7e9ce1..58697e3cbe 100644 --- a/drivers/video/bridge/Makefile +++ b/drivers/video/bridge/Makefile @@ -4,6 +4,7 @@ # Written by Simon Glass obj-$(CONFIG_VIDEO_BRIDGE) += video-bridge-uclass.o +obj-$(CONFIG_VIDEO_BRIDGE_PARADE_DP501) += dp501.o obj-$(CONFIG_VIDEO_BRIDGE_PARADE_PS862X) += ps862x.o obj-$(CONFIG_VIDEO_BRIDGE_NXP_PTN3460) += ptn3460.o obj-$(CONFIG_VIDEO_BRIDGE_ANALOGIX_ANX6345) += anx6345.o diff --git a/drivers/video/bridge/dp501.c b/drivers/video/bridge/dp501.c new file mode 100644 index 00..095e3e71fe --- /dev/null +++ b/drivers/video/bridge/dp501.c @@ -0,0 +1,579 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) 2024 Jonas Schwöbel + * Copyright (C) 2024 Svyatoslav Ryhel + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +/* TOP */ +#define TOPCFG00x00 +#define ROMI2C_PRESCALE0x01 +#define HDCPI2C_PRESCALE 0x02 +#define GPIO 0x03 +#define GPIO_OUT_ENB 0x04 +#define TESTI2C_CTL0x05 +#define I2CMTIMEOUT0x06 +#define TOPCFG10x07 +#define TOPCFG20x08 +#define TOPCFG30x09 +#define TOPCFG40x0A +#define CLKSWRST 0x0B +#define CADETB_CTL 0x0C + +/* Video Attribute */ +#define HTOTAL_L 0x10 +#define HTOTAL_H 0x11 +#define HSTART_L 0x12 +#define HSTART_H 0x13 +#define HWIDTH_L 0x14 +#define HWIDTH_H 0x15 +#define VTOTAL_L 0x16 +#define VTOTAL_H 0x17 +#define VSTART_L 0x18 +#define VSTART_H 0x19 +#define VHEIGHT_L 0x1A +#define VHEIGHT_H 0x1B +#define HSPHSW_L 0x1C +#define HSPHSW_H 0x1D +#define VSPVSW_L 0x1E +#define VSPVSW_H 0x1F +#define MISC0 0x20 +#define MISC1 0x21 + +/* Video Capture */ +#define VCAPCTRL0 0x24 +#define VCAPCTRL1 0x25 +#define VCAPCTRL2 0x26 +#define VCAPCTRL3 0x27 +#define VCAPCTRL4 0x28 +#define VCAP_MEASURE 0x29 + +/* Main Link Control */ +#define NVID_L 0x2C +#define NVID_M 0x2D +#define NVID_H 0x2E +#define LINK_CTRL0 0x2F +#define LINK_CTRL1 0x30 +#define LINK_DEBUG 0x31 +#define ERR_POS0x32 +#define ERR_PAT0x33 +#define LINK_DEB_SEL 0x34 +#define IDLE_PATTERN 0x35 +#define TU_SIZE0x36 +#define CRC_CTRL 0x37 +#define CRC_OUT0x38 + +/* AVI-2 InfoFrame */ +#define SD_CTRL0 0x3A +#define SD_CTRL1 0x3B +#define SD_HB0 0x3C +#define SD_HB1 0x3D +#define SD_HB2 0x3E +#define SD_HB3 0x3F +#define SD_DB0 0x40 +#define SD_DB1 0x41 +#define SD_DB2 0x42 +#define SD_DB3 0x43 +#define SD_DB4 0x44 +#define SD_DB5
[PATCH v2 2/7] video: panel: add Samsung LTL106HL02 MIPI DSI panel driver
From: Anton Bambura LTL106HL02 is a color active matrix TFT (Thin Film Transistor) liquid crystal display (LCD) that uses amorphous silicon TFT as switching devices. This model is composed of a TFT LCD panel, a driver circuit and a backlight unit. The resolution of a 10.6" contains 1920 x 1080 pixels and can display up to 16,8M color with wide viewing angle. Co-developed-by: Jonas Schwöbel Signed-off-by: Jonas Schwöbel Co-developed-by: Svyatoslav Ryhel Signed-off-by: Svyatoslav Ryhel Signed-off-by: Anton Bambura --- drivers/video/Kconfig | 9 ++ drivers/video/Makefile | 1 + drivers/video/samsung-ltl106hl02.c | 157 + 3 files changed, 167 insertions(+) create mode 100644 drivers/video/samsung-ltl106hl02.c diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig index 05567a0095..52b515197d 100644 --- a/drivers/video/Kconfig +++ b/drivers/video/Kconfig @@ -555,6 +555,15 @@ config VIDEO_LCD_RENESAS_R69328 IPS-LCD module with Renesas R69328 IC. The panel has a 720x1280 resolution and uses 24 bit RGB per pixel. +config VIDEO_LCD_SAMSUNG_LTL106HL02 + tristate "Samsung LTL106HL02 1920x1080 DSI video mode panel" + depends on PANEL && BACKLIGHT + select VIDEO_MIPI_DSI + help + Say Y here if you want to enable support for Samsung LTL106HL02 + LCD module found in Microsoft Surface 2. The panel has a FullHD + resolution (1920x1080). + config VIDEO_LCD_SSD2828 bool "SSD2828 bridge chip" ---help--- diff --git a/drivers/video/Makefile b/drivers/video/Makefile index bb6d9b74b9..f3f70cd04a 100644 --- a/drivers/video/Makefile +++ b/drivers/video/Makefile @@ -63,6 +63,7 @@ obj-$(CONFIG_VIDEO_LCD_ORISETECH_OTM8009A) += orisetech_otm8009a.o obj-$(CONFIG_VIDEO_LCD_RAYDIUM_RM68200) += raydium-rm68200.o obj-$(CONFIG_VIDEO_LCD_RENESAS_R61307) += renesas-r61307.o obj-$(CONFIG_VIDEO_LCD_RENESAS_R69328) += renesas-r69328.o +obj-$(CONFIG_VIDEO_LCD_SAMSUNG_LTL106HL02) += samsung-ltl106hl02.o obj-$(CONFIG_VIDEO_LCD_SSD2828) += ssd2828.o obj-$(CONFIG_VIDEO_LCD_TDO_TL070WSH30) += tdo-tl070wsh30.o obj-$(CONFIG_VIDEO_MCDE_SIMPLE) += mcde_simple.o diff --git a/drivers/video/samsung-ltl106hl02.c b/drivers/video/samsung-ltl106hl02.c new file mode 100644 index 00..5e6c11c4be --- /dev/null +++ b/drivers/video/samsung-ltl106hl02.c @@ -0,0 +1,157 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Samsung LTL106HL02-001 DSI panel driver + * + * Copyright (c) 2020 Anton Bambura + * Copyright (c) 2023 Svyatoslav Ryhel + * Copyright (c) 2024 Jonas Schwöbel + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +struct samsung_ltl106hl02_priv { + struct udevice *vdd; + struct udevice *backlight; + + struct gpio_desc reset_gpio; +}; + +static struct display_timing default_timing = { + .pixelclock.typ = 13700, + .hactive.typ= 1920, + .hfront_porch.typ = 32, + .hback_porch.typ= 64, + .hsync_len.typ = 32, + .vactive.typ= 1080, + .vfront_porch.typ = 2, + .vback_porch.typ= 26, + .vsync_len.typ = 3, +}; + +static int samsung_ltl106hl02_enable_backlight(struct udevice *dev) +{ + struct mipi_dsi_panel_plat *plat = dev_get_plat(dev); + struct mipi_dsi_device *dsi = plat->device; + int ret; + + ret = mipi_dsi_dcs_exit_sleep_mode(dsi); + if (ret < 0) { + log_debug("%s: failed to exit sleep mode: %d\n", + __func__, ret); + return ret; + } + mdelay(70); + + ret = mipi_dsi_dcs_set_display_on(dsi); + if (ret < 0) { + log_debug("%s: failed to enable display: %d\n", + __func__, ret); + return ret; + } + mdelay(5); + + return 0; +} + +static int samsung_ltl106hl02_set_backlight(struct udevice *dev, int percent) +{ + struct samsung_ltl106hl02_priv *priv = dev_get_priv(dev); + int ret; + + ret = backlight_enable(priv->backlight); + if (ret) + return ret; + + return backlight_set_brightness(priv->backlight, percent); +} + +static int samsung_ltl106hl02_timings(struct udevice *dev, + struct display_timing *timing) +{ + memcpy(timing, _timing, sizeof(*timing)); + return 0; +} + +static int samsung_ltl106hl02_of_to_plat(struct udevice *dev) +{ + struct samsung_ltl106hl02_priv *priv = dev_get_priv(dev); + int ret; + + ret = uclass_get_device_by_phandle(UCLASS_PANEL_BACKLIGHT, dev, + "backlight", >backlight); + if (ret) { + log_debug("%s: cannot get backlight: ret = %d\n", +
[PATCH v2 1/7] video: panel: add LG LG070WX3 MIPI DSI panel driver
The LD070WX3 is a Color Active Matrix Liquid Crystal Display with an integral Light Emitting Diode (LED) backlight system. The matrix employs a-Si Thin Film Transistor as the active element. It is a transmissive type display operating in the normally Black mode. This TFT-LCD has 7.0 inches diagonally measured active display area with WXGA resolution (800 by 1280 pixel array). Signed-off-by: Svyatoslav Ryhel --- drivers/video/Kconfig | 8 ++ drivers/video/Makefile | 1 + drivers/video/lg-ld070wx3.c | 186 3 files changed, 195 insertions(+) create mode 100644 drivers/video/lg-ld070wx3.c diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig index e2016d73d1..05567a0095 100644 --- a/drivers/video/Kconfig +++ b/drivers/video/Kconfig @@ -522,6 +522,14 @@ config VIDEO_LCD_ORISETECH_OTM8009A Say Y here if you want to enable support for Orise Technology otm8009a 480x800 dsi 2dl panel. +config VIDEO_LCD_LG_LD070WX3 + bool "LD070WX3 DSI LCD panel support" + depends on PANEL && BACKLIGHT + select VIDEO_MIPI_DSI + help + Say Y here if you want to enable support for LG LD070WX3 + 800x1280 DSI video mode panel. + config VIDEO_LCD_RAYDIUM_RM68200 bool "RM68200 DSI LCD panel support" select VIDEO_MIPI_DSI diff --git a/drivers/video/Makefile b/drivers/video/Makefile index fdc2937632..bb6d9b74b9 100644 --- a/drivers/video/Makefile +++ b/drivers/video/Makefile @@ -58,6 +58,7 @@ obj-$(CONFIG_VIDEO_LCD_ANX9804) += anx9804.o obj-$(CONFIG_VIDEO_LCD_ENDEAVORU) += endeavoru-panel.o obj-$(CONFIG_VIDEO_LCD_HIMAX_HX8394) += himax-hx8394.o obj-$(CONFIG_VIDEO_LCD_HITACHI_TX18D42VM) += hitachi_tx18d42vm_lcd.o +obj-$(CONFIG_VIDEO_LCD_LG_LD070WX3) += lg-ld070wx3.o obj-$(CONFIG_VIDEO_LCD_ORISETECH_OTM8009A) += orisetech_otm8009a.o obj-$(CONFIG_VIDEO_LCD_RAYDIUM_RM68200) += raydium-rm68200.o obj-$(CONFIG_VIDEO_LCD_RENESAS_R61307) += renesas-r61307.o diff --git a/drivers/video/lg-ld070wx3.c b/drivers/video/lg-ld070wx3.c new file mode 100644 index 00..610a06ffe7 --- /dev/null +++ b/drivers/video/lg-ld070wx3.c @@ -0,0 +1,186 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * LG LD070WX3-SL01 DSI panel driver + * + * Copyright (c) 2023 Svyatoslav Ryhel + */ + +#include +#include +#include +#include +#include +#include +#include + +struct lg_ld070wx3_priv { + struct udevice *vdd; + struct udevice *vcc; + + struct udevice *backlight; +}; + +static struct display_timing default_timing = { + .pixelclock.typ = 7000, + .hactive.typ= 800, + .hfront_porch.typ = 32, + .hback_porch.typ= 48, + .hsync_len.typ = 8, + .vactive.typ= 1280, + .vfront_porch.typ = 5, + .vback_porch.typ= 3, + .vsync_len.typ = 1, +}; + +static void dcs_write_one(struct mipi_dsi_device *dsi, u8 cmd, u8 data) +{ + mipi_dsi_dcs_write(dsi, cmd, , 1); +} + +static int lg_ld070wx3_enable_backlight(struct udevice *dev) +{ + struct mipi_dsi_panel_plat *plat = dev_get_plat(dev); + struct mipi_dsi_device *dsi = plat->device; + int ret; + + ret = mipi_dsi_dcs_soft_reset(dsi); + if (ret < 0) { + log_debug("%s: failed to soft reset panel: %d\n", + __func__, ret); + return ret; + } + + /* Delay before sending new command after soft reset */ + mdelay(20); + + /* Differential input impedance selection */ + dcs_write_one(dsi, 0xAE, 0x0B); + + /* Enter test mode 1 and 2*/ + dcs_write_one(dsi, 0xEE, 0xEA); + dcs_write_one(dsi, 0xEF, 0x5F); + + /* Increased MIPI CLK driving ability */ + dcs_write_one(dsi, 0xF2, 0x68); + + /* Exit test mode 1 and 2 */ + dcs_write_one(dsi, 0xEE, 0x00); + dcs_write_one(dsi, 0xEF, 0x00); + + return 0; +} + +static int lg_ld070wx3_set_backlight(struct udevice *dev, int percent) +{ + struct lg_ld070wx3_priv *priv = dev_get_priv(dev); + int ret; + + ret = backlight_enable(priv->backlight); + if (ret) + return ret; + + return backlight_set_brightness(priv->backlight, percent); +} + +static int lg_ld070wx3_timings(struct udevice *dev, + struct display_timing *timing) +{ + memcpy(timing, _timing, sizeof(*timing)); + return 0; +} + +static int lg_ld070wx3_of_to_plat(struct udevice *dev) +{ + struct lg_ld070wx3_priv *priv = dev_get_priv(dev); + int ret; + + ret = uclass_get_device_by_phandle(UCLASS_PANEL_BACKLIGHT, dev, + "backlight", >backlight); + if (ret) { + log_debug("%s: cannot get backlight: ret = %d\n", + __func__, ret); +
[PATCH v2 0/7] Tegra panel improvements
The current patch set improves the logic of existing panels and bridge used by Tegra 3 devices and brings support for additional DSI panels used by Tegra 4 devices. New and existing drivers are fully reusable, contain no device specific parts, and are written according to existing datasheets. --- Changes from v1: - improved ssd2825 code style - added TC358768 RGB to DSI bridge bringup commit (used by TF700T) - added Parade DP501 transmitter bringup (used by Lenovo Ideapad Yoga 11) --- Anton Bambura (1): video: panel: add Samsung LTL106HL02 MIPI DSI panel driver Jonas Schwöbel (1): video: bridge: add basic support for the Parade DP501 transmitter Svyatoslav Ryhel (5): video: panel: add LG LG070WX3 MIPI DSI panel driver video: bridge: add Toshiba TC358768 RGB to DSI bridge support video: endeavoru-panel: shift the init sequence by one step earlier video: bridge: ssd2825: shift the init sequence by one step earlier video: renesas: shift the init sequence by one step earlier drivers/video/Kconfig | 17 + drivers/video/Makefile | 2 + drivers/video/bridge/Kconfig | 19 + drivers/video/bridge/Makefile | 2 + drivers/video/bridge/dp501.c | 579 + drivers/video/bridge/ssd2825.c | 86 +-- drivers/video/bridge/tc358768.c| 985 + drivers/video/endeavoru-panel.c| 128 ++-- drivers/video/lg-ld070wx3.c| 186 ++ drivers/video/renesas-r61307.c | 93 +-- drivers/video/renesas-r69328.c | 81 +-- drivers/video/samsung-ltl106hl02.c | 157 + 12 files changed, 2155 insertions(+), 180 deletions(-) create mode 100644 drivers/video/bridge/dp501.c create mode 100644 drivers/video/bridge/tc358768.c create mode 100644 drivers/video/lg-ld070wx3.c create mode 100644 drivers/video/samsung-ltl106hl02.c -- 2.40.1
[PATCH v2 1/1] boot: pxe_utils: skip fdt setup in case legacy kernel is booted
Currently, if boot with extlinux.conf and do not set the fdt U-Boot will provide its own device tree. This behavior is beneficial if the U-Boot device tree is in sync with Linux, but it totally halts the booting of pre-dtb kernels (3.4 for example) since it uses ATAGs. To fix this, pass `-` in the fdt extlinux field as a signal that no tree should be used. Suggested-by: Jonas Schwöbel Tested-by: Jethro Bull Signed-off-by: Svyatoslav Ryhel --- boot/pxe_utils.c | 27 ++- doc/develop/distro.rst | 6 ++ 2 files changed, 28 insertions(+), 5 deletions(-) diff --git a/boot/pxe_utils.c b/boot/pxe_utils.c index 83bc167785..9620562675 100644 --- a/boot/pxe_utils.c +++ b/boot/pxe_utils.c @@ -634,7 +634,12 @@ static int label_boot(struct pxe_context *ctx, struct pxe_label *label) char *fdtfilefree = NULL; if (label->fdt) { - fdtfile = label->fdt; + if (IS_ENABLED(CONFIG_SUPPORT_PASSING_ATAGS)) { + if (strcmp("-", label->fdt)) + fdtfile = label->fdt; + } else { + fdtfile = label->fdt; + } } else if (label->fdtdir) { char *f1, *f2, *f3, *f4, *slash; @@ -731,14 +736,26 @@ static int label_boot(struct pxe_context *ctx, struct pxe_label *label) zboot_argc = 5; } - if (!bootm_argv[3]) - bootm_argv[3] = env_get("fdt_addr"); + if (!bootm_argv[3]) { + if (IS_ENABLED(CONFIG_SUPPORT_PASSING_ATAGS)) { + if (strcmp("-", label->fdt)) + bootm_argv[3] = env_get("fdt_addr"); + } else { + bootm_argv[3] = env_get("fdt_addr"); + } + } kernel_addr_r = genimg_get_kernel_addr(kernel_addr); buf = map_sysmem(kernel_addr_r, 0); - if (!bootm_argv[3] && genimg_get_format(buf) != IMAGE_FORMAT_FIT) - bootm_argv[3] = env_get("fdtcontroladdr"); + if (!bootm_argv[3] && genimg_get_format(buf) != IMAGE_FORMAT_FIT) { + if (IS_ENABLED(CONFIG_SUPPORT_PASSING_ATAGS)) { + if (strcmp("-", label->fdt)) + bootm_argv[3] = env_get("fdtcontroladdr"); + } else { + bootm_argv[3] = env_get("fdtcontroladdr"); + } + } if (bootm_argv[3]) { if (!bootm_argv[2]) diff --git a/doc/develop/distro.rst b/doc/develop/distro.rst index 8016acad09..9e715b23eb 100644 --- a/doc/develop/distro.rst +++ b/doc/develop/distro.rst @@ -81,6 +81,12 @@ as specified at `Boot Loader Specification`_: * Does not document the fdtdir option, which automatically selects the DTB to pass to the kernel. +* If no fdt/fdtdir is provided, the U-Boot will pass its own currently used + device tree. + +* If ``-`` is passed as fdt argument and ``CONFIG_SUPPORT_PASSING_ATAGS`` is + enabled, then no device tree will be used (legacy booting / pre-dtb kernel). + See also doc/README.pxe under 'pxe file format'. One example extlinux.conf generated by the Fedora installer is:: -- 2.40.1
[PATCH v2 0/1] Fix booting kernels with ATAGS and extlinux
Currently, if boot with extlinux.conf and do not set the fdt U-Boot will provide its own device tree. This behavior is beneficial if the U-Boot device tree is in sync with Linux, but it totally halts the booting of pre-dtb kernels (3.4 for example) since it uses ATAGs. To fix this, pass `-` in the fdt extlinux field as a signal that no tree should be used. Tested with 3.4 legacy kernel and mainline 6.7 kernel on P895 (lg_x3 board). --- Changes form v1 - Added CONFIG guards - Clarified documentation --- Svyatoslav Ryhel (1): boot: pxe_utils: skip fdt setup in case legacy kernel is booted boot/pxe_utils.c | 27 ++- doc/develop/distro.rst | 6 ++ 2 files changed, 28 insertions(+), 5 deletions(-) -- 2.40.1
Re: [PATCH v1 0/1] Fix booting kernels with ATAGS and extlinux
25 січня 2024 р. 16:47:48 GMT+02:00, Tom Rini написав(-ла): >On Thu, Jan 25, 2024 at 04:34:41PM +0200, Svyatoslav wrote: >> >> >> 25 січня 2024 р. 16:17:34 GMT+02:00, Tom Rini >> написав(-ла): >> >On Thu, Jan 25, 2024 at 04:16:11PM +0200, Svyatoslav wrote: >> >> >> >> >> >> 25 січня 2024 р. 16:12:36 GMT+02:00, Tom Rini >> >> написав(-ла): >> >> >On Thu, Jan 25, 2024 at 08:51:09AM +0200, Svyatoslav wrote: >> >> >> >> >> >> >> >> >> 25 січня 2024 р. 08:29:54 GMT+02:00, Dan Carpenter >> >> >> написав(-ла): >> >> >> >On Wed, Jan 24, 2024 at 10:27:30PM +0200, Svyatoslav Ryhel wrote: >> >> >> >> Currently, if boot with extlinux.conf and do not set the fdt >> >> >> >> U-Boot will provide its own device tree. This behavior is >> >> >> >> beneficial if the U-Boot device tree is in sync with Linux, >> >> >> >> but it totally halts the booting of pre-dtb kernels (3.4 for >> >> >> >> example) since it uses ATAGs. To fix this, pass `-` in the >> >> >> >> fdt extlinux field as a signal that no tree should be used. >> >> >> > >> >> >> >Passing - doesn't seem like the most intuitive thing... Is there a >> >> >> >different argument we could use? >> >> >> > >> >> >> >> >> >> I agree that `-` is not the most intuitive argument, >> >> >> but this is a way to implement a fix with the least >> >> >> code posssible. To make this less obscure I have >> >> >> adjusted documentation. >> >> > >> >> >It's also how historically we do similar things. eg, "bootm >> >> >$kernel_addr_r - $fdt_addr_r". My question is can we re-work this, >> >> >cleanly, with guards around SUPPORT_PASSING_ATAGS to not increase size >> >> >anywhere that doesn't need this legacy case. >> >> > >> >> >> >> Which behavior you propose? >> > >> >Well, using the IS_ENABLED macro with the new tests around "-". >> > >> >> So using "-" for booting with extlinux with ATAGs is fine for you? >> Guards, sure, I will handle this. Which tests you are interested in? >> Maybe you can point to an example? Thanks. > >Sorry, I meant tests in terms of writing the code, not unit tests as no, >we don't have enough unit tests around booting a kernel as it stands and >I don't see how to just add a test for extlinux + legacy kernel. > Alright then, thanks!
Re: [PATCH v1 0/1] Fix booting kernels with ATAGS and extlinux
25 січня 2024 р. 16:17:34 GMT+02:00, Tom Rini написав(-ла): >On Thu, Jan 25, 2024 at 04:16:11PM +0200, Svyatoslav wrote: >> >> >> 25 січня 2024 р. 16:12:36 GMT+02:00, Tom Rini >> написав(-ла): >> >On Thu, Jan 25, 2024 at 08:51:09AM +0200, Svyatoslav wrote: >> >> >> >> >> >> 25 січня 2024 р. 08:29:54 GMT+02:00, Dan Carpenter >> >> написав(-ла): >> >> >On Wed, Jan 24, 2024 at 10:27:30PM +0200, Svyatoslav Ryhel wrote: >> >> >> Currently, if boot with extlinux.conf and do not set the fdt >> >> >> U-Boot will provide its own device tree. This behavior is >> >> >> beneficial if the U-Boot device tree is in sync with Linux, >> >> >> but it totally halts the booting of pre-dtb kernels (3.4 for >> >> >> example) since it uses ATAGs. To fix this, pass `-` in the >> >> >> fdt extlinux field as a signal that no tree should be used. >> >> > >> >> >Passing - doesn't seem like the most intuitive thing... Is there a >> >> >different argument we could use? >> >> > >> >> >> >> I agree that `-` is not the most intuitive argument, >> >> but this is a way to implement a fix with the least >> >> code posssible. To make this less obscure I have >> >> adjusted documentation. >> > >> >It's also how historically we do similar things. eg, "bootm >> >$kernel_addr_r - $fdt_addr_r". My question is can we re-work this, >> >cleanly, with guards around SUPPORT_PASSING_ATAGS to not increase size >> >anywhere that doesn't need this legacy case. >> > >> >> Which behavior you propose? > >Well, using the IS_ENABLED macro with the new tests around "-". > So using "-" for booting with extlinux with ATAGs is fine for you? Guards, sure, I will handle this. Which tests you are interested in? Maybe you can point to an example? Thanks.
Re: [PATCH v1 0/1] Fix booting kernels with ATAGS and extlinux
25 січня 2024 р. 16:12:36 GMT+02:00, Tom Rini написав(-ла): >On Thu, Jan 25, 2024 at 08:51:09AM +0200, Svyatoslav wrote: >> >> >> 25 січня 2024 р. 08:29:54 GMT+02:00, Dan Carpenter >> написав(-ла): >> >On Wed, Jan 24, 2024 at 10:27:30PM +0200, Svyatoslav Ryhel wrote: >> >> Currently, if boot with extlinux.conf and do not set the fdt >> >> U-Boot will provide its own device tree. This behavior is >> >> beneficial if the U-Boot device tree is in sync with Linux, >> >> but it totally halts the booting of pre-dtb kernels (3.4 for >> >> example) since it uses ATAGs. To fix this, pass `-` in the >> >> fdt extlinux field as a signal that no tree should be used. >> > >> >Passing - doesn't seem like the most intuitive thing... Is there a >> >different argument we could use? >> > >> >> I agree that `-` is not the most intuitive argument, >> but this is a way to implement a fix with the least >> code posssible. To make this less obscure I have >> adjusted documentation. > >It's also how historically we do similar things. eg, "bootm >$kernel_addr_r - $fdt_addr_r". My question is can we re-work this, >cleanly, with guards around SUPPORT_PASSING_ATAGS to not increase size >anywhere that doesn't need this legacy case. > Which behavior you propose?
Re: [PATCH v1 0/1] Fix booting kernels with ATAGS and extlinux
25 січня 2024 р. 08:29:54 GMT+02:00, Dan Carpenter написав(-ла): >On Wed, Jan 24, 2024 at 10:27:30PM +0200, Svyatoslav Ryhel wrote: >> Currently, if boot with extlinux.conf and do not set the fdt >> U-Boot will provide its own device tree. This behavior is >> beneficial if the U-Boot device tree is in sync with Linux, >> but it totally halts the booting of pre-dtb kernels (3.4 for >> example) since it uses ATAGs. To fix this, pass `-` in the >> fdt extlinux field as a signal that no tree should be used. > >Passing - doesn't seem like the most intuitive thing... Is there a >different argument we could use? > I agree that `-` is not the most intuitive argument, but this is a way to implement a fix with the least code posssible. To make this less obscure I have adjusted documentation. Currently if no fdt is specified u-boot will pass its own device tree and if leave fdt field blank u-boot will fail with the wrong name for the device tree. So there is NO way to boot ATAGs based kernel if u-boot has an appended tree and fdt support built in. >regards, >dan carpenter >
[PATCH v1 1/1] boot: pxe_utils: skip fdt setup in case legacy kernel is booted
Currently, if boot with extlinux.conf and do not set the fdt U-Boot will provide its own device tree. This behavior is beneficial if the U-Boot device tree is in sync with Linux, but it totally halts the booting of pre-dtb kernels (3.4 for example) since it uses ATAGs. To fix this, pass `-` in the fdt extlinux field as a signal that no tree should be used. Suggested-by: Jonas Schwöbel Tested-by: Jethro Bull Signed-off-by: Svyatoslav Ryhel --- boot/pxe_utils.c | 8 +--- doc/develop/distro.rst | 3 +++ 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/boot/pxe_utils.c b/boot/pxe_utils.c index 83bc167785..6a2c881965 100644 --- a/boot/pxe_utils.c +++ b/boot/pxe_utils.c @@ -634,7 +634,8 @@ static int label_boot(struct pxe_context *ctx, struct pxe_label *label) char *fdtfilefree = NULL; if (label->fdt) { - fdtfile = label->fdt; + if (strcmp("-", label->fdt)) + fdtfile = label->fdt; } else if (label->fdtdir) { char *f1, *f2, *f3, *f4, *slash; @@ -731,13 +732,14 @@ static int label_boot(struct pxe_context *ctx, struct pxe_label *label) zboot_argc = 5; } - if (!bootm_argv[3]) + if (!bootm_argv[3] && strcmp("-", label->fdt)) bootm_argv[3] = env_get("fdt_addr"); kernel_addr_r = genimg_get_kernel_addr(kernel_addr); buf = map_sysmem(kernel_addr_r, 0); - if (!bootm_argv[3] && genimg_get_format(buf) != IMAGE_FORMAT_FIT) + if (!bootm_argv[3] && genimg_get_format(buf) != IMAGE_FORMAT_FIT && + strcmp("-", label->fdt)) bootm_argv[3] = env_get("fdtcontroladdr"); if (bootm_argv[3]) { diff --git a/doc/develop/distro.rst b/doc/develop/distro.rst index 8016acad09..c81da8a0fd 100644 --- a/doc/develop/distro.rst +++ b/doc/develop/distro.rst @@ -81,6 +81,9 @@ as specified at `Boot Loader Specification`_: * Does not document the fdtdir option, which automatically selects the DTB to pass to the kernel. +* If no fdt/fdtdir is provided, the U-Boot will pass its own device tree, and + if fdt is passed with ``-``, then device tree will not be used (legacy booting). + See also doc/README.pxe under 'pxe file format'. One example extlinux.conf generated by the Fedora installer is:: -- 2.40.1
[PATCH v1 0/1] Fix booting kernels with ATAGS and extlinux
Currently, if boot with extlinux.conf and do not set the fdt U-Boot will provide its own device tree. This behavior is beneficial if the U-Boot device tree is in sync with Linux, but it totally halts the booting of pre-dtb kernels (3.4 for example) since it uses ATAGs. To fix this, pass `-` in the fdt extlinux field as a signal that no tree should be used. Tested with 3.4 legacy kernel and mainline 6.7 kernel on P895 (lg_x3 board). Svyatoslav Ryhel (1): boot: pxe_utils: skip fdt setup in case legacy kernel is booted boot/pxe_utils.c | 8 +--- doc/develop/distro.rst | 3 +++ 2 files changed, 8 insertions(+), 3 deletions(-) -- 2.40.1
[PATCH v1 5/5] video: renesas: shift the init sequence by one step earlier
Shift all setup stages one step earlier to better fit the existing uclass. Signed-off-by: Svyatoslav Ryhel --- drivers/video/renesas-r61307.c | 93 +++--- drivers/video/renesas-r69328.c | 81 +++-- 2 files changed, 95 insertions(+), 79 deletions(-) diff --git a/drivers/video/renesas-r61307.c b/drivers/video/renesas-r61307.c index 426fdc6224..1eccaf6b1b 100644 --- a/drivers/video/renesas-r61307.c +++ b/drivers/video/renesas-r61307.c @@ -118,42 +118,6 @@ static struct display_timing default_timing = { }; static int renesas_r61307_enable_backlight(struct udevice *dev) -{ - struct renesas_r61307_priv *priv = dev_get_priv(dev); - int ret; - - ret = regulator_set_enable_if_allowed(priv->vcc, 1); - if (ret) { - log_err("enabling vcc-supply failed (%d)\n", ret); - return ret; - } - mdelay(5); - - ret = regulator_set_enable_if_allowed(priv->iovcc, 1); - if (ret) { - log_err("enabling iovcc-supply failed (%d)\n", ret); - return ret; - } - - ret = dm_gpio_set_value(>reset_gpio, 0); - if (ret) { - log_err("changing reset-gpio failed (%d)\n", ret); - return ret; - } - mdelay(5); - - ret = dm_gpio_set_value(>reset_gpio, 1); - if (ret) { - log_err("changing reset-gpio failed (%d)\n", ret); - return ret; - } - - mdelay(5); - - return 0; -} - -static int renesas_r61307_set_backlight(struct udevice *dev, int percent) { struct renesas_r61307_priv *priv = dev_get_priv(dev); struct mipi_dsi_panel_plat *plat = dev_get_plat(dev); @@ -205,18 +169,23 @@ static int renesas_r61307_set_backlight(struct udevice *dev, int percent) log_err("failed to set display on: %d\n", ret); return ret; } - mdelay(50); + return 0; +} + +static int renesas_r61307_set_backlight(struct udevice *dev, int percent) +{ + struct renesas_r61307_priv *priv = dev_get_priv(dev); + int ret; + ret = backlight_enable(priv->backlight); if (ret) return ret; - ret = backlight_set_brightness(priv->backlight, percent); - if (ret) - return ret; + mdelay(5); - return 0; + return backlight_set_brightness(priv->backlight, percent); } static int renesas_r61307_timings(struct udevice *dev, @@ -266,6 +235,46 @@ static int renesas_r61307_of_to_plat(struct udevice *dev) return 0; } +static int renesas_r61307_hw_init(struct udevice *dev) +{ + struct renesas_r61307_priv *priv = dev_get_priv(dev); + int ret; + + ret = regulator_set_enable_if_allowed(priv->vcc, 1); + if (ret) { + log_debug("%s: enabling vcc-supply failed (%d)\n", + __func__, ret); + return ret; + } + mdelay(5); + + ret = regulator_set_enable_if_allowed(priv->iovcc, 1); + if (ret) { + log_debug("%s: enabling iovcc-supply failed (%d)\n", + __func__, ret); + return ret; + } + + ret = dm_gpio_set_value(>reset_gpio, 0); + if (ret) { + log_debug("%s: changing reset-gpio failed (%d)\n", + __func__, ret); + return ret; + } + mdelay(5); + + ret = dm_gpio_set_value(>reset_gpio, 1); + if (ret) { + log_debug("%s: changing reset-gpio failed (%d)\n", + __func__, ret); + return ret; + } + + mdelay(5); + + return 0; +} + static int renesas_r61307_probe(struct udevice *dev) { struct mipi_dsi_panel_plat *plat = dev_get_plat(dev); @@ -275,7 +284,7 @@ static int renesas_r61307_probe(struct udevice *dev) plat->format = MIPI_DSI_FMT_RGB888; plat->mode_flags = MIPI_DSI_MODE_VIDEO; - return 0; + return renesas_r61307_hw_init(dev); } static const struct panel_ops renesas_r61307_ops = { diff --git a/drivers/video/renesas-r69328.c b/drivers/video/renesas-r69328.c index d2f7169468..ecf89ec021 100644 --- a/drivers/video/renesas-r69328.c +++ b/drivers/video/renesas-r69328.c @@ -65,37 +65,6 @@ static struct display_timing default_timing = { static int renesas_r69328_enable_backlight(struct udevice *dev) { - struct renesas_r69328_priv *priv = dev_get_priv(dev); - int ret; - - ret = dm_gpio_set_value(>enable_gpio, 1); - if (ret) { - log_err("error changing enable-gpios (%d)\n", ret); - return ret; - } - mdelay(5); - - ret = dm_gpio_set_value(>reset_gpio, 0); - if (ret) { - log_err("error changing
[PATCH v1 4/5] video: bridge: ssd2825: shift the init sequence by one step earlier
Shift all setup stages one step earlier to better fit the existing uclass. Signed-off-by: Svyatoslav Ryhel --- drivers/video/bridge/ssd2825.c | 82 +++--- 1 file changed, 46 insertions(+), 36 deletions(-) diff --git a/drivers/video/bridge/ssd2825.c b/drivers/video/bridge/ssd2825.c index cea20dcffa..9783e9e05a 100644 --- a/drivers/video/bridge/ssd2825.c +++ b/drivers/video/bridge/ssd2825.c @@ -351,38 +351,6 @@ static int ssd2825_bridge_enable_panel(struct udevice *dev) struct display_timing *dt = >timing; int ret; - ret = clk_prepare_enable(priv->tx_clk); - if (ret) { - log_err("error enabling tx_clk (%d)\n", ret); - return ret; - } - - ret = dm_gpio_set_value(>power_gpio, 1); - if (ret) { - log_err("error changing power-gpios (%d)\n", ret); - return ret; - } - mdelay(10); - - ret = dm_gpio_set_value(>reset_gpio, 0); - if (ret) { - log_err("error changing reset-gpios (%d)\n", ret); - return ret; - } - mdelay(10); - - ret = dm_gpio_set_value(>reset_gpio, 1); - if (ret) { - log_err("error changing reset-gpios (%d)\n", ret); - return ret; - } - mdelay(10); - - /* Perform panel HW setup */ - ret = panel_enable_backlight(priv->panel); - if (ret) - return ret; - /* Perform SW reset */ ssd2825_write_register(dev, SSD2825_OPERATION_CTRL_REG, 0x0100); @@ -417,8 +385,8 @@ static int ssd2825_bridge_enable_panel(struct udevice *dev) SSD2825_CONF_REG_ECD | SSD2825_CONF_REG_EOT); ssd2825_write_register(dev, SSD2825_VC_CTRL_REG, 0x); - /* Set up SW panel configuration */ - ret = panel_set_backlight(priv->panel, BACKLIGHT_DEFAULT); + /* Perform panel setup */ + ret = panel_enable_backlight(priv->panel); if (ret) return ret; @@ -427,7 +395,10 @@ static int ssd2825_bridge_enable_panel(struct udevice *dev) static int ssd2825_bridge_set_panel(struct udevice *dev, int percent) { - return 0; + struct ssd2825_bridge_priv *priv = dev_get_priv(dev); + + /* Set up SW panel configuration */ + return panel_set_backlight(priv->panel, percent); } static int ssd2825_bridge_panel_timings(struct udevice *dev, @@ -440,6 +411,45 @@ static int ssd2825_bridge_panel_timings(struct udevice *dev, return 0; } +static int ssd2825_bridge_hw_init(struct udevice *dev) +{ + struct ssd2825_bridge_priv *priv = dev_get_priv(dev); + int ret; + + ret = clk_prepare_enable(priv->tx_clk); + if (ret) { + log_debug("%s: error enabling tx_clk (%d)\n", + __func__, ret); + return ret; + } + + ret = dm_gpio_set_value(>power_gpio, 1); + if (ret) { + log_debug("%s: error changing power-gpios (%d)\n", + __func__, ret); + return ret; + } + mdelay(10); + + ret = dm_gpio_set_value(>reset_gpio, 0); + if (ret) { + log_debug("%s: error changing reset-gpios (%d)\n", + __func__, ret); + return ret; + } + mdelay(10); + + ret = dm_gpio_set_value(>reset_gpio, 1); + if (ret) { + log_debug("%s: error changing reset-gpios (%d)\n", + __func__, ret); + return ret; + } + mdelay(10); + + return 0; +} + static int ssd2825_bridge_probe(struct udevice *dev) { struct ssd2825_bridge_priv *priv = dev_get_priv(dev); @@ -496,7 +506,7 @@ static int ssd2825_bridge_probe(struct udevice *dev) return PTR_ERR(priv->tx_clk); } - return 0; + return ssd2825_bridge_hw_init(dev); } static const struct panel_ops ssd2825_bridge_ops = { -- 2.40.1
[PATCH v1 3/5] video: endeavoru-panel: shift the init sequence by one step earlier
Shift all setup stages one step earlier to better fit the existing uclass. Signed-off-by: Svyatoslav Ryhel --- drivers/video/endeavoru-panel.c | 128 +--- 1 file changed, 68 insertions(+), 60 deletions(-) diff --git a/drivers/video/endeavoru-panel.c b/drivers/video/endeavoru-panel.c index 79a272128b..1bff641434 100644 --- a/drivers/video/endeavoru-panel.c +++ b/drivers/video/endeavoru-panel.c @@ -57,61 +57,8 @@ static void dcs_write_one(struct mipi_dsi_device *dsi, u8 cmd, u8 data) static int endeavoru_panel_enable_backlight(struct udevice *dev) { - struct endeavoru_panel_priv *priv = dev_get_priv(dev); - int ret; - - ret = dm_gpio_set_value(>reset_gpio, 1); - if (ret) { - log_err("error changing reset-gpios (%d)\n", ret); - return ret; - } - mdelay(5); - - ret = regulator_set_enable_if_allowed(priv->vddio, 1); - if (ret) { - log_err("error enabling iovcc-supply (%d)\n", ret); - return ret; - } - mdelay(1); - - ret = regulator_set_enable_if_allowed(priv->vdd, 1); - if (ret) { - log_err("error enabling vcc-supply (%d)\n", ret); - return ret; - } - mdelay(20); - - ret = dm_gpio_set_value(>reset_gpio, 0); - if (ret) { - log_err("error changing reset-gpios (%d)\n", ret); - return ret; - } - mdelay(2); - - /* Reset panel */ - ret = dm_gpio_set_value(>reset_gpio, 1); - if (ret) { - log_err("error changing reset-gpios (%d)\n", ret); - return ret; - } - mdelay(1); - - ret = dm_gpio_set_value(>reset_gpio, 0); - if (ret) { - log_err("error changing reset-gpios (%d)\n", ret); - return ret; - } - mdelay(25); - - return 0; -} - -static int endeavoru_panel_set_backlight(struct udevice *dev, int percent) -{ - struct endeavoru_panel_priv *priv = dev_get_priv(dev); struct mipi_dsi_panel_plat *plat = dev_get_plat(dev); struct mipi_dsi_device *dsi = plat->device; - int ret; dcs_write_one(dsi, 0xc2, 0x08); @@ -160,18 +107,22 @@ static int endeavoru_panel_set_backlight(struct udevice *dev, int percent) dcs_write_one(dsi, 0x55, 0x80); dcs_write_one(dsi, 0x5e, 0x06); - ret = backlight_enable(priv->backlight); - if (ret) - return ret; - /* Set backlight */ dcs_write_one(dsi, 0x51, 0x96); - ret = backlight_set_brightness(priv->backlight, percent); + return 0; +} + +static int endeavoru_panel_set_backlight(struct udevice *dev, int percent) +{ + struct endeavoru_panel_priv *priv = dev_get_priv(dev); + int ret; + + ret = backlight_enable(priv->backlight); if (ret) return ret; - return 0; + return backlight_set_brightness(priv->backlight, percent); } static int endeavoru_panel_timings(struct udevice *dev, @@ -217,6 +168,63 @@ static int endeavoru_panel_of_to_plat(struct udevice *dev) return 0; } +static int endeavoru_panel_hw_init(struct udevice *dev) +{ + struct endeavoru_panel_priv *priv = dev_get_priv(dev); + int ret; + + ret = dm_gpio_set_value(>reset_gpio, 1); + if (ret) { + log_debug("%s: error changing reset-gpios (%d)\n", + __func__, ret); + return ret; + } + mdelay(5); + + ret = regulator_set_enable_if_allowed(priv->vddio, 1); + if (ret) { + log_debug("%s: error enabling iovcc-supply (%d)\n", + __func__, ret); + return ret; + } + mdelay(1); + + ret = regulator_set_enable_if_allowed(priv->vdd, 1); + if (ret) { + log_debug("%s: error enabling vcc-supply (%d)\n", + __func__, ret); + return ret; + } + mdelay(20); + + ret = dm_gpio_set_value(>reset_gpio, 0); + if (ret) { + log_debug("%s: error changing reset-gpios (%d)\n", + __func__, ret); + return ret; + } + mdelay(2); + + /* Reset panel */ + ret = dm_gpio_set_value(>reset_gpio, 1); + if (ret) { + log_debug("%s: error changing reset-gpios (%d)\n", + __func__, ret); + return ret; + } + mdelay(1); + + ret = dm_gpio_set_value(>reset_gpio, 0); + if (ret) { + log_debug("%s: error changing reset-gpios (%d)\n", + __func__, ret); + return ret; + } + mdelay(25); + + return 0; +} + static int ende
[PATCH v1 2/5] video: panel: add Samsung LTL106HL02 MIPI DSI panel driver
From: Anton Bambura LTL106HL02 is a color active matrix TFT (Thin Film Transistor) liquid crystal display (LCD) that uses amorphous silicon TFT as switching devices. This model is composed of a TFT LCD panel, a driver circuit and a backlight unit. The resolution of a 10.6" contains 1920 x 1080 pixels and can display up to 16,8M color with wide viewing angle. Co-developed-by: Jonas Schwöbel Signed-off-by: Jonas Schwöbel Co-developed-by: Svyatoslav Ryhel Signed-off-by: Svyatoslav Ryhel Signed-off-by: Anton Bambura --- drivers/video/Kconfig | 9 ++ drivers/video/Makefile | 1 + drivers/video/samsung-ltl106hl02.c | 157 + 3 files changed, 167 insertions(+) create mode 100644 drivers/video/samsung-ltl106hl02.c diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig index 05567a0095..52b515197d 100644 --- a/drivers/video/Kconfig +++ b/drivers/video/Kconfig @@ -555,6 +555,15 @@ config VIDEO_LCD_RENESAS_R69328 IPS-LCD module with Renesas R69328 IC. The panel has a 720x1280 resolution and uses 24 bit RGB per pixel. +config VIDEO_LCD_SAMSUNG_LTL106HL02 + tristate "Samsung LTL106HL02 1920x1080 DSI video mode panel" + depends on PANEL && BACKLIGHT + select VIDEO_MIPI_DSI + help + Say Y here if you want to enable support for Samsung LTL106HL02 + LCD module found in Microsoft Surface 2. The panel has a FullHD + resolution (1920x1080). + config VIDEO_LCD_SSD2828 bool "SSD2828 bridge chip" ---help--- diff --git a/drivers/video/Makefile b/drivers/video/Makefile index bb6d9b74b9..f3f70cd04a 100644 --- a/drivers/video/Makefile +++ b/drivers/video/Makefile @@ -63,6 +63,7 @@ obj-$(CONFIG_VIDEO_LCD_ORISETECH_OTM8009A) += orisetech_otm8009a.o obj-$(CONFIG_VIDEO_LCD_RAYDIUM_RM68200) += raydium-rm68200.o obj-$(CONFIG_VIDEO_LCD_RENESAS_R61307) += renesas-r61307.o obj-$(CONFIG_VIDEO_LCD_RENESAS_R69328) += renesas-r69328.o +obj-$(CONFIG_VIDEO_LCD_SAMSUNG_LTL106HL02) += samsung-ltl106hl02.o obj-$(CONFIG_VIDEO_LCD_SSD2828) += ssd2828.o obj-$(CONFIG_VIDEO_LCD_TDO_TL070WSH30) += tdo-tl070wsh30.o obj-$(CONFIG_VIDEO_MCDE_SIMPLE) += mcde_simple.o diff --git a/drivers/video/samsung-ltl106hl02.c b/drivers/video/samsung-ltl106hl02.c new file mode 100644 index 00..5e6c11c4be --- /dev/null +++ b/drivers/video/samsung-ltl106hl02.c @@ -0,0 +1,157 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Samsung LTL106HL02-001 DSI panel driver + * + * Copyright (c) 2020 Anton Bambura + * Copyright (c) 2023 Svyatoslav Ryhel + * Copyright (c) 2024 Jonas Schwöbel + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +struct samsung_ltl106hl02_priv { + struct udevice *vdd; + struct udevice *backlight; + + struct gpio_desc reset_gpio; +}; + +static struct display_timing default_timing = { + .pixelclock.typ = 13700, + .hactive.typ= 1920, + .hfront_porch.typ = 32, + .hback_porch.typ= 64, + .hsync_len.typ = 32, + .vactive.typ= 1080, + .vfront_porch.typ = 2, + .vback_porch.typ= 26, + .vsync_len.typ = 3, +}; + +static int samsung_ltl106hl02_enable_backlight(struct udevice *dev) +{ + struct mipi_dsi_panel_plat *plat = dev_get_plat(dev); + struct mipi_dsi_device *dsi = plat->device; + int ret; + + ret = mipi_dsi_dcs_exit_sleep_mode(dsi); + if (ret < 0) { + log_debug("%s: failed to exit sleep mode: %d\n", + __func__, ret); + return ret; + } + mdelay(70); + + ret = mipi_dsi_dcs_set_display_on(dsi); + if (ret < 0) { + log_debug("%s: failed to enable display: %d\n", + __func__, ret); + return ret; + } + mdelay(5); + + return 0; +} + +static int samsung_ltl106hl02_set_backlight(struct udevice *dev, int percent) +{ + struct samsung_ltl106hl02_priv *priv = dev_get_priv(dev); + int ret; + + ret = backlight_enable(priv->backlight); + if (ret) + return ret; + + return backlight_set_brightness(priv->backlight, percent); +} + +static int samsung_ltl106hl02_timings(struct udevice *dev, + struct display_timing *timing) +{ + memcpy(timing, _timing, sizeof(*timing)); + return 0; +} + +static int samsung_ltl106hl02_of_to_plat(struct udevice *dev) +{ + struct samsung_ltl106hl02_priv *priv = dev_get_priv(dev); + int ret; + + ret = uclass_get_device_by_phandle(UCLASS_PANEL_BACKLIGHT, dev, + "backlight", >backlight); + if (ret) { + log_debug("%s: cannot get backlight: ret = %d\n", +
[PATCH v1 1/5] video: panel: add LG LG070WX3 MIPI DSI panel driver
The LD070WX3 is a Color Active Matrix Liquid Crystal Display with an integral Light Emitting Diode (LED) backlight system. The matrix employs a-Si Thin Film Transistor as the active element. It is a transmissive type display operating in the normally Black mode. This TFT-LCD has 7.0 inches diagonally measured active display area with WXGA resolution (800 by 1280 pixel array). Signed-off-by: Svyatoslav Ryhel --- drivers/video/Kconfig | 8 ++ drivers/video/Makefile | 1 + drivers/video/lg-ld070wx3.c | 186 3 files changed, 195 insertions(+) create mode 100644 drivers/video/lg-ld070wx3.c diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig index e2016d73d1..05567a0095 100644 --- a/drivers/video/Kconfig +++ b/drivers/video/Kconfig @@ -522,6 +522,14 @@ config VIDEO_LCD_ORISETECH_OTM8009A Say Y here if you want to enable support for Orise Technology otm8009a 480x800 dsi 2dl panel. +config VIDEO_LCD_LG_LD070WX3 + bool "LD070WX3 DSI LCD panel support" + depends on PANEL && BACKLIGHT + select VIDEO_MIPI_DSI + help + Say Y here if you want to enable support for LG LD070WX3 + 800x1280 DSI video mode panel. + config VIDEO_LCD_RAYDIUM_RM68200 bool "RM68200 DSI LCD panel support" select VIDEO_MIPI_DSI diff --git a/drivers/video/Makefile b/drivers/video/Makefile index fdc2937632..bb6d9b74b9 100644 --- a/drivers/video/Makefile +++ b/drivers/video/Makefile @@ -58,6 +58,7 @@ obj-$(CONFIG_VIDEO_LCD_ANX9804) += anx9804.o obj-$(CONFIG_VIDEO_LCD_ENDEAVORU) += endeavoru-panel.o obj-$(CONFIG_VIDEO_LCD_HIMAX_HX8394) += himax-hx8394.o obj-$(CONFIG_VIDEO_LCD_HITACHI_TX18D42VM) += hitachi_tx18d42vm_lcd.o +obj-$(CONFIG_VIDEO_LCD_LG_LD070WX3) += lg-ld070wx3.o obj-$(CONFIG_VIDEO_LCD_ORISETECH_OTM8009A) += orisetech_otm8009a.o obj-$(CONFIG_VIDEO_LCD_RAYDIUM_RM68200) += raydium-rm68200.o obj-$(CONFIG_VIDEO_LCD_RENESAS_R61307) += renesas-r61307.o diff --git a/drivers/video/lg-ld070wx3.c b/drivers/video/lg-ld070wx3.c new file mode 100644 index 00..610a06ffe7 --- /dev/null +++ b/drivers/video/lg-ld070wx3.c @@ -0,0 +1,186 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * LG LD070WX3-SL01 DSI panel driver + * + * Copyright (c) 2023 Svyatoslav Ryhel + */ + +#include +#include +#include +#include +#include +#include +#include + +struct lg_ld070wx3_priv { + struct udevice *vdd; + struct udevice *vcc; + + struct udevice *backlight; +}; + +static struct display_timing default_timing = { + .pixelclock.typ = 7000, + .hactive.typ= 800, + .hfront_porch.typ = 32, + .hback_porch.typ= 48, + .hsync_len.typ = 8, + .vactive.typ= 1280, + .vfront_porch.typ = 5, + .vback_porch.typ= 3, + .vsync_len.typ = 1, +}; + +static void dcs_write_one(struct mipi_dsi_device *dsi, u8 cmd, u8 data) +{ + mipi_dsi_dcs_write(dsi, cmd, , 1); +} + +static int lg_ld070wx3_enable_backlight(struct udevice *dev) +{ + struct mipi_dsi_panel_plat *plat = dev_get_plat(dev); + struct mipi_dsi_device *dsi = plat->device; + int ret; + + ret = mipi_dsi_dcs_soft_reset(dsi); + if (ret < 0) { + log_debug("%s: failed to soft reset panel: %d\n", + __func__, ret); + return ret; + } + + /* Delay before sending new command after soft reset */ + mdelay(20); + + /* Differential input impedance selection */ + dcs_write_one(dsi, 0xAE, 0x0B); + + /* Enter test mode 1 and 2*/ + dcs_write_one(dsi, 0xEE, 0xEA); + dcs_write_one(dsi, 0xEF, 0x5F); + + /* Increased MIPI CLK driving ability */ + dcs_write_one(dsi, 0xF2, 0x68); + + /* Exit test mode 1 and 2 */ + dcs_write_one(dsi, 0xEE, 0x00); + dcs_write_one(dsi, 0xEF, 0x00); + + return 0; +} + +static int lg_ld070wx3_set_backlight(struct udevice *dev, int percent) +{ + struct lg_ld070wx3_priv *priv = dev_get_priv(dev); + int ret; + + ret = backlight_enable(priv->backlight); + if (ret) + return ret; + + return backlight_set_brightness(priv->backlight, percent); +} + +static int lg_ld070wx3_timings(struct udevice *dev, + struct display_timing *timing) +{ + memcpy(timing, _timing, sizeof(*timing)); + return 0; +} + +static int lg_ld070wx3_of_to_plat(struct udevice *dev) +{ + struct lg_ld070wx3_priv *priv = dev_get_priv(dev); + int ret; + + ret = uclass_get_device_by_phandle(UCLASS_PANEL_BACKLIGHT, dev, + "backlight", >backlight); + if (ret) { + log_debug("%s: cannot get backlight: ret = %d\n", + __func__, ret); +
[PATCH v1 0/5] Tegra panel improvements
The current patch set improves the logic of existing panels and bridge used by Tegra 3 devices and brings support for additional DSI panels used by Tegra 4 devices. New and existing drivers are fully reusable, contain no device specific parts, and are written according to existing datasheets. Anton Bambura (1): video: panel: add Samsung LTL106HL02 MIPI DSI panel driver Svyatoslav Ryhel (4): video: panel: add LG LG070WX3 MIPI DSI panel driver video: endeavoru-panel: shift the init sequence by one step earlier video: bridge: ssd2825: shift the init sequence by one step earlier video: renesas: shift the init sequence by one step earlier drivers/video/Kconfig | 17 +++ drivers/video/Makefile | 2 + drivers/video/bridge/ssd2825.c | 82 +++-- drivers/video/endeavoru-panel.c| 128 ++-- drivers/video/lg-ld070wx3.c| 186 + drivers/video/renesas-r61307.c | 93 --- drivers/video/renesas-r69328.c | 81 +++-- drivers/video/samsung-ltl106hl02.c | 157 8 files changed, 571 insertions(+), 175 deletions(-) create mode 100644 drivers/video/lg-ld070wx3.c create mode 100644 drivers/video/samsung-ltl106hl02.c -- 2.40.1
[PATCH v6 17/18] video: tegra20: dsi: set correct fifo depth
From: Jonas Schwöbel According to Thierry Reding's commit in the linux kernel 976cebc35bed0456a42bf96073a26f251d23b264 "drm/tegra: dsi: Make FIFO depths host parameters" correct depth of the video FIFO is 1920 *words* no *bytes* Tested-by: Ion Agorria # HTC One X Tested-by: Svyatoslav Ryhel # Nvidia Tegratab T114 Signed-off-by: Jonas Schwöbel Signed-off-by: Svyatoslav Ryhel --- drivers/video/tegra20/tegra-dsi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/video/tegra20/tegra-dsi.c b/drivers/video/tegra20/tegra-dsi.c index ddd74540f2..7d63557d1b 100644 --- a/drivers/video/tegra20/tegra-dsi.c +++ b/drivers/video/tegra20/tegra-dsi.c @@ -873,7 +873,7 @@ static int tegra_dsi_bridge_probe(struct udevice *dev) return -EINVAL; } - priv->video_fifo_depth = 480; + priv->video_fifo_depth = 1920; priv->host_fifo_depth = 64; ret = reset_get_by_name(dev, "dsi", _ctl); -- 2.40.1
[PATCH v6 18/18] video: tegra20: dsi: use set_backlight for backlight only
From: Jonas Schwöbel Shift the backlight set further to prevent visual glitches on panel init. Signed-off-by: Jonas Schwöbel Signed-off-by: Svyatoslav Ryhel --- drivers/video/tegra20/tegra-dsi.c | 10 -- 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/drivers/video/tegra20/tegra-dsi.c b/drivers/video/tegra20/tegra-dsi.c index 7d63557d1b..13dae37806 100644 --- a/drivers/video/tegra20/tegra-dsi.c +++ b/drivers/video/tegra20/tegra-dsi.c @@ -766,10 +766,6 @@ static int tegra_dsi_encoder_enable(struct udevice *dev) if (ret) return ret; - ret = panel_set_backlight(priv->panel, BACKLIGHT_DEFAULT); - if (ret) - return ret; - tegra_dsi_configure(dev, device->mode_flags); tegra_dc_enable_controller(dev); @@ -784,8 +780,10 @@ static int tegra_dsi_encoder_enable(struct udevice *dev) static int tegra_dsi_bridge_set_panel(struct udevice *dev, int percent) { - /* Is not used in tegra dc */ - return 0; + struct tegra_dsi_priv *priv = dev_get_priv(dev); + + /* Turn on/off backlight */ + return panel_set_backlight(priv->panel, percent); } static int tegra_dsi_panel_timings(struct udevice *dev, -- 2.40.1
[PATCH v6 16/18] video: tegra20: dsi: remove pre-configuration
From: Jonas Schwöbel Configuration for DC driver command mode is not required for every panel. Removed. Tested-by: Ion Agorria # HTC One X Tested-by: Svyatoslav Ryhel # Nvidia Tegratab T114 Signed-off-by: Jonas Schwöbel Signed-off-by: Svyatoslav Ryhel --- drivers/video/tegra20/tegra-dsi.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/video/tegra20/tegra-dsi.c b/drivers/video/tegra20/tegra-dsi.c index fc9ca1310a..ddd74540f2 100644 --- a/drivers/video/tegra20/tegra-dsi.c +++ b/drivers/video/tegra20/tegra-dsi.c @@ -766,8 +766,6 @@ static int tegra_dsi_encoder_enable(struct udevice *dev) if (ret) return ret; - tegra_dsi_configure(dev, 0); - ret = panel_set_backlight(priv->panel, BACKLIGHT_DEFAULT); if (ret) return ret; -- 2.40.1
[PATCH v6 15/18] video: tegra20: dsi: add reset support
Implement reset use to discard any changes which could have been applied to DSI before and can interfere with current configuration. Tested-by: Ion Agorria # HTC One X Tested-by: Svyatoslav Ryhel # Nvidia Tegratab T114 Signed-off-by: Svyatoslav Ryhel --- drivers/video/tegra20/tegra-dsi.c | 14 ++ 1 file changed, 14 insertions(+) diff --git a/drivers/video/tegra20/tegra-dsi.c b/drivers/video/tegra20/tegra-dsi.c index 25a629535e..fc9ca1310a 100644 --- a/drivers/video/tegra20/tegra-dsi.c +++ b/drivers/video/tegra20/tegra-dsi.c @@ -12,6 +12,7 @@ #include #include #include +#include #include #include #include @@ -863,6 +864,7 @@ static int tegra_dsi_bridge_probe(struct udevice *dev) struct tegra_dsi_priv *priv = dev_get_priv(dev); struct mipi_dsi_device *device = >device; struct mipi_dsi_panel_plat *mipi_plat; + struct reset_ctl reset_ctl; int ret; priv->version = dev_get_driver_data(dev); @@ -876,6 +878,13 @@ static int tegra_dsi_bridge_probe(struct udevice *dev) priv->video_fifo_depth = 480; priv->host_fifo_depth = 64; + ret = reset_get_by_name(dev, "dsi", _ctl); + if (ret) { + log_debug("%s: reset_get_by_name() failed: %d\n", + __func__, ret); + return ret; + } + ret = uclass_get_device_by_phandle(UCLASS_REGULATOR, dev, "avdd-dsi-csi-supply", >avdd); if (ret) @@ -914,12 +923,17 @@ static int tegra_dsi_bridge_probe(struct udevice *dev) tegra_dsi_get_format(device->format, >format); + reset_assert(_ctl); + ret = regulator_set_enable_if_allowed(priv->avdd, true); if (ret && ret != -ENOSYS) return ret; tegra_dsi_init_clocks(dev); + mdelay(2); + reset_deassert(_ctl); + return 0; } -- 2.40.1
[PATCH v6 14/18] video: tegra20: dsi: add T114 support
Existing Tegra DSI driver mostly fits T114 apart MIPI calibration which on T114 has dedicated driver. To resolve this MIPI calibration logic was split for pre-T114 and T114+ devices. Tested-by: Ion Agorria # HTC One X Tested-by: Svyatoslav Ryhel # Nvidia Tegratab T114 Signed-off-by: Svyatoslav Ryhel --- drivers/video/tegra20/tegra-dsi.c | 78 ++- .../video/tegra20/tegra-dsi.h | 24 +- 2 files changed, 96 insertions(+), 6 deletions(-) rename arch/arm/include/asm/arch-tegra30/dsi.h => drivers/video/tegra20/tegra-dsi.h (90%) diff --git a/drivers/video/tegra20/tegra-dsi.c b/drivers/video/tegra20/tegra-dsi.c index de225ed376..25a629535e 100644 --- a/drivers/video/tegra20/tegra-dsi.c +++ b/drivers/video/tegra20/tegra-dsi.c @@ -20,17 +20,24 @@ #include #include #include -#include #include "tegra-dc.h" +#include "tegra-dsi.h" #include "mipi-phy.h" +/* List of supported DSI bridges */ +enum { + DSI_V0, + DSI_V1, +}; + struct tegra_dsi_priv { struct mipi_dsi_host host; struct mipi_dsi_device device; struct mipi_dphy_timing dphy_timing; struct udevice *panel; + struct udevice *mipi; struct display_timing timing; struct dsi_ctlr *dsi; @@ -41,6 +48,8 @@ struct tegra_dsi_priv { int dsi_clk; int video_fifo_depth; int host_fifo_depth; + + u32 version; }; static void tegra_dc_enable_controller(struct udevice *dev) @@ -501,6 +510,41 @@ static void tegra_dsi_pad_calibrate(struct dsi_pad_ctrl_reg *pad) writel(value, TEGRA_VI_BASE + (CSI_CIL_PAD_CONFIG << 2)); } +static void tegra_dsi_mipi_calibrate(struct tegra_dsi_priv *priv) +{ + struct dsi_pad_ctrl_reg *pad = >dsi->pad; + u32 value; + int ret; + + ret = misc_set_enabled(priv->mipi, true); + if (ret) + log_debug("%s: failed to enable MIPI calibration: %d\n", + __func__, ret); + + writel(0, >pad_ctrl); + writel(0, >pad_ctrl_1); + writel(0, >pad_ctrl_2); + writel(0, >pad_ctrl_3); + writel(0, >pad_ctrl_4); + + /* DSI pad enable */ + value = DSI_PAD_CONTROL_VS1_PULLDN(0) | DSI_PAD_CONTROL_VS1_PDIO(0); + writel(value, >pad_ctrl); + + value = DSI_PAD_SLEW_UP(0x7) | DSI_PAD_SLEW_DN(0x7) | + DSI_PAD_LP_UP(0x1) | DSI_PAD_LP_DN(0x1) | + DSI_PAD_OUT_CLK(0x0); + writel(value, >pad_ctrl_2); + + value = DSI_PAD_PREEMP_PD_CLK(0x3) | DSI_PAD_PREEMP_PU_CLK(0x3) | + DSI_PAD_PREEMP_PD(0x03) | DSI_PAD_PREEMP_PU(0x3); + writel(value, >pad_ctrl_3); + + ret = misc_write(priv->mipi, 0, NULL, 0); + if (ret) + log_debug("%s: MIPI calibration failed %d\n", __func__, ret); +} + static void tegra_dsi_set_timeout(struct dsi_timeout_reg *rtimeout, unsigned long bclk, unsigned int vrefresh) @@ -664,10 +708,25 @@ static int tegra_dsi_encoder_enable(struct udevice *dev) u32 value; int ret; + /* If for some reasone DSI is enabled then it needs to +* be disabled in order for the panel initialization +* commands to be properly sent. +*/ + value = readl(>dsi_pwr_ctrl); + + if (value & DSI_POWER_CONTROL_ENABLE) { + value = readl(>dsi_pwr_ctrl); + value &= ~DSI_POWER_CONTROL_ENABLE; + writel(value, >dsi_pwr_ctrl); + } + /* Disable interrupt */ writel(0, >int_enable); - tegra_dsi_pad_calibrate(>dsi->pad); + if (priv->version) + tegra_dsi_mipi_calibrate(priv); + else + tegra_dsi_pad_calibrate(>dsi->pad); tegra_dsi_get_muldiv(device->format, , ); @@ -806,6 +865,8 @@ static int tegra_dsi_bridge_probe(struct udevice *dev) struct mipi_dsi_panel_plat *mipi_plat; int ret; + priv->version = dev_get_driver_data(dev); + priv->dsi = (struct dsi_ctlr *)dev_read_addr_ptr(dev); if (!priv->dsi) { printf("%s: No display controller address\n", __func__); @@ -828,6 +889,16 @@ static int tegra_dsi_bridge_probe(struct udevice *dev) return log_ret(ret); } + if (priv->version) { + ret = uclass_get_device_by_phandle(UCLASS_MISC, dev, + "nvidia,mipi-calibrate", + >mipi); + if (ret) { + log_debug("%s: cannot get MIPI: error %d\n", __func__, ret); + return ret; + } + } + panel_get_display_timing(priv->panel, >timing)
[PATCH v6 13/18] video: tegra20: add MIPI calibration driver
Dedicated MIPI calibration driver is used on T114 and newer. Before T114 MIPI calibration registers were part of VI and CSI. Tested-by: Svyatoslav Ryhel # Nvidia Tegratab T114 Signed-off-by: Svyatoslav Ryhel --- drivers/video/tegra20/Makefile | 2 +- drivers/video/tegra20/tegra-mipi.c | 188 + 2 files changed, 189 insertions(+), 1 deletion(-) create mode 100644 drivers/video/tegra20/tegra-mipi.c diff --git a/drivers/video/tegra20/Makefile b/drivers/video/tegra20/Makefile index f0b534c579..a75aea2a87 100644 --- a/drivers/video/tegra20/Makefile +++ b/drivers/video/tegra20/Makefile @@ -1,5 +1,5 @@ # SPDX-License-Identifier: GPL-2.0+ obj-$(CONFIG_VIDEO_TEGRA20) += tegra-dc.o -obj-$(CONFIG_VIDEO_DSI_TEGRA30) += tegra-dsi.o mipi-phy.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-mipi.c b/drivers/video/tegra20/tegra-mipi.c new file mode 100644 index 00..2df3c1a994 --- /dev/null +++ b/drivers/video/tegra20/tegra-mipi.c @@ -0,0 +1,188 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2013 NVIDIA Corporation + * Copyright (c) 2023 Svyatoslav Ryhel + */ + +#include +#include +#include +#include +#include + +#include + +/* MIPI control registers 0x00 ~ 0x60 */ +struct mipi_ctlr { + uint mipi_cal_ctrl; + uint mipi_cal_autocal_ctrl; + uint mipi_cal_status; + + uint unused1[2]; + + uint mipi_cal_config_csia; + uint mipi_cal_config_csib; + uint mipi_cal_config_csic; + uint mipi_cal_config_csid; + uint mipi_cal_config_csie; + + uint unused2[4]; + + uint mipi_cal_config_dsia; + uint mipi_cal_config_dsib; + uint mipi_cal_config_dsic; + uint mipi_cal_config_dsid; + + uint unused3[4]; + + uint mipi_cal_bias_pad_cfg0; + uint mipi_cal_bias_pad_cfg1; + uint mipi_cal_bias_pad_cfg2; +}; + +#define MIPI_CAL_CTRL_NOISE_FILTER(x) (((x) & 0xf) << 26) +#define MIPI_CAL_CTRL_PRESCALE(x) (((x) & 0x3) << 24) +#define MIPI_CAL_CTRL_CLKEN_OVRBIT(4) +#define MIPI_CAL_CTRL_STARTBIT(0) + +#define MIPI_CAL_STATUS_DONE BIT(16) +#define MIPI_CAL_STATUS_ACTIVE BIT(0) + +#define MIPI_CAL_OVERIDE(x)(((x) & 0x1) << 30) +#define MIPI_CAL_SEL(x)(((x) & 0x1) << 21) +#define MIPI_CAL_HSPDOS(x) (((x) & 0x1f) << 16) +#define MIPI_CAL_HSPUOS(x) (((x) & 0x1f) << 8) +#define MIPI_CAL_TERMOS(x) (((x) & 0x1f) << 0) + +#define MIPI_CAL_BIAS_PAD_PDVCLAMP BIT(1) +#define MIPI_CAL_BIAS_PAD_E_VCLAMP_REF BIT(0) + +#define MIPI_CAL_BIAS_PAD_DRV_DN_REF(x) (((x) & 0x7) << 16) +#define MIPI_CAL_BIAS_PAD_DRV_UP_REF(x) (((x) & 0x7) << 8) + +#define MIPI_CAL_BIAS_PAD_VCLAMP(x)(((x) & 0x7) << 16) +#define MIPI_CAL_BIAS_PAD_VAUXP(x) (((x) & 0x7) << 4) +#define MIPI_CAL_BIAS_PAD_PDVREG BIT(1) + +struct tegra_mipi_priv { + struct mipi_ctlr*mipi; + struct clk *mipi_cal; +}; + +static int tegra_mipi_calibrate(struct udevice *dev, int offset, const void *buf, + int size) +{ + struct tegra_mipi_priv *priv = dev_get_priv(dev); + u32 value; + + value = MIPI_CAL_BIAS_PAD_DRV_DN_REF(0x2) | + MIPI_CAL_BIAS_PAD_DRV_UP_REF(0x0); + writel(value, >mipi->mipi_cal_bias_pad_cfg1); + + value = readl(>mipi->mipi_cal_bias_pad_cfg2); + value &= ~MIPI_CAL_BIAS_PAD_VCLAMP(0x7); + value &= ~MIPI_CAL_BIAS_PAD_VAUXP(0x7); + writel(value, >mipi->mipi_cal_bias_pad_cfg2); + + value = MIPI_CAL_OVERIDE(0x0) | MIPI_CAL_SEL(0x1) | + MIPI_CAL_HSPDOS(0x0) | MIPI_CAL_HSPUOS(0x4) | + MIPI_CAL_TERMOS(0x5); + writel(value, >mipi->mipi_cal_config_dsia); + writel(value, >mipi->mipi_cal_config_dsib); + + /* Deselect PAD C */ + value = readl(>mipi->mipi_cal_config_dsic); + value &= ~(MIPI_CAL_SEL(0x1)); + writel(value, >mipi->mipi_cal_config_dsic); + + /* Deselect PAD D */ + value = readl(>mipi->mipi_cal_config_dsid); + value &= ~(MIPI_CAL_SEL(0x1)); + writel(value, >mipi->mipi_cal_config_dsid); + + value = readl(>mipi->mipi_cal_ctrl); + value &= ~MIPI_CAL_CTRL_NOISE_FILTER(0xf); + value &= ~MIPI_CAL_CTRL_PRESCALE(0x3); + value |= MIPI_CAL_CTRL_NOISE_FILTER(0xa) | +MIPI_CAL_CTRL_PRESCALE(0x2) | +MIPI_CAL_CTRL_CLKEN_OVR; + writel(value, >mipi->mipi_cal_ctrl); + + /* clear any pending status bits */ + value = readl(>mipi->mipi_cal_status); + writel(value, >mipi->mipi_cal_
[PATCH v6 12/18] video: tegra20: dc: parameterize V- and H-sync polarities
Based on Thierry Reding's Linux commit: 'commit 1716b1891e1de05e2c20ccafa9f58550f3539717 ("drm/tegra: rgb: Parameterize V- and H-sync polarities")' Signed-off-by: Svyatoslav Ryhel --- arch/arm/include/asm/arch-tegra/dc.h | 5 + drivers/video/tegra20/tegra-dc.c | 22 -- 2 files changed, 25 insertions(+), 2 deletions(-) diff --git a/arch/arm/include/asm/arch-tegra/dc.h b/arch/arm/include/asm/arch-tegra/dc.h index 6444af2993..ca3718411a 100644 --- a/arch/arm/include/asm/arch-tegra/dc.h +++ b/arch/arm/include/asm/arch-tegra/dc.h @@ -443,6 +443,11 @@ enum win_color_depth_id { #defineWINDOW_D_SELECT BIT(7) #defineWINDOW_H_SELECT BIT(8) +/* DC_COM_PIN_OUTPUT_POLARITY1 0x307 */ +#define LHS_OUTPUT_POLARITY_LOWBIT(30) +#define LVS_OUTPUT_POLARITY_LOWBIT(28) +#define LSC0_OUTPUT_POLARITY_LOW BIT(24) + /* DC_DISP_DISP_WIN_OPTIONS 0x402 */ #defineCURSOR_ENABLE BIT(16) #defineSOR_ENABLE BIT(25) diff --git a/drivers/video/tegra20/tegra-dc.c b/drivers/video/tegra20/tegra-dc.c index caeec94468..ffa81eeac3 100644 --- a/drivers/video/tegra20/tegra-dc.c +++ b/drivers/video/tegra20/tegra-dc.c @@ -220,8 +220,11 @@ static const u32 rgb_sel_tab[PIN_OUTPUT_SEL_COUNT] = { 0x0002, }; -static void rgb_enable(struct dc_com_reg *com) +static void rgb_enable(struct tegra_lcd_priv *priv) { + struct dc_com_reg *com = >dc->com; + struct display_timing *dt = >timing; + u32 value; int i; for (i = 0; i < PIN_REG_COUNT; i++) { @@ -230,6 +233,21 @@ static void rgb_enable(struct dc_com_reg *com) writel(rgb_data_tab[i], >pin_output_data[i]); } + /* configure H- and V-sync signal polarities */ + value = readl(>pin_output_polarity[1]); + + if (dt->flags & DISPLAY_FLAGS_HSYNC_LOW) + value |= LHS_OUTPUT_POLARITY_LOW; + else + value &= ~LHS_OUTPUT_POLARITY_LOW; + + if (dt->flags & DISPLAY_FLAGS_VSYNC_LOW) + value |= LVS_OUTPUT_POLARITY_LOW; + else + value &= ~LVS_OUTPUT_POLARITY_LOW; + + writel(value, >pin_output_polarity[1]); + for (i = 0; i < PIN_OUTPUT_SEL_COUNT; i++) writel(rgb_sel_tab[i], >pin_output_sel[i]); } @@ -329,7 +347,7 @@ static int tegra_display_probe(struct tegra_lcd_priv *priv, basic_init_timer(>dc->disp); if (priv->soc->has_rgb) - rgb_enable(>dc->com); + rgb_enable(priv); if (priv->pixel_clock) update_display_mode(priv); -- 2.40.1
[PATCH v6 11/18] video: tegra20: dc: clean framebuffer memory block
From: Jonas Schwöbel Fill the framebuffer memory with zeros to avoid visual glitches. Signed-off-by: Jonas Schwöbel Signed-off-by: Svyatoslav Ryhel --- drivers/video/tegra20/tegra-dc.c | 5 + 1 file changed, 5 insertions(+) diff --git a/drivers/video/tegra20/tegra-dc.c b/drivers/video/tegra20/tegra-dc.c index ac6833229a..caeec94468 100644 --- a/drivers/video/tegra20/tegra-dc.c +++ b/drivers/video/tegra20/tegra-dc.c @@ -4,6 +4,7 @@ */ #include +#include #include #include #include @@ -398,6 +399,10 @@ static int tegra_lcd_probe(struct udevice *dev) priv->scdiv = dc_plat->scdiv; } + /* Clean the framebuffer area */ + memset((u8 *)plat->base, 0, plat->size); + flush_dcache_all(); + if (tegra_display_probe(priv, (void *)plat->base)) { debug("%s: Failed to probe display driver\n", __func__); return -1; -- 2.40.1
[PATCH v6 10/18] video: tegra20: dc: enable backlight after DC is configured
From: Jonas Schwöbel The goal of panel_set_backlight() is to enable backlight. Hence, it should be called at the probe end. Signed-off-by: Jonas Schwöbel Signed-off-by: Svyatoslav Ryhel --- drivers/video/tegra20/tegra-dc.c | 8 +--- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/drivers/video/tegra20/tegra-dc.c b/drivers/video/tegra20/tegra-dc.c index 000a0e02f8..ac6833229a 100644 --- a/drivers/video/tegra20/tegra-dc.c +++ b/drivers/video/tegra20/tegra-dc.c @@ -414,12 +414,6 @@ static int tegra_lcd_probe(struct udevice *dev) return ret; } - ret = panel_set_backlight(priv->panel, BACKLIGHT_DEFAULT); - if (ret) { - debug("%s: Cannot set backlight to default, ret=%d\n", __func__, ret); - return ret; - } - mmu_set_region_dcache_behaviour(priv->frame_buffer, plat->size, DCACHE_WRITETHROUGH); @@ -432,7 +426,7 @@ static int tegra_lcd_probe(struct udevice *dev) debug("LCD frame buffer at %08x, size %x\n", priv->frame_buffer, plat->size); - return 0; + return panel_set_backlight(priv->panel, BACKLIGHT_DEFAULT); } static int tegra_lcd_of_to_plat(struct udevice *dev) -- 2.40.1
[PATCH v6 09/18] video: tegra20: dc: fix printing of framebuffer address
From: Jonas Schwöbel Framebuffer address should not be a pointer. Signed-off-by: Jonas Schwöbel 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 a8e32e6893..000a0e02f8 100644 --- a/drivers/video/tegra20/tegra-dc.c +++ b/drivers/video/tegra20/tegra-dc.c @@ -429,7 +429,7 @@ static int tegra_lcd_probe(struct udevice *dev) uc_priv->xsize = priv->width; uc_priv->ysize = priv->height; uc_priv->bpix = priv->log2_bpp; - debug("LCD frame buffer at %pa, size %x\n", >frame_buffer, + debug("LCD frame buffer at %08x, size %x\n", priv->frame_buffer, plat->size); return 0; -- 2.40.1
[PATCH v6 08/18] video: tegra20: dc: configure behavior if PLLD/D2 is used
If DISP1 is a PLLD/D2 child, it cannot go over 370MHz. The cause of this is not quite clear. This can be overcomed by further halving the PLLD/D2 if the target parent rate is over 800MHz. This way DISP1 and DSI clocks will have the same frequency. The shift divider in this case has to be calculated from the original PLLD/D2 frequency and is passed from the DSI driver. Tested-by: Andreas Westman Dorcsak # ASUS Grouper E1565 Tested-by: Ion Agorria # HTC One X Tested-by: Svyatoslav Ryhel # Nvidia Tegratab T114 Tested-by: Jonas Schwöbel # Microsoft Surface 2 Signed-off-by: Jonas Schwöbel Signed-off-by: Svyatoslav Ryhel --- drivers/video/tegra20/tegra-dc.c | 34 +++ drivers/video/tegra20/tegra-dc.h | 1 + drivers/video/tegra20/tegra-dsi.c | 14 + 3 files changed, 36 insertions(+), 13 deletions(-) diff --git a/drivers/video/tegra20/tegra-dc.c b/drivers/video/tegra20/tegra-dc.c index 9a18e38cd8..a8e32e6893 100644 --- a/drivers/video/tegra20/tegra-dc.c +++ b/drivers/video/tegra20/tegra-dc.c @@ -48,6 +48,7 @@ struct tegra_lcd_priv { fdt_addr_t frame_buffer;/* Address of frame buffer */ unsigned pixel_clock; /* Pixel clock in Hz */ int dc_clk[2]; /* Contains clk and its parent */ + ulong scdiv;/* Clock divider used by disp_clk_ctrl */ bool rotation; /* 180 degree panel turn */ bool pipe; /* DC controller: 0 for A, 1 for B */ }; @@ -126,8 +127,6 @@ static int update_display_mode(struct tegra_lcd_priv *priv) struct dc_disp_reg *disp = >dc->disp; struct display_timing *dt = >timing; unsigned long val; - unsigned long rate; - unsigned long div; writel(0x0, >disp_timing_opt); @@ -150,21 +149,11 @@ static int update_display_mode(struct tegra_lcd_priv *priv) writel(val, >disp_interface_ctrl); } - /* -* The pixel clock divider is in 7.1 format (where the bottom bit -* represents 0.5). Here we calculate the divider needed to get from -* the display clock (typically 600MHz) to the pixel clock. We round -* up or down as requried. -*/ - rate = clock_get_periph_rate(priv->dc_clk[0], priv->dc_clk[1]); - div = ((rate * 2 + priv->pixel_clock / 2) / priv->pixel_clock) - 2; - debug("Display clock %lu, divider %lu\n", rate, div); - if (priv->soc->has_rgb) writel(0x00010001, >shift_clk_opt); val = PIXEL_CLK_DIVIDER_PCD1 << PIXEL_CLK_DIVIDER_SHIFT; - val |= div << SHIFT_CLK_DIVIDER_SHIFT; + val |= priv->scdiv << SHIFT_CLK_DIVIDER_SHIFT; writel(val, >disp_clk_ctrl); return 0; @@ -314,6 +303,17 @@ static int tegra_display_probe(struct tegra_lcd_priv *priv, rate /= 2; #endif + /* +* The pixel clock divider is in 7.1 format (where the bottom bit +* represents 0.5). Here we calculate the divider needed to get from +* the display clock (typically 600MHz) to the pixel clock. We round +* up or down as required. +*/ + if (!priv->scdiv) + priv->scdiv = ((rate * 2 + priv->pixel_clock / 2) + / priv->pixel_clock) - 2; + debug("Display clock %lu, divider %lu\n", rate, priv->scdiv); + /* * HOST1X is init by default at 150MHz with PLLC as parent */ @@ -390,6 +390,14 @@ static int tegra_lcd_probe(struct udevice *dev) reset_deassert(_ctl); mdelay(4); + /* 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); + + priv->scdiv = dc_plat->scdiv; + } + if (tegra_display_probe(priv, (void *)plat->base)) { debug("%s: Failed to probe display driver\n", __func__); return -1; diff --git a/drivers/video/tegra20/tegra-dc.h b/drivers/video/tegra20/tegra-dc.h index 75fc0fa4de..05042dab1c 100644 --- a/drivers/video/tegra20/tegra-dc.h +++ b/drivers/video/tegra20/tegra-dc.h @@ -23,6 +23,7 @@ struct tegra_dc_plat { struct udevice *dev;/* Display controller device */ struct dc_ctlr *dc; /* Display controller regmap */ bool pipe; /* DC number: 0 for A, 1 for B */ + ulong scdiv;/* Shift clock divider */ }; /* This holds information about a window which can be displayed */ diff --git a/drivers/video/tegra20/tegra-dsi.c b/drivers/video/tegra20/tegra-dsi.c index 72b91ed26b..de225ed376 100644 --- a/drivers/video/tegra20/tegra-dsi.c
[PATCH v6 06/18] video: tegra20: dc: add reset support
Implement reset use to discard any changes which could have been applied to DC before and can interfere with current configuration. Tested-by: Agneli # Toshiba AC100 T20 Tested-by: Robert Eckelmann # ASUS TF101 Tested-by: Andreas Westman Dorcsak # ASUS Grouper E1565 Tested-by: Ion Agorria # HTC One X Tested-by: Svyatoslav Ryhel # Nvidia Tegratab T114 Signed-off-by: Svyatoslav Ryhel --- drivers/video/tegra20/tegra-dc.c | 17 + 1 file changed, 17 insertions(+) diff --git a/drivers/video/tegra20/tegra-dc.c b/drivers/video/tegra20/tegra-dc.c index 56a23b3c97..35abb6fe46 100644 --- a/drivers/video/tegra20/tegra-dc.c +++ b/drivers/video/tegra20/tegra-dc.c @@ -10,7 +10,9 @@ #include #include #include +#include #include +#include #include #include #include @@ -342,6 +344,7 @@ static int tegra_lcd_probe(struct udevice *dev) struct video_uc_plat *plat = dev_get_uclass_plat(dev); struct video_priv *uc_priv = dev_get_uclass_priv(dev); struct tegra_lcd_priv *priv = dev_get_priv(dev); + struct reset_ctl reset_ctl; int ret; /* Initialize the Tegra display controller */ @@ -349,6 +352,20 @@ static int tegra_lcd_probe(struct udevice *dev) funcmux_select(PERIPH_ID_DISP1, FUNCMUX_DEFAULT); #endif + ret = reset_get_by_name(dev, "dc", _ctl); + if (ret) { + log_err("reset_get_by_name() failed: %d\n", ret); + return ret; + } + + clock_disable(priv->dc_clk[0]); + + /* Reset everything set before */ + reset_assert(_ctl); + mdelay(4); + reset_deassert(_ctl); + mdelay(4); + if (tegra_display_probe(priv, (void *)plat->base)) { debug("%s: Failed to probe display driver\n", __func__); return -1; -- 2.40.1
[PATCH v6 07/18] video: tegra20: dc: add powergate
Add powergate use on T114 to complete resetting of DC. Signed-off-by: Svyatoslav Ryhel --- drivers/video/tegra20/tegra-dc.c | 27 +++ 1 file changed, 27 insertions(+) diff --git a/drivers/video/tegra20/tegra-dc.c b/drivers/video/tegra20/tegra-dc.c index 35abb6fe46..9a18e38cd8 100644 --- a/drivers/video/tegra20/tegra-dc.c +++ b/drivers/video/tegra20/tegra-dc.c @@ -22,6 +22,7 @@ #include #include #include +#include #include #include "tegra-dc.h" @@ -32,6 +33,7 @@ DECLARE_GLOBAL_DATA_PTR; struct tegra_dc_soc_info { bool has_timer; bool has_rgb; + bool has_pgate; }; /* Information about the display controller */ @@ -360,6 +362,28 @@ static int tegra_lcd_probe(struct udevice *dev) clock_disable(priv->dc_clk[0]); + if (priv->soc->has_pgate) { + uint powergate; + + if (priv->pipe) + powergate = TEGRA_POWERGATE_DISB; + else + powergate = TEGRA_POWERGATE_DIS; + + ret = tegra_powergate_power_off(powergate); + if (ret < 0) { + log_err("failed to power off DISP gate: %d", ret); + return ret; + } + + ret = tegra_powergate_sequence_power_up(powergate, + priv->dc_clk[0]); + if (ret < 0) { + log_err("failed to power up DISP gate: %d", ret); + return ret; + } + } + /* Reset everything set before */ reset_assert(_ctl); mdelay(4); @@ -510,16 +534,19 @@ 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, + .has_pgate = false, }; static const struct tegra_dc_soc_info tegra30_dc_soc_info = { .has_timer = false, .has_rgb = true, + .has_pgate = false, }; static const struct tegra_dc_soc_info tegra114_dc_soc_info = { .has_timer = false, .has_rgb = false, + .has_pgate = true, }; static const struct udevice_id tegra_lcd_ids[] = { -- 2.40.1
[PATCH v6 05/18] video: tegra20: dc: add PLLD2 parent support
T30+ SOC have second PLLD - PLLD2 which can be actively used by DC and act as main DISP1/2 clock parent. Tested-by: Agneli # Toshiba AC100 T20 Tested-by: Robert Eckelmann # ASUS TF101 Tested-by: Andreas Westman Dorcsak # ASUS Grouper E1565 Tested-by: Ion Agorria # HTC One X Tested-by: Svyatoslav Ryhel # Nvidia Tegratab T114 Signed-off-by: Svyatoslav Ryhel --- drivers/video/tegra20/tegra-dc.c | 6 ++ 1 file changed, 6 insertions(+) diff --git a/drivers/video/tegra20/tegra-dc.c b/drivers/video/tegra20/tegra-dc.c index 0e94e665ef..56a23b3c97 100644 --- a/drivers/video/tegra20/tegra-dc.c +++ b/drivers/video/tegra20/tegra-dc.c @@ -304,6 +304,12 @@ static int tegra_display_probe(struct tegra_lcd_priv *priv, if (priv->dc_clk[1] == CLOCK_ID_DISPLAY) rate /= 2; +#ifndef CONFIG_TEGRA20 + /* PLLD2 obeys same rules as PLLD but it is present only on T30+ */ + if (priv->dc_clk[1] == CLOCK_ID_DISPLAY2) + rate /= 2; +#endif + /* * HOST1X is init by default at 150MHz with PLLC as parent */ -- 2.40.1
[PATCH v6 04/18] video: tegra20: dc: pass DC id to internal devices
Tegra SoC has 2 independent display controllers called DC_A and DC_B, they are handled differently by internal video devices like DSI and HDMI controllers so it is important for last to know which display controller is used to properly set up registers. To achieve this, a pipe field was added to pdata to pass display controller id to internal Tegra SoC devices. Tested-by: Agneli # Toshiba AC100 T20 Tested-by: Robert Eckelmann # ASUS TF101 Tested-by: Andreas Westman Dorcsak # ASUS Grouper E1565 Tested-by: Ion Agorria # HTC One X Tested-by: Svyatoslav Ryhel # Nvidia Tegratab T114 Signed-off-by: Svyatoslav Ryhel --- drivers/video/tegra20/tegra-dc.c | 6 ++ drivers/video/tegra20/tegra-dc.h | 3 +++ 2 files changed, 9 insertions(+) diff --git a/drivers/video/tegra20/tegra-dc.c b/drivers/video/tegra20/tegra-dc.c index 5d8874f323..0e94e665ef 100644 --- a/drivers/video/tegra20/tegra-dc.c +++ b/drivers/video/tegra20/tegra-dc.c @@ -45,6 +45,7 @@ struct tegra_lcd_priv { unsigned pixel_clock; /* Pixel clock in Hz */ int dc_clk[2]; /* Contains clk and its parent */ bool rotation; /* 180 degree panel turn */ + bool pipe; /* DC controller: 0 for A, 1 for B */ }; enum { @@ -406,6 +407,9 @@ static int tegra_lcd_of_to_plat(struct udevice *dev) priv->rotation = dev_read_bool(dev, "nvidia,180-rotation"); + if (!strcmp(dev->name, TEGRA_DC_B)) + priv->pipe = 1; + rgb = fdt_subnode_offset(blob, node, "rgb"); if (rgb < 0) { debug("%s: Cannot find rgb subnode for '%s' (ret=%d)\n", @@ -431,12 +435,14 @@ static int tegra_lcd_of_to_plat(struct udevice *dev) return ret; } + /* 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, >timing); diff --git a/drivers/video/tegra20/tegra-dc.h b/drivers/video/tegra20/tegra-dc.h index 5c05221038..75fc0fa4de 100644 --- a/drivers/video/tegra20/tegra-dc.h +++ b/drivers/video/tegra20/tegra-dc.h @@ -14,12 +14,15 @@ /* arch-tegra/dc exists only because T124 uses it */ #include +#define TEGRA_DC_A "dc@5420" +#define TEGRA_DC_B "dc@5424" #define TEGRA_DSI_A"dsi@5430" #define TEGRA_DSI_B"dsi@5440" struct tegra_dc_plat { struct udevice *dev;/* Display controller device */ struct dc_ctlr *dc; /* Display controller regmap */ + bool pipe; /* DC number: 0 for A, 1 for B */ }; /* This holds information about a window which can be displayed */ -- 2.40.1
[PATCH v6 03/18] video: tegra20: consolidate DC header
Consolidate HD headers and place the result into video/tegra20 since it is used only by devices from this directory. Tested-by: Agneli # Toshiba AC100 T20 Tested-by: Robert Eckelmann # ASUS TF101 Tested-by: Andreas Westman Dorcsak # ASUS Grouper E1565 Tested-by: Ion Agorria # HTC One X Tested-by: Svyatoslav Ryhel # Nvidia Tegratab T114 Signed-off-by: Svyatoslav Ryhel --- arch/arm/include/asm/arch-tegra/dc.h | 8 arch/arm/include/asm/arch-tegra114/display.h | 28 - arch/arm/include/asm/arch-tegra20/display.h | 28 - arch/arm/include/asm/arch-tegra30/display.h | 28 - drivers/video/tegra20/tegra-dc.c | 3 +- drivers/video/tegra20/tegra-dc.h | 41 drivers/video/tegra20/tegra-dsi.c| 2 +- drivers/video/tegra20/tegra-pwm-backlight.c | 3 +- 8 files changed, 46 insertions(+), 95 deletions(-) delete mode 100644 arch/arm/include/asm/arch-tegra114/display.h delete mode 100644 arch/arm/include/asm/arch-tegra20/display.h delete mode 100644 arch/arm/include/asm/arch-tegra30/display.h create mode 100644 drivers/video/tegra20/tegra-dc.h diff --git a/arch/arm/include/asm/arch-tegra/dc.h b/arch/arm/include/asm/arch-tegra/dc.h index 7613d84f22..6444af2993 100644 --- a/arch/arm/include/asm/arch-tegra/dc.h +++ b/arch/arm/include/asm/arch-tegra/dc.h @@ -569,12 +569,4 @@ enum { #define DC_N_WINDOWS 5 #define DC_REG_SAVE_SPACE (DC_N_WINDOWS + 5) -#define TEGRA_DSI_A"dsi@5430" -#define TEGRA_DSI_B"dsi@5440" - -struct tegra_dc_plat { - struct udevice *dev;/* Display controller device */ - struct dc_ctlr *dc; /* Display controller regmap */ -}; - #endif /* __ASM_ARCH_TEGRA_DC_H */ diff --git a/arch/arm/include/asm/arch-tegra114/display.h b/arch/arm/include/asm/arch-tegra114/display.h deleted file mode 100644 index 9411525799..00 --- a/arch/arm/include/asm/arch-tegra114/display.h +++ /dev/null @@ -1,28 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ -/* - * (C) Copyright 2010 - * NVIDIA Corporation - */ - -#ifndef __ASM_ARCH_TEGRA_DISPLAY_H -#define __ASM_ARCH_TEGRA_DISPLAY_H - -#include - -/* This holds information about a window which can be displayed */ -struct disp_ctl_win { - enum win_color_depth_id fmt;/* Color depth/format */ - unsigned intbpp;/* Bits per pixel */ - phys_addr_t phys_addr; /* Physical address in memory */ - unsigned intx; /* Horizontal address offset (bytes) */ - unsigned inty; /* Veritical address offset (bytes) */ - unsigned intw; /* Width of source window */ - unsigned inth; /* Height of source window */ - unsigned intstride; /* Number of bytes per line */ - unsigned intout_x; /* Left edge of output window (col) */ - unsigned intout_y; /* Top edge of output window (row) */ - unsigned intout_w; /* Width of output window in pixels */ - unsigned intout_h; /* Height of output window in pixels */ -}; - -#endif /*__ASM_ARCH_TEGRA_DISPLAY_H*/ diff --git a/arch/arm/include/asm/arch-tegra20/display.h b/arch/arm/include/asm/arch-tegra20/display.h deleted file mode 100644 index e7b3cffd46..00 --- a/arch/arm/include/asm/arch-tegra20/display.h +++ /dev/null @@ -1,28 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ -/* - * (C) Copyright 2010 - * NVIDIA Corporation - */ - -#ifndef __ASM_ARCH_TEGRA_DISPLAY_H -#define __ASM_ARCH_TEGRA_DISPLAY_H - -#include - -/* This holds information about a window which can be displayed */ -struct disp_ctl_win { - enum win_color_depth_id fmt;/* Color depth/format */ - unsignedbpp;/* Bits per pixel */ - phys_addr_t phys_addr; /* Physical address in memory */ - unsignedx; /* Horizontal address offset (bytes) */ - unsignedy; /* Veritical address offset (bytes) */ - unsignedw; /* Width of source window */ - unsignedh; /* Height of source window */ - unsignedstride; /* Number of bytes per line */ - unsignedout_x; /* Left edge of output window (col) */ - unsignedout_y; /* Top edge of output window (row) */ - unsignedout_w; /* Width of output window in pixels */ - unsignedout_h; /* Height of output window in pixels */ -}; - -#endif /*__ASM_ARCH_TEGRA_DISPLAY_H*/ diff --git a/arch/arm/include/asm/arch-tegra30/display.h b/arch/arm/include/asm/arch-tegra30/display.h deleted file mode 100644 index 9411525799..00 --- a/arch/arm/include/asm/arch-tegra30/display.h +++ /dev/null @@ -1,28 +0,0 @@ -/* SPDX-License
[PATCH v6 01/18] video: tegra20: dc: diverge DC per-SOC
Diverge DC driver setup to better fit each of supported generations of Tegra SOC. Tested-by: Agneli # Toshiba AC100 T20 Tested-by: Robert Eckelmann # ASUS TF101 Tested-by: Andreas Westman Dorcsak # ASUS Grouper E1565 Tested-by: Ion Agorria # HTC One X Tested-by: Svyatoslav Ryhel # Nvidia Tegratab T114 Signed-off-by: Svyatoslav Ryhel --- arch/arm/dts/tegra114-u-boot.dtsi| 13 +++ arch/arm/dts/tegra114.dtsi | 4 +- arch/arm/dts/tegra30-u-boot.dtsi | 4 + arch/arm/dts/tegra30.dtsi| 2 +- arch/arm/include/asm/arch-tegra114/display.h | 28 + arch/arm/include/asm/arch-tegra114/pwm.h | 13 +++ drivers/video/tegra20/tegra-dc.c | 107 +-- 7 files changed, 133 insertions(+), 38 deletions(-) create mode 100644 arch/arm/include/asm/arch-tegra114/display.h create mode 100644 arch/arm/include/asm/arch-tegra114/pwm.h diff --git a/arch/arm/dts/tegra114-u-boot.dtsi b/arch/arm/dts/tegra114-u-boot.dtsi index 7c11972552..6a02714a25 100644 --- a/arch/arm/dts/tegra114-u-boot.dtsi +++ b/arch/arm/dts/tegra114-u-boot.dtsi @@ -1,3 +1,16 @@ #include #include "tegra-u-boot.dtsi" + +/ { + host1x@5000 { + bootph-all; + dc@5420 { + bootph-all; + }; + + dc@5424 { + bootph-all; + }; + }; +}; diff --git a/arch/arm/dts/tegra114.dtsi b/arch/arm/dts/tegra114.dtsi index 68ee7f3165..250d692f6b 100644 --- a/arch/arm/dts/tegra114.dtsi +++ b/arch/arm/dts/tegra114.dtsi @@ -42,7 +42,7 @@ }; dc@5420 { - compatible = "nvidia,tegra114-dc", "nvidia,tegra20-dc"; + compatible = "nvidia,tegra114-dc"; reg = <0x5420 0x0004>; interrupts = ; clocks = <_car TEGRA114_CLK_DISP1>, @@ -61,7 +61,7 @@ }; dc@5424 { - compatible = "nvidia,tegra114-dc", "nvidia,tegra20-dc"; + compatible = "nvidia,tegra114-dc"; reg = <0x5424 0x0004>; interrupts = ; clocks = <_car TEGRA114_CLK_DISP2>, diff --git a/arch/arm/dts/tegra30-u-boot.dtsi b/arch/arm/dts/tegra30-u-boot.dtsi index 3038227dbe..6a02714a25 100644 --- a/arch/arm/dts/tegra30-u-boot.dtsi +++ b/arch/arm/dts/tegra30-u-boot.dtsi @@ -8,5 +8,9 @@ dc@5420 { bootph-all; }; + + dc@5424 { + bootph-all; + }; }; }; diff --git a/arch/arm/dts/tegra30.dtsi b/arch/arm/dts/tegra30.dtsi index f198bc0edb..1177e2ab1f 100644 --- a/arch/arm/dts/tegra30.dtsi +++ b/arch/arm/dts/tegra30.dtsi @@ -158,7 +158,7 @@ }; dc@5420 { - compatible = "nvidia,tegra30-dc", "nvidia,tegra20-dc"; + compatible = "nvidia,tegra30-dc"; reg = <0x5420 0x0004>; interrupts = ; clocks = <_car TEGRA30_CLK_DISP1>, diff --git a/arch/arm/include/asm/arch-tegra114/display.h b/arch/arm/include/asm/arch-tegra114/display.h new file mode 100644 index 00..9411525799 --- /dev/null +++ b/arch/arm/include/asm/arch-tegra114/display.h @@ -0,0 +1,28 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * (C) Copyright 2010 + * NVIDIA Corporation + */ + +#ifndef __ASM_ARCH_TEGRA_DISPLAY_H +#define __ASM_ARCH_TEGRA_DISPLAY_H + +#include + +/* This holds information about a window which can be displayed */ +struct disp_ctl_win { + enum win_color_depth_id fmt;/* Color depth/format */ + unsigned intbpp;/* Bits per pixel */ + phys_addr_t phys_addr; /* Physical address in memory */ + unsigned intx; /* Horizontal address offset (bytes) */ + unsigned inty; /* Veritical address offset (bytes) */ + unsigned intw; /* Width of source window */ + unsigned inth; /* Height of source window */ + unsigned intstride; /* Number of bytes per line */ + unsigned intout_x; /* Left edge of output window (col) */ + unsigned intout_y; /* Top edge of output window (row) */ + unsigned intout_w; /* Width of output window in pixels */ + unsigned intout_h; /* Height of output window in pixels */ +}; + +#endif /*__ASM_ARCH_TEGRA_DISPLAY_H*/ diff --git a/arch/arm/include/asm/arch-tegra114/pwm.h b/arch/arm/include/asm/arch-tegra114/pwm.h new file mode 100644 index 00..af39151803 --
[PATCH v6 02/18] video: tegra20: dc: fix image shift on rotated panels
Subtracting 1 from x and y fixes image shifting on rotated panels. Tested-by: Robert Eckelmann # ASUS Grouper E1565 Signed-off-by: Svyatoslav Ryhel --- drivers/video/tegra20/tegra-dc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/video/tegra20/tegra-dc.c b/drivers/video/tegra20/tegra-dc.c index 7605e77bc1..bcc2748623 100644 --- a/drivers/video/tegra20/tegra-dc.c +++ b/drivers/video/tegra20/tegra-dc.c @@ -242,8 +242,8 @@ static int setup_window(struct tegra_lcd_priv *priv, struct disp_ctl_win *win) { if (priv->rotation) { - win->x = priv->width * 2; - win->y = priv->height; + win->x = priv->width * 2 - 1; + win->y = priv->height - 1; } else { win->x = 0; win->y = 0; -- 2.40.1
[PATCH v6 00/18] Add T114 video support
T114 is not that different from T30 and all T30 drivers will work on T114 as well with some adjustments. Patches propose general improvements for existing Tegra DC and DSI drivers as well Tegra 114 video support (experimentl). Commits pass buildman for tegra. --- Changes from v5: - backlight enable moved to the last step of setup for DSI - parameterized V- and H-sync polarities - added framebuffer clearing on probe to avoid glitches - backlight enable moved after DC is fully configured - fixed printing framebuffer pointer instead of address - moved scdiv calculation to tegra DSI if it is used Changes from v4: - fixed typo in max rate to be divided (400KHz > 400MHz) Changes from v3: - fixed the clock divider calculation if PLLD/D2 is used - removed unnecessary pre-configuration - set correct video FIFO depth for DSI Changes from v2: - fixed image distortion on devices with 180deg rotation Changes from v1: - reworked patchset entirely - diverged DC configuration per-SOC - consolidated dc headers from different SOC gen - initial support of DC detection (tegra has 2 DC) - added PLLD2 support, resets and powergating - added T114+ MIPI calibration - added DSI detection (tegra has 2 DSI) and resets --- Jonas Schwöbel (6): video: tegra20: dc: fix printing of framebuffer address video: tegra20: dc: enable backlight after DC is configured video: tegra20: dc: clean framebuffer memory block video: tegra20: dsi: remove pre-configuration video: tegra20: dsi: set correct fifo depth video: tegra20: dsi: use set_backlight for backlight only Svyatoslav Ryhel (12): video: tegra20: dc: diverge DC per-SOC video: tegra20: dc: fix image shift on rotated panels video: tegra20: consolidate DC header video: tegra20: dc: pass DC id to internal devices video: tegra20: dc: add PLLD2 parent support video: tegra20: dc: add reset support video: tegra20: dc: add powergate video: tegra20: dc: configure behavior if PLLD/D2 is used video: tegra20: dc: parameterize V- and H-sync polarities video: tegra20: add MIPI calibration driver video: tegra20: dsi: add T114 support video: tegra20: dsi: add reset support arch/arm/dts/tegra114-u-boot.dtsi | 13 + arch/arm/dts/tegra114.dtsi| 4 +- arch/arm/dts/tegra30-u-boot.dtsi | 4 + arch/arm/dts/tegra30.dtsi | 2 +- arch/arm/include/asm/arch-tegra/dc.h | 13 +- arch/arm/include/asm/arch-tegra114/pwm.h | 13 + arch/arm/include/asm/arch-tegra20/display.h | 28 -- arch/arm/include/asm/arch-tegra30/display.h | 28 -- drivers/video/tegra20/Makefile| 2 +- drivers/video/tegra20/tegra-dc.c | 239 +- drivers/video/tegra20/tegra-dc.h | 45 drivers/video/tegra20/tegra-dsi.c | 122 - .../video/tegra20/tegra-dsi.h | 24 +- drivers/video/tegra20/tegra-mipi.c| 188 ++ drivers/video/tegra20/tegra-pwm-backlight.c | 3 +- 15 files changed, 583 insertions(+), 145 deletions(-) create mode 100644 arch/arm/include/asm/arch-tegra114/pwm.h delete mode 100644 arch/arm/include/asm/arch-tegra20/display.h delete mode 100644 arch/arm/include/asm/arch-tegra30/display.h create mode 100644 drivers/video/tegra20/tegra-dc.h rename arch/arm/include/asm/arch-tegra30/dsi.h => drivers/video/tegra20/tegra-dsi.h (90%) create mode 100644 drivers/video/tegra20/tegra-mipi.c -- 2.40.1
[PATCH v5 13/13] video: tegra20: dsi: set correct fifo depth
From: Jonas Schwöbel According to Thierry Reding's commit in the linux kernel 976cebc35bed0456a42bf96073a26f251d23b264 "drm/tegra: dsi: Make FIFO depths host parameters" correct depth of the video FIFO is 1920 *words* no *bytes* Tested-by: Ion Agorria # HTC One X Tested-by: Svyatoslav Ryhel # Nvidia Tegratab T114 Signed-off-by: Jonas Schwöbel Signed-off-by: Svyatoslav Ryhel --- drivers/video/tegra20/tegra-dsi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/video/tegra20/tegra-dsi.c b/drivers/video/tegra20/tegra-dsi.c index e60a1d2ac4..4bd1ca7280 100644 --- a/drivers/video/tegra20/tegra-dsi.c +++ b/drivers/video/tegra20/tegra-dsi.c @@ -859,7 +859,7 @@ static int tegra_dsi_bridge_probe(struct udevice *dev) return -EINVAL; } - priv->video_fifo_depth = 480; + priv->video_fifo_depth = 1920; priv->host_fifo_depth = 64; ret = reset_get_by_name(dev, "dsi", _ctl); -- 2.40.1
[PATCH v5 11/13] video: tegra20: dsi: add reset support
Implement reset use to discard any changes which could have been applied to DSI before and can interfere with current configuration. Tested-by: Ion Agorria # HTC One X Tested-by: Svyatoslav Ryhel # Nvidia Tegratab T114 Signed-off-by: Svyatoslav Ryhel --- drivers/video/tegra20/tegra-dsi.c | 14 ++ 1 file changed, 14 insertions(+) diff --git a/drivers/video/tegra20/tegra-dsi.c b/drivers/video/tegra20/tegra-dsi.c index f4743e8458..6408026808 100644 --- a/drivers/video/tegra20/tegra-dsi.c +++ b/drivers/video/tegra20/tegra-dsi.c @@ -12,6 +12,7 @@ #include #include #include +#include #include #include #include @@ -849,6 +850,7 @@ static int tegra_dsi_bridge_probe(struct udevice *dev) struct tegra_dsi_priv *priv = dev_get_priv(dev); struct mipi_dsi_device *device = >device; struct mipi_dsi_panel_plat *mipi_plat; + struct reset_ctl reset_ctl; int ret; priv->version = dev_get_driver_data(dev); @@ -862,6 +864,13 @@ static int tegra_dsi_bridge_probe(struct udevice *dev) priv->video_fifo_depth = 480; priv->host_fifo_depth = 64; + ret = reset_get_by_name(dev, "dsi", _ctl); + if (ret) { + log_debug("%s: reset_get_by_name() failed: %d\n", + __func__, ret); + return ret; + } + ret = uclass_get_device_by_phandle(UCLASS_REGULATOR, dev, "avdd-dsi-csi-supply", >avdd); if (ret) @@ -900,12 +909,17 @@ static int tegra_dsi_bridge_probe(struct udevice *dev) tegra_dsi_get_format(device->format, >format); + reset_assert(_ctl); + ret = regulator_set_enable_if_allowed(priv->avdd, true); if (ret && ret != -ENOSYS) return ret; tegra_dsi_init_clocks(dev); + mdelay(2); + reset_deassert(_ctl); + return 0; } -- 2.40.1
[PATCH v5 12/13] video: tegra20: dsi: remove pre-configuration
From: Jonas Schwöbel Configuration for DC driver command mode is not required for every panel. Removed. Tested-by: Ion Agorria # HTC One X Tested-by: Svyatoslav Ryhel # Nvidia Tegratab T114 Signed-off-by: Jonas Schwöbel Signed-off-by: Svyatoslav Ryhel --- drivers/video/tegra20/tegra-dsi.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/video/tegra20/tegra-dsi.c b/drivers/video/tegra20/tegra-dsi.c index 6408026808..e60a1d2ac4 100644 --- a/drivers/video/tegra20/tegra-dsi.c +++ b/drivers/video/tegra20/tegra-dsi.c @@ -766,8 +766,6 @@ static int tegra_dsi_encoder_enable(struct udevice *dev) if (ret) return ret; - tegra_dsi_configure(dev, 0); - ret = panel_set_backlight(priv->panel, BACKLIGHT_DEFAULT); if (ret) return ret; -- 2.40.1
[PATCH v5 10/13] video: tegra20: dsi: add T114 support
Existing Tegra DSI driver mostly fits T114 apart MIPI calibration which on T114 has dedicated driver. To resolve this MIPI calibration logic was split for pre-T114 and T114+ devices. Tested-by: Ion Agorria # HTC One X Tested-by: Svyatoslav Ryhel # Nvidia Tegratab T114 Signed-off-by: Svyatoslav Ryhel --- drivers/video/tegra20/tegra-dsi.c | 78 ++- .../video/tegra20/tegra-dsi.h | 24 +- 2 files changed, 96 insertions(+), 6 deletions(-) rename arch/arm/include/asm/arch-tegra30/dsi.h => drivers/video/tegra20/tegra-dsi.h (90%) diff --git a/drivers/video/tegra20/tegra-dsi.c b/drivers/video/tegra20/tegra-dsi.c index 72b91ed26b..f4743e8458 100644 --- a/drivers/video/tegra20/tegra-dsi.c +++ b/drivers/video/tegra20/tegra-dsi.c @@ -20,17 +20,24 @@ #include #include #include -#include #include "tegra-dc.h" +#include "tegra-dsi.h" #include "mipi-phy.h" +/* List of supported DSI bridges */ +enum { + DSI_V0, + DSI_V1, +}; + struct tegra_dsi_priv { struct mipi_dsi_host host; struct mipi_dsi_device device; struct mipi_dphy_timing dphy_timing; struct udevice *panel; + struct udevice *mipi; struct display_timing timing; struct dsi_ctlr *dsi; @@ -41,6 +48,8 @@ struct tegra_dsi_priv { int dsi_clk; int video_fifo_depth; int host_fifo_depth; + + u32 version; }; static void tegra_dc_enable_controller(struct udevice *dev) @@ -501,6 +510,41 @@ static void tegra_dsi_pad_calibrate(struct dsi_pad_ctrl_reg *pad) writel(value, TEGRA_VI_BASE + (CSI_CIL_PAD_CONFIG << 2)); } +static void tegra_dsi_mipi_calibrate(struct tegra_dsi_priv *priv) +{ + struct dsi_pad_ctrl_reg *pad = >dsi->pad; + u32 value; + int ret; + + ret = misc_set_enabled(priv->mipi, true); + if (ret) + log_debug("%s: failed to enable MIPI calibration: %d\n", + __func__, ret); + + writel(0, >pad_ctrl); + writel(0, >pad_ctrl_1); + writel(0, >pad_ctrl_2); + writel(0, >pad_ctrl_3); + writel(0, >pad_ctrl_4); + + /* DSI pad enable */ + value = DSI_PAD_CONTROL_VS1_PULLDN(0) | DSI_PAD_CONTROL_VS1_PDIO(0); + writel(value, >pad_ctrl); + + value = DSI_PAD_SLEW_UP(0x7) | DSI_PAD_SLEW_DN(0x7) | + DSI_PAD_LP_UP(0x1) | DSI_PAD_LP_DN(0x1) | + DSI_PAD_OUT_CLK(0x0); + writel(value, >pad_ctrl_2); + + value = DSI_PAD_PREEMP_PD_CLK(0x3) | DSI_PAD_PREEMP_PU_CLK(0x3) | + DSI_PAD_PREEMP_PD(0x03) | DSI_PAD_PREEMP_PU(0x3); + writel(value, >pad_ctrl_3); + + ret = misc_write(priv->mipi, 0, NULL, 0); + if (ret) + log_debug("%s: MIPI calibration failed %d\n", __func__, ret); +} + static void tegra_dsi_set_timeout(struct dsi_timeout_reg *rtimeout, unsigned long bclk, unsigned int vrefresh) @@ -664,10 +708,25 @@ static int tegra_dsi_encoder_enable(struct udevice *dev) u32 value; int ret; + /* If for some reasone DSI is enabled then it needs to +* be disabled in order for the panel initialization +* commands to be properly sent. +*/ + value = readl(>dsi_pwr_ctrl); + + if (value & DSI_POWER_CONTROL_ENABLE) { + value = readl(>dsi_pwr_ctrl); + value &= ~DSI_POWER_CONTROL_ENABLE; + writel(value, >dsi_pwr_ctrl); + } + /* Disable interrupt */ writel(0, >int_enable); - tegra_dsi_pad_calibrate(>dsi->pad); + if (priv->version) + tegra_dsi_mipi_calibrate(priv); + else + tegra_dsi_pad_calibrate(>dsi->pad); tegra_dsi_get_muldiv(device->format, , ); @@ -792,6 +851,8 @@ static int tegra_dsi_bridge_probe(struct udevice *dev) struct mipi_dsi_panel_plat *mipi_plat; int ret; + priv->version = dev_get_driver_data(dev); + priv->dsi = (struct dsi_ctlr *)dev_read_addr_ptr(dev); if (!priv->dsi) { printf("%s: No display controller address\n", __func__); @@ -814,6 +875,16 @@ static int tegra_dsi_bridge_probe(struct udevice *dev) return log_ret(ret); } + if (priv->version) { + ret = uclass_get_device_by_phandle(UCLASS_MISC, dev, + "nvidia,mipi-calibrate", + >mipi); + if (ret) { + log_debug("%s: cannot get MIPI: error %d\n", __func__, ret); + return ret; + } + } + panel_get_display_timing(priv->panel, >timing)
[PATCH v5 08/13] video: tegra20: dc: fix the clock divider calculation if PLLD/D2 is used
If DISP1 is a PLLD/D2 child, it cannot go over 370MHz. The cause of this is not quite clear. This can be overcomed by further halving the DISP1 clock if its parent is PLLD/D2 and the target rate is > 400MHz. Tested-by: Andreas Westman Dorcsak # ASUS Grouper E1565 Tested-by: Ion Agorria # HTC One X Tested-by: Svyatoslav Ryhel # Nvidia Tegratab T114 Tested-by: Jonas Schwöbel # Microsoft Surface 2 Signed-off-by: Jonas Schwöbel Signed-off-by: Svyatoslav Ryhel --- drivers/video/tegra20/tegra-dc.c | 41 ++-- 1 file changed, 28 insertions(+), 13 deletions(-) diff --git a/drivers/video/tegra20/tegra-dc.c b/drivers/video/tegra20/tegra-dc.c index 9a18e38cd8..999651aecb 100644 --- a/drivers/video/tegra20/tegra-dc.c +++ b/drivers/video/tegra20/tegra-dc.c @@ -48,6 +48,7 @@ struct tegra_lcd_priv { fdt_addr_t frame_buffer;/* Address of frame buffer */ unsigned pixel_clock; /* Pixel clock in Hz */ int dc_clk[2]; /* Contains clk and its parent */ + ulong clk_div; /* Clock divider used by disp_clk_ctrl */ bool rotation; /* 180 degree panel turn */ bool pipe; /* DC controller: 0 for A, 1 for B */ }; @@ -126,8 +127,6 @@ static int update_display_mode(struct tegra_lcd_priv *priv) struct dc_disp_reg *disp = >dc->disp; struct display_timing *dt = >timing; unsigned long val; - unsigned long rate; - unsigned long div; writel(0x0, >disp_timing_opt); @@ -150,21 +149,11 @@ static int update_display_mode(struct tegra_lcd_priv *priv) writel(val, >disp_interface_ctrl); } - /* -* The pixel clock divider is in 7.1 format (where the bottom bit -* represents 0.5). Here we calculate the divider needed to get from -* the display clock (typically 600MHz) to the pixel clock. We round -* up or down as requried. -*/ - rate = clock_get_periph_rate(priv->dc_clk[0], priv->dc_clk[1]); - div = ((rate * 2 + priv->pixel_clock / 2) / priv->pixel_clock) - 2; - debug("Display clock %lu, divider %lu\n", rate, div); - if (priv->soc->has_rgb) writel(0x00010001, >shift_clk_opt); val = PIXEL_CLK_DIVIDER_PCD1 << PIXEL_CLK_DIVIDER_SHIFT; - val |= div << SHIFT_CLK_DIVIDER_SHIFT; + val |= priv->clk_div << SHIFT_CLK_DIVIDER_SHIFT; writel(val, >disp_clk_ctrl); return 0; @@ -314,6 +303,32 @@ static int tegra_display_probe(struct tegra_lcd_priv *priv, rate /= 2; #endif + /* +* The pixel clock divider is in 7.1 format (where the bottom bit +* represents 0.5). Here we calculate the divider needed to get from +* the display clock (typically 600MHz) to the pixel clock. We round +* up or down as required. +*/ + priv->clk_div = ((rate * 2 + priv->pixel_clock / 2) + / priv->pixel_clock) - 2; + debug("Display clock %lu, divider %lu\n", rate, priv->clk_div); + + /* +* BUG: If DISP1 is a PLLD/D2 child, it cannot go over 370MHz. The +* cause of this is not quite clear. This can be overcomed by +* further halving the DISP1 clock if its parent is PLLD/D2 and +* the target rate is > 400MHz. +*/ + if (priv->dc_clk[1] == CLOCK_ID_DISPLAY) + if (rate > 4) + rate /= 2; + +#ifndef CONFIG_TEGRA20 + if (priv->dc_clk[1] == CLOCK_ID_DISPLAY2) + if (rate > 4) + rate /= 2; +#endif + /* * HOST1X is init by default at 150MHz with PLLC as parent */ -- 2.40.1
[PATCH v5 09/13] video: tegra20: add MIPI calibration driver
Dedicated MIPI calibration driver is used on T114 and newer. Before T114 MIPI calibration registers were part of VI and CSI. Tested-by: Svyatoslav Ryhel # Nvidia Tegratab T114 Signed-off-by: Svyatoslav Ryhel --- drivers/video/tegra20/Makefile | 2 +- drivers/video/tegra20/tegra-mipi.c | 188 + 2 files changed, 189 insertions(+), 1 deletion(-) create mode 100644 drivers/video/tegra20/tegra-mipi.c diff --git a/drivers/video/tegra20/Makefile b/drivers/video/tegra20/Makefile index f0b534c579..a75aea2a87 100644 --- a/drivers/video/tegra20/Makefile +++ b/drivers/video/tegra20/Makefile @@ -1,5 +1,5 @@ # SPDX-License-Identifier: GPL-2.0+ obj-$(CONFIG_VIDEO_TEGRA20) += tegra-dc.o -obj-$(CONFIG_VIDEO_DSI_TEGRA30) += tegra-dsi.o mipi-phy.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-mipi.c b/drivers/video/tegra20/tegra-mipi.c new file mode 100644 index 00..2df3c1a994 --- /dev/null +++ b/drivers/video/tegra20/tegra-mipi.c @@ -0,0 +1,188 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2013 NVIDIA Corporation + * Copyright (c) 2023 Svyatoslav Ryhel + */ + +#include +#include +#include +#include +#include + +#include + +/* MIPI control registers 0x00 ~ 0x60 */ +struct mipi_ctlr { + uint mipi_cal_ctrl; + uint mipi_cal_autocal_ctrl; + uint mipi_cal_status; + + uint unused1[2]; + + uint mipi_cal_config_csia; + uint mipi_cal_config_csib; + uint mipi_cal_config_csic; + uint mipi_cal_config_csid; + uint mipi_cal_config_csie; + + uint unused2[4]; + + uint mipi_cal_config_dsia; + uint mipi_cal_config_dsib; + uint mipi_cal_config_dsic; + uint mipi_cal_config_dsid; + + uint unused3[4]; + + uint mipi_cal_bias_pad_cfg0; + uint mipi_cal_bias_pad_cfg1; + uint mipi_cal_bias_pad_cfg2; +}; + +#define MIPI_CAL_CTRL_NOISE_FILTER(x) (((x) & 0xf) << 26) +#define MIPI_CAL_CTRL_PRESCALE(x) (((x) & 0x3) << 24) +#define MIPI_CAL_CTRL_CLKEN_OVRBIT(4) +#define MIPI_CAL_CTRL_STARTBIT(0) + +#define MIPI_CAL_STATUS_DONE BIT(16) +#define MIPI_CAL_STATUS_ACTIVE BIT(0) + +#define MIPI_CAL_OVERIDE(x)(((x) & 0x1) << 30) +#define MIPI_CAL_SEL(x)(((x) & 0x1) << 21) +#define MIPI_CAL_HSPDOS(x) (((x) & 0x1f) << 16) +#define MIPI_CAL_HSPUOS(x) (((x) & 0x1f) << 8) +#define MIPI_CAL_TERMOS(x) (((x) & 0x1f) << 0) + +#define MIPI_CAL_BIAS_PAD_PDVCLAMP BIT(1) +#define MIPI_CAL_BIAS_PAD_E_VCLAMP_REF BIT(0) + +#define MIPI_CAL_BIAS_PAD_DRV_DN_REF(x) (((x) & 0x7) << 16) +#define MIPI_CAL_BIAS_PAD_DRV_UP_REF(x) (((x) & 0x7) << 8) + +#define MIPI_CAL_BIAS_PAD_VCLAMP(x)(((x) & 0x7) << 16) +#define MIPI_CAL_BIAS_PAD_VAUXP(x) (((x) & 0x7) << 4) +#define MIPI_CAL_BIAS_PAD_PDVREG BIT(1) + +struct tegra_mipi_priv { + struct mipi_ctlr*mipi; + struct clk *mipi_cal; +}; + +static int tegra_mipi_calibrate(struct udevice *dev, int offset, const void *buf, + int size) +{ + struct tegra_mipi_priv *priv = dev_get_priv(dev); + u32 value; + + value = MIPI_CAL_BIAS_PAD_DRV_DN_REF(0x2) | + MIPI_CAL_BIAS_PAD_DRV_UP_REF(0x0); + writel(value, >mipi->mipi_cal_bias_pad_cfg1); + + value = readl(>mipi->mipi_cal_bias_pad_cfg2); + value &= ~MIPI_CAL_BIAS_PAD_VCLAMP(0x7); + value &= ~MIPI_CAL_BIAS_PAD_VAUXP(0x7); + writel(value, >mipi->mipi_cal_bias_pad_cfg2); + + value = MIPI_CAL_OVERIDE(0x0) | MIPI_CAL_SEL(0x1) | + MIPI_CAL_HSPDOS(0x0) | MIPI_CAL_HSPUOS(0x4) | + MIPI_CAL_TERMOS(0x5); + writel(value, >mipi->mipi_cal_config_dsia); + writel(value, >mipi->mipi_cal_config_dsib); + + /* Deselect PAD C */ + value = readl(>mipi->mipi_cal_config_dsic); + value &= ~(MIPI_CAL_SEL(0x1)); + writel(value, >mipi->mipi_cal_config_dsic); + + /* Deselect PAD D */ + value = readl(>mipi->mipi_cal_config_dsid); + value &= ~(MIPI_CAL_SEL(0x1)); + writel(value, >mipi->mipi_cal_config_dsid); + + value = readl(>mipi->mipi_cal_ctrl); + value &= ~MIPI_CAL_CTRL_NOISE_FILTER(0xf); + value &= ~MIPI_CAL_CTRL_PRESCALE(0x3); + value |= MIPI_CAL_CTRL_NOISE_FILTER(0xa) | +MIPI_CAL_CTRL_PRESCALE(0x2) | +MIPI_CAL_CTRL_CLKEN_OVR; + writel(value, >mipi->mipi_cal_ctrl); + + /* clear any pending status bits */ + value = readl(>mipi->mipi_cal_status); + writel(value, >mipi->mipi_cal_
[PATCH v5 07/13] video: tegra20: dc: add powergate
Add powergate use on T114 to complete resetting of DC. Signed-off-by: Svyatoslav Ryhel --- drivers/video/tegra20/tegra-dc.c | 27 +++ 1 file changed, 27 insertions(+) diff --git a/drivers/video/tegra20/tegra-dc.c b/drivers/video/tegra20/tegra-dc.c index 35abb6fe46..9a18e38cd8 100644 --- a/drivers/video/tegra20/tegra-dc.c +++ b/drivers/video/tegra20/tegra-dc.c @@ -22,6 +22,7 @@ #include #include #include +#include #include #include "tegra-dc.h" @@ -32,6 +33,7 @@ DECLARE_GLOBAL_DATA_PTR; struct tegra_dc_soc_info { bool has_timer; bool has_rgb; + bool has_pgate; }; /* Information about the display controller */ @@ -360,6 +362,28 @@ static int tegra_lcd_probe(struct udevice *dev) clock_disable(priv->dc_clk[0]); + if (priv->soc->has_pgate) { + uint powergate; + + if (priv->pipe) + powergate = TEGRA_POWERGATE_DISB; + else + powergate = TEGRA_POWERGATE_DIS; + + ret = tegra_powergate_power_off(powergate); + if (ret < 0) { + log_err("failed to power off DISP gate: %d", ret); + return ret; + } + + ret = tegra_powergate_sequence_power_up(powergate, + priv->dc_clk[0]); + if (ret < 0) { + log_err("failed to power up DISP gate: %d", ret); + return ret; + } + } + /* Reset everything set before */ reset_assert(_ctl); mdelay(4); @@ -510,16 +534,19 @@ 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, + .has_pgate = false, }; static const struct tegra_dc_soc_info tegra30_dc_soc_info = { .has_timer = false, .has_rgb = true, + .has_pgate = false, }; static const struct tegra_dc_soc_info tegra114_dc_soc_info = { .has_timer = false, .has_rgb = false, + .has_pgate = true, }; static const struct udevice_id tegra_lcd_ids[] = { -- 2.40.1
[PATCH v5 06/13] video: tegra20: dc: add reset support
Implement reset use to discard any changes which could have been applied to DC before and can interfere with current configuration. Tested-by: Agneli # Toshiba AC100 T20 Tested-by: Robert Eckelmann # ASUS TF101 Tested-by: Andreas Westman Dorcsak # ASUS Grouper E1565 Tested-by: Ion Agorria # HTC One X Tested-by: Svyatoslav Ryhel # Nvidia Tegratab T114 Signed-off-by: Svyatoslav Ryhel --- drivers/video/tegra20/tegra-dc.c | 17 + 1 file changed, 17 insertions(+) diff --git a/drivers/video/tegra20/tegra-dc.c b/drivers/video/tegra20/tegra-dc.c index 56a23b3c97..35abb6fe46 100644 --- a/drivers/video/tegra20/tegra-dc.c +++ b/drivers/video/tegra20/tegra-dc.c @@ -10,7 +10,9 @@ #include #include #include +#include #include +#include #include #include #include @@ -342,6 +344,7 @@ static int tegra_lcd_probe(struct udevice *dev) struct video_uc_plat *plat = dev_get_uclass_plat(dev); struct video_priv *uc_priv = dev_get_uclass_priv(dev); struct tegra_lcd_priv *priv = dev_get_priv(dev); + struct reset_ctl reset_ctl; int ret; /* Initialize the Tegra display controller */ @@ -349,6 +352,20 @@ static int tegra_lcd_probe(struct udevice *dev) funcmux_select(PERIPH_ID_DISP1, FUNCMUX_DEFAULT); #endif + ret = reset_get_by_name(dev, "dc", _ctl); + if (ret) { + log_err("reset_get_by_name() failed: %d\n", ret); + return ret; + } + + clock_disable(priv->dc_clk[0]); + + /* Reset everything set before */ + reset_assert(_ctl); + mdelay(4); + reset_deassert(_ctl); + mdelay(4); + if (tegra_display_probe(priv, (void *)plat->base)) { debug("%s: Failed to probe display driver\n", __func__); return -1; -- 2.40.1
[PATCH v5 05/13] video: tegra20: dc: add PLLD2 parent support
T30+ SOC have second PLLD - PLLD2 which can be actively used by DC and act as main DISP1/2 clock parent. Tested-by: Agneli # Toshiba AC100 T20 Tested-by: Robert Eckelmann # ASUS TF101 Tested-by: Andreas Westman Dorcsak # ASUS Grouper E1565 Tested-by: Ion Agorria # HTC One X Tested-by: Svyatoslav Ryhel # Nvidia Tegratab T114 Signed-off-by: Svyatoslav Ryhel --- drivers/video/tegra20/tegra-dc.c | 6 ++ 1 file changed, 6 insertions(+) diff --git a/drivers/video/tegra20/tegra-dc.c b/drivers/video/tegra20/tegra-dc.c index 0e94e665ef..56a23b3c97 100644 --- a/drivers/video/tegra20/tegra-dc.c +++ b/drivers/video/tegra20/tegra-dc.c @@ -304,6 +304,12 @@ static int tegra_display_probe(struct tegra_lcd_priv *priv, if (priv->dc_clk[1] == CLOCK_ID_DISPLAY) rate /= 2; +#ifndef CONFIG_TEGRA20 + /* PLLD2 obeys same rules as PLLD but it is present only on T30+ */ + if (priv->dc_clk[1] == CLOCK_ID_DISPLAY2) + rate /= 2; +#endif + /* * HOST1X is init by default at 150MHz with PLLC as parent */ -- 2.40.1
[PATCH v5 04/13] video: tegra20: dc: pass DC id to internal devices
Tegra SoC has 2 independent display controllers called DC_A and DC_B, they are handled differently by internal video devices like DSI and HDMI controllers so it is important for last to know which display controller is used to properly set up registers. To achieve this, a pipe field was added to pdata to pass display controller id to internal Tegra SoC devices. Tested-by: Agneli # Toshiba AC100 T20 Tested-by: Robert Eckelmann # ASUS TF101 Tested-by: Andreas Westman Dorcsak # ASUS Grouper E1565 Tested-by: Ion Agorria # HTC One X Tested-by: Svyatoslav Ryhel # Nvidia Tegratab T114 Signed-off-by: Svyatoslav Ryhel --- drivers/video/tegra20/tegra-dc.c | 6 ++ drivers/video/tegra20/tegra-dc.h | 3 +++ 2 files changed, 9 insertions(+) diff --git a/drivers/video/tegra20/tegra-dc.c b/drivers/video/tegra20/tegra-dc.c index 5d8874f323..0e94e665ef 100644 --- a/drivers/video/tegra20/tegra-dc.c +++ b/drivers/video/tegra20/tegra-dc.c @@ -45,6 +45,7 @@ struct tegra_lcd_priv { unsigned pixel_clock; /* Pixel clock in Hz */ int dc_clk[2]; /* Contains clk and its parent */ bool rotation; /* 180 degree panel turn */ + bool pipe; /* DC controller: 0 for A, 1 for B */ }; enum { @@ -406,6 +407,9 @@ static int tegra_lcd_of_to_plat(struct udevice *dev) priv->rotation = dev_read_bool(dev, "nvidia,180-rotation"); + if (!strcmp(dev->name, TEGRA_DC_B)) + priv->pipe = 1; + rgb = fdt_subnode_offset(blob, node, "rgb"); if (rgb < 0) { debug("%s: Cannot find rgb subnode for '%s' (ret=%d)\n", @@ -431,12 +435,14 @@ static int tegra_lcd_of_to_plat(struct udevice *dev) return ret; } + /* 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, >timing); diff --git a/drivers/video/tegra20/tegra-dc.h b/drivers/video/tegra20/tegra-dc.h index 5c05221038..75fc0fa4de 100644 --- a/drivers/video/tegra20/tegra-dc.h +++ b/drivers/video/tegra20/tegra-dc.h @@ -14,12 +14,15 @@ /* arch-tegra/dc exists only because T124 uses it */ #include +#define TEGRA_DC_A "dc@5420" +#define TEGRA_DC_B "dc@5424" #define TEGRA_DSI_A"dsi@5430" #define TEGRA_DSI_B"dsi@5440" struct tegra_dc_plat { struct udevice *dev;/* Display controller device */ struct dc_ctlr *dc; /* Display controller regmap */ + bool pipe; /* DC number: 0 for A, 1 for B */ }; /* This holds information about a window which can be displayed */ -- 2.40.1
[PATCH v5 03/13] video: tegra20: consolidate DC header
Consolidate HD headers and place the result into video/tegra20 since it is used only by devices from this directory. Tested-by: Agneli # Toshiba AC100 T20 Tested-by: Robert Eckelmann # ASUS TF101 Tested-by: Andreas Westman Dorcsak # ASUS Grouper E1565 Tested-by: Ion Agorria # HTC One X Tested-by: Svyatoslav Ryhel # Nvidia Tegratab T114 Signed-off-by: Svyatoslav Ryhel --- arch/arm/include/asm/arch-tegra/dc.h | 8 arch/arm/include/asm/arch-tegra114/display.h | 28 - arch/arm/include/asm/arch-tegra20/display.h | 28 - arch/arm/include/asm/arch-tegra30/display.h | 28 - drivers/video/tegra20/tegra-dc.c | 3 +- drivers/video/tegra20/tegra-dc.h | 41 drivers/video/tegra20/tegra-dsi.c| 2 +- drivers/video/tegra20/tegra-pwm-backlight.c | 3 +- 8 files changed, 46 insertions(+), 95 deletions(-) delete mode 100644 arch/arm/include/asm/arch-tegra114/display.h delete mode 100644 arch/arm/include/asm/arch-tegra20/display.h delete mode 100644 arch/arm/include/asm/arch-tegra30/display.h create mode 100644 drivers/video/tegra20/tegra-dc.h diff --git a/arch/arm/include/asm/arch-tegra/dc.h b/arch/arm/include/asm/arch-tegra/dc.h index 7613d84f22..6444af2993 100644 --- a/arch/arm/include/asm/arch-tegra/dc.h +++ b/arch/arm/include/asm/arch-tegra/dc.h @@ -569,12 +569,4 @@ enum { #define DC_N_WINDOWS 5 #define DC_REG_SAVE_SPACE (DC_N_WINDOWS + 5) -#define TEGRA_DSI_A"dsi@5430" -#define TEGRA_DSI_B"dsi@5440" - -struct tegra_dc_plat { - struct udevice *dev;/* Display controller device */ - struct dc_ctlr *dc; /* Display controller regmap */ -}; - #endif /* __ASM_ARCH_TEGRA_DC_H */ diff --git a/arch/arm/include/asm/arch-tegra114/display.h b/arch/arm/include/asm/arch-tegra114/display.h deleted file mode 100644 index 9411525799..00 --- a/arch/arm/include/asm/arch-tegra114/display.h +++ /dev/null @@ -1,28 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ -/* - * (C) Copyright 2010 - * NVIDIA Corporation - */ - -#ifndef __ASM_ARCH_TEGRA_DISPLAY_H -#define __ASM_ARCH_TEGRA_DISPLAY_H - -#include - -/* This holds information about a window which can be displayed */ -struct disp_ctl_win { - enum win_color_depth_id fmt;/* Color depth/format */ - unsigned intbpp;/* Bits per pixel */ - phys_addr_t phys_addr; /* Physical address in memory */ - unsigned intx; /* Horizontal address offset (bytes) */ - unsigned inty; /* Veritical address offset (bytes) */ - unsigned intw; /* Width of source window */ - unsigned inth; /* Height of source window */ - unsigned intstride; /* Number of bytes per line */ - unsigned intout_x; /* Left edge of output window (col) */ - unsigned intout_y; /* Top edge of output window (row) */ - unsigned intout_w; /* Width of output window in pixels */ - unsigned intout_h; /* Height of output window in pixels */ -}; - -#endif /*__ASM_ARCH_TEGRA_DISPLAY_H*/ diff --git a/arch/arm/include/asm/arch-tegra20/display.h b/arch/arm/include/asm/arch-tegra20/display.h deleted file mode 100644 index e7b3cffd46..00 --- a/arch/arm/include/asm/arch-tegra20/display.h +++ /dev/null @@ -1,28 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ -/* - * (C) Copyright 2010 - * NVIDIA Corporation - */ - -#ifndef __ASM_ARCH_TEGRA_DISPLAY_H -#define __ASM_ARCH_TEGRA_DISPLAY_H - -#include - -/* This holds information about a window which can be displayed */ -struct disp_ctl_win { - enum win_color_depth_id fmt;/* Color depth/format */ - unsignedbpp;/* Bits per pixel */ - phys_addr_t phys_addr; /* Physical address in memory */ - unsignedx; /* Horizontal address offset (bytes) */ - unsignedy; /* Veritical address offset (bytes) */ - unsignedw; /* Width of source window */ - unsignedh; /* Height of source window */ - unsignedstride; /* Number of bytes per line */ - unsignedout_x; /* Left edge of output window (col) */ - unsignedout_y; /* Top edge of output window (row) */ - unsignedout_w; /* Width of output window in pixels */ - unsignedout_h; /* Height of output window in pixels */ -}; - -#endif /*__ASM_ARCH_TEGRA_DISPLAY_H*/ diff --git a/arch/arm/include/asm/arch-tegra30/display.h b/arch/arm/include/asm/arch-tegra30/display.h deleted file mode 100644 index 9411525799..00 --- a/arch/arm/include/asm/arch-tegra30/display.h +++ /dev/null @@ -1,28 +0,0 @@ -/* SPDX-License
[PATCH v5 01/13] video: tegra20: dc: diverge DC per-SOC
Diverge DC driver setup to better fit each of supported generations of Tegra SOC. Tested-by: Agneli # Toshiba AC100 T20 Tested-by: Robert Eckelmann # ASUS TF101 Tested-by: Andreas Westman Dorcsak # ASUS Grouper E1565 Tested-by: Ion Agorria # HTC One X Tested-by: Svyatoslav Ryhel # Nvidia Tegratab T114 Signed-off-by: Svyatoslav Ryhel --- arch/arm/dts/tegra114-u-boot.dtsi| 13 +++ arch/arm/dts/tegra114.dtsi | 4 +- arch/arm/dts/tegra30-u-boot.dtsi | 4 + arch/arm/dts/tegra30.dtsi| 2 +- arch/arm/include/asm/arch-tegra114/display.h | 28 + arch/arm/include/asm/arch-tegra114/pwm.h | 13 +++ drivers/video/tegra20/tegra-dc.c | 107 +-- 7 files changed, 133 insertions(+), 38 deletions(-) create mode 100644 arch/arm/include/asm/arch-tegra114/display.h create mode 100644 arch/arm/include/asm/arch-tegra114/pwm.h diff --git a/arch/arm/dts/tegra114-u-boot.dtsi b/arch/arm/dts/tegra114-u-boot.dtsi index 7c11972552..6a02714a25 100644 --- a/arch/arm/dts/tegra114-u-boot.dtsi +++ b/arch/arm/dts/tegra114-u-boot.dtsi @@ -1,3 +1,16 @@ #include #include "tegra-u-boot.dtsi" + +/ { + host1x@5000 { + bootph-all; + dc@5420 { + bootph-all; + }; + + dc@5424 { + bootph-all; + }; + }; +}; diff --git a/arch/arm/dts/tegra114.dtsi b/arch/arm/dts/tegra114.dtsi index 68ee7f3165..250d692f6b 100644 --- a/arch/arm/dts/tegra114.dtsi +++ b/arch/arm/dts/tegra114.dtsi @@ -42,7 +42,7 @@ }; dc@5420 { - compatible = "nvidia,tegra114-dc", "nvidia,tegra20-dc"; + compatible = "nvidia,tegra114-dc"; reg = <0x5420 0x0004>; interrupts = ; clocks = <_car TEGRA114_CLK_DISP1>, @@ -61,7 +61,7 @@ }; dc@5424 { - compatible = "nvidia,tegra114-dc", "nvidia,tegra20-dc"; + compatible = "nvidia,tegra114-dc"; reg = <0x5424 0x0004>; interrupts = ; clocks = <_car TEGRA114_CLK_DISP2>, diff --git a/arch/arm/dts/tegra30-u-boot.dtsi b/arch/arm/dts/tegra30-u-boot.dtsi index 3038227dbe..6a02714a25 100644 --- a/arch/arm/dts/tegra30-u-boot.dtsi +++ b/arch/arm/dts/tegra30-u-boot.dtsi @@ -8,5 +8,9 @@ dc@5420 { bootph-all; }; + + dc@5424 { + bootph-all; + }; }; }; diff --git a/arch/arm/dts/tegra30.dtsi b/arch/arm/dts/tegra30.dtsi index f198bc0edb..1177e2ab1f 100644 --- a/arch/arm/dts/tegra30.dtsi +++ b/arch/arm/dts/tegra30.dtsi @@ -158,7 +158,7 @@ }; dc@5420 { - compatible = "nvidia,tegra30-dc", "nvidia,tegra20-dc"; + compatible = "nvidia,tegra30-dc"; reg = <0x5420 0x0004>; interrupts = ; clocks = <_car TEGRA30_CLK_DISP1>, diff --git a/arch/arm/include/asm/arch-tegra114/display.h b/arch/arm/include/asm/arch-tegra114/display.h new file mode 100644 index 00..9411525799 --- /dev/null +++ b/arch/arm/include/asm/arch-tegra114/display.h @@ -0,0 +1,28 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * (C) Copyright 2010 + * NVIDIA Corporation + */ + +#ifndef __ASM_ARCH_TEGRA_DISPLAY_H +#define __ASM_ARCH_TEGRA_DISPLAY_H + +#include + +/* This holds information about a window which can be displayed */ +struct disp_ctl_win { + enum win_color_depth_id fmt;/* Color depth/format */ + unsigned intbpp;/* Bits per pixel */ + phys_addr_t phys_addr; /* Physical address in memory */ + unsigned intx; /* Horizontal address offset (bytes) */ + unsigned inty; /* Veritical address offset (bytes) */ + unsigned intw; /* Width of source window */ + unsigned inth; /* Height of source window */ + unsigned intstride; /* Number of bytes per line */ + unsigned intout_x; /* Left edge of output window (col) */ + unsigned intout_y; /* Top edge of output window (row) */ + unsigned intout_w; /* Width of output window in pixels */ + unsigned intout_h; /* Height of output window in pixels */ +}; + +#endif /*__ASM_ARCH_TEGRA_DISPLAY_H*/ diff --git a/arch/arm/include/asm/arch-tegra114/pwm.h b/arch/arm/include/asm/arch-tegra114/pwm.h new file mode 100644 index 00..af39151803 --
[PATCH v5 02/13] video: tegra20: dc: fix image shift on rotated panels
Subtracting 1 from x and y fixes image shifting on rotated panels. Tested-by: Robert Eckelmann # ASUS Grouper E1565 Signed-off-by: Svyatoslav Ryhel --- drivers/video/tegra20/tegra-dc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/video/tegra20/tegra-dc.c b/drivers/video/tegra20/tegra-dc.c index 7605e77bc1..bcc2748623 100644 --- a/drivers/video/tegra20/tegra-dc.c +++ b/drivers/video/tegra20/tegra-dc.c @@ -242,8 +242,8 @@ static int setup_window(struct tegra_lcd_priv *priv, struct disp_ctl_win *win) { if (priv->rotation) { - win->x = priv->width * 2; - win->y = priv->height; + win->x = priv->width * 2 - 1; + win->y = priv->height - 1; } else { win->x = 0; win->y = 0; -- 2.40.1
[PATCH v5 00/13] Add T114 video support
T114 is not that different from T30 and all T30 drivers will work on T114 as well with some adjustments. Patches propose general improvements for existing Tegra DC and DSI drivers as well Tegra 114 video support (experimentl). Commits pass buildman for tegra. --- Changes from v4: - fixed typo in max rate to be divided (400KHz > 400MHz) Changes from v3: - fixed the clock divider calculation if PLLD/D2 is used - removed unnecessary pre-configuration - set correct video FIFO depth for DSI Changes from v2: - fixed image distortion on devices with 180deg rotation Changes from v1: - reworked patchset entirely - diverged DC configuration per-SOC - consolidated dc headers from different SOC gen - initial support of DC detection (tegra has 2 DC) - added PLLD2 support, resets and powergating - added T114+ MIPI calibration - added DSI detection (tegra has 2 DSI) and resets --- Jonas Schwöbel (2): video: tegra20: dsi: remove pre-configuration video: tegra20: dsi: set correct fifo depth Svyatoslav Ryhel (11): video: tegra20: dc: diverge DC per-SOC video: tegra20: dc: fix image shift on rotated panels video: tegra20: consolidate DC header video: tegra20: dc: pass DC id to internal devices video: tegra20: dc: add PLLD2 parent support video: tegra20: dc: add reset support video: tegra20: dc: add powergate video: tegra20: dc: fix the clock divider calculation if PLLD/D2 is used video: tegra20: add MIPI calibration driver video: tegra20: dsi: add T114 support video: tegra20: dsi: add reset support arch/arm/dts/tegra114-u-boot.dtsi | 13 ++ arch/arm/dts/tegra114.dtsi| 4 +- arch/arm/dts/tegra30-u-boot.dtsi | 4 + arch/arm/dts/tegra30.dtsi | 2 +- arch/arm/include/asm/arch-tegra/dc.h | 8 - arch/arm/include/asm/arch-tegra114/pwm.h | 13 ++ arch/arm/include/asm/arch-tegra20/display.h | 28 --- arch/arm/include/asm/arch-tegra30/display.h | 28 --- drivers/video/tegra20/Makefile| 2 +- drivers/video/tegra20/tegra-dc.c | 211 +- drivers/video/tegra20/tegra-dc.h | 44 drivers/video/tegra20/tegra-dsi.c | 98 +++- .../video/tegra20/tegra-dsi.h | 24 +- drivers/video/tegra20/tegra-mipi.c| 188 drivers/video/tegra20/tegra-pwm-backlight.c | 3 +- 15 files changed, 540 insertions(+), 130 deletions(-) create mode 100644 arch/arm/include/asm/arch-tegra114/pwm.h delete mode 100644 arch/arm/include/asm/arch-tegra20/display.h delete mode 100644 arch/arm/include/asm/arch-tegra30/display.h create mode 100644 drivers/video/tegra20/tegra-dc.h rename arch/arm/include/asm/arch-tegra30/dsi.h => drivers/video/tegra20/tegra-dsi.h (90%) create mode 100644 drivers/video/tegra20/tegra-mipi.c -- 2.40.1
[PATCH v4 13/13] video: tegra20: dsi: set correct fifo depth
From: Jonas Schwöbel According to Thierry Reding's commit in the linux kernel 976cebc35bed0456a42bf96073a26f251d23b264 "drm/tegra: dsi: Make FIFO depths host parameters" correct depth of the video FIFO is 1920 *words* no *bytes* Tested-by: Ion Agorria # HTC One X Tested-by: Svyatoslav Ryhel # Nvidia Tegratab T114 Signed-off-by: Jonas Schwöbel Signed-off-by: Svyatoslav Ryhel --- drivers/video/tegra20/tegra-dsi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/video/tegra20/tegra-dsi.c b/drivers/video/tegra20/tegra-dsi.c index e60a1d2ac4..4bd1ca7280 100644 --- a/drivers/video/tegra20/tegra-dsi.c +++ b/drivers/video/tegra20/tegra-dsi.c @@ -859,7 +859,7 @@ static int tegra_dsi_bridge_probe(struct udevice *dev) return -EINVAL; } - priv->video_fifo_depth = 480; + priv->video_fifo_depth = 1920; priv->host_fifo_depth = 64; ret = reset_get_by_name(dev, "dsi", _ctl); -- 2.40.1
[PATCH v4 12/13] video: tegra20: dsi: remove pre-configuration
From: Jonas Schwöbel Configuration for DC driver command mode is not required for every panel. Removed. Tested-by: Ion Agorria # HTC One X Tested-by: Svyatoslav Ryhel # Nvidia Tegratab T114 Signed-off-by: Jonas Schwöbel Signed-off-by: Svyatoslav Ryhel --- drivers/video/tegra20/tegra-dsi.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/video/tegra20/tegra-dsi.c b/drivers/video/tegra20/tegra-dsi.c index 6408026808..e60a1d2ac4 100644 --- a/drivers/video/tegra20/tegra-dsi.c +++ b/drivers/video/tegra20/tegra-dsi.c @@ -766,8 +766,6 @@ static int tegra_dsi_encoder_enable(struct udevice *dev) if (ret) return ret; - tegra_dsi_configure(dev, 0); - ret = panel_set_backlight(priv->panel, BACKLIGHT_DEFAULT); if (ret) return ret; -- 2.40.1
[PATCH v4 11/13] video: tegra20: dsi: add reset support
Implement reset use to discard any changes which could have been applied to DSI before and can interfere with current configuration. Tested-by: Ion Agorria # HTC One X Tested-by: Svyatoslav Ryhel # Nvidia Tegratab T114 Signed-off-by: Svyatoslav Ryhel --- drivers/video/tegra20/tegra-dsi.c | 14 ++ 1 file changed, 14 insertions(+) diff --git a/drivers/video/tegra20/tegra-dsi.c b/drivers/video/tegra20/tegra-dsi.c index f4743e8458..6408026808 100644 --- a/drivers/video/tegra20/tegra-dsi.c +++ b/drivers/video/tegra20/tegra-dsi.c @@ -12,6 +12,7 @@ #include #include #include +#include #include #include #include @@ -849,6 +850,7 @@ static int tegra_dsi_bridge_probe(struct udevice *dev) struct tegra_dsi_priv *priv = dev_get_priv(dev); struct mipi_dsi_device *device = >device; struct mipi_dsi_panel_plat *mipi_plat; + struct reset_ctl reset_ctl; int ret; priv->version = dev_get_driver_data(dev); @@ -862,6 +864,13 @@ static int tegra_dsi_bridge_probe(struct udevice *dev) priv->video_fifo_depth = 480; priv->host_fifo_depth = 64; + ret = reset_get_by_name(dev, "dsi", _ctl); + if (ret) { + log_debug("%s: reset_get_by_name() failed: %d\n", + __func__, ret); + return ret; + } + ret = uclass_get_device_by_phandle(UCLASS_REGULATOR, dev, "avdd-dsi-csi-supply", >avdd); if (ret) @@ -900,12 +909,17 @@ static int tegra_dsi_bridge_probe(struct udevice *dev) tegra_dsi_get_format(device->format, >format); + reset_assert(_ctl); + ret = regulator_set_enable_if_allowed(priv->avdd, true); if (ret && ret != -ENOSYS) return ret; tegra_dsi_init_clocks(dev); + mdelay(2); + reset_deassert(_ctl); + return 0; } -- 2.40.1
[PATCH v4 10/13] video: tegra20: dsi: add T114 support
Existing Tegra DSI driver mostly fits T114 apart MIPI calibration which on T114 has dedicated driver. To resolve this MIPI calibration logic was split for pre-T114 and T114+ devices. Tested-by: Ion Agorria # HTC One X Tested-by: Svyatoslav Ryhel # Nvidia Tegratab T114 Signed-off-by: Svyatoslav Ryhel --- drivers/video/tegra20/tegra-dsi.c | 78 ++- .../video/tegra20/tegra-dsi.h | 24 +- 2 files changed, 96 insertions(+), 6 deletions(-) rename arch/arm/include/asm/arch-tegra30/dsi.h => drivers/video/tegra20/tegra-dsi.h (90%) diff --git a/drivers/video/tegra20/tegra-dsi.c b/drivers/video/tegra20/tegra-dsi.c index 72b91ed26b..f4743e8458 100644 --- a/drivers/video/tegra20/tegra-dsi.c +++ b/drivers/video/tegra20/tegra-dsi.c @@ -20,17 +20,24 @@ #include #include #include -#include #include "tegra-dc.h" +#include "tegra-dsi.h" #include "mipi-phy.h" +/* List of supported DSI bridges */ +enum { + DSI_V0, + DSI_V1, +}; + struct tegra_dsi_priv { struct mipi_dsi_host host; struct mipi_dsi_device device; struct mipi_dphy_timing dphy_timing; struct udevice *panel; + struct udevice *mipi; struct display_timing timing; struct dsi_ctlr *dsi; @@ -41,6 +48,8 @@ struct tegra_dsi_priv { int dsi_clk; int video_fifo_depth; int host_fifo_depth; + + u32 version; }; static void tegra_dc_enable_controller(struct udevice *dev) @@ -501,6 +510,41 @@ static void tegra_dsi_pad_calibrate(struct dsi_pad_ctrl_reg *pad) writel(value, TEGRA_VI_BASE + (CSI_CIL_PAD_CONFIG << 2)); } +static void tegra_dsi_mipi_calibrate(struct tegra_dsi_priv *priv) +{ + struct dsi_pad_ctrl_reg *pad = >dsi->pad; + u32 value; + int ret; + + ret = misc_set_enabled(priv->mipi, true); + if (ret) + log_debug("%s: failed to enable MIPI calibration: %d\n", + __func__, ret); + + writel(0, >pad_ctrl); + writel(0, >pad_ctrl_1); + writel(0, >pad_ctrl_2); + writel(0, >pad_ctrl_3); + writel(0, >pad_ctrl_4); + + /* DSI pad enable */ + value = DSI_PAD_CONTROL_VS1_PULLDN(0) | DSI_PAD_CONTROL_VS1_PDIO(0); + writel(value, >pad_ctrl); + + value = DSI_PAD_SLEW_UP(0x7) | DSI_PAD_SLEW_DN(0x7) | + DSI_PAD_LP_UP(0x1) | DSI_PAD_LP_DN(0x1) | + DSI_PAD_OUT_CLK(0x0); + writel(value, >pad_ctrl_2); + + value = DSI_PAD_PREEMP_PD_CLK(0x3) | DSI_PAD_PREEMP_PU_CLK(0x3) | + DSI_PAD_PREEMP_PD(0x03) | DSI_PAD_PREEMP_PU(0x3); + writel(value, >pad_ctrl_3); + + ret = misc_write(priv->mipi, 0, NULL, 0); + if (ret) + log_debug("%s: MIPI calibration failed %d\n", __func__, ret); +} + static void tegra_dsi_set_timeout(struct dsi_timeout_reg *rtimeout, unsigned long bclk, unsigned int vrefresh) @@ -664,10 +708,25 @@ static int tegra_dsi_encoder_enable(struct udevice *dev) u32 value; int ret; + /* If for some reasone DSI is enabled then it needs to +* be disabled in order for the panel initialization +* commands to be properly sent. +*/ + value = readl(>dsi_pwr_ctrl); + + if (value & DSI_POWER_CONTROL_ENABLE) { + value = readl(>dsi_pwr_ctrl); + value &= ~DSI_POWER_CONTROL_ENABLE; + writel(value, >dsi_pwr_ctrl); + } + /* Disable interrupt */ writel(0, >int_enable); - tegra_dsi_pad_calibrate(>dsi->pad); + if (priv->version) + tegra_dsi_mipi_calibrate(priv); + else + tegra_dsi_pad_calibrate(>dsi->pad); tegra_dsi_get_muldiv(device->format, , ); @@ -792,6 +851,8 @@ static int tegra_dsi_bridge_probe(struct udevice *dev) struct mipi_dsi_panel_plat *mipi_plat; int ret; + priv->version = dev_get_driver_data(dev); + priv->dsi = (struct dsi_ctlr *)dev_read_addr_ptr(dev); if (!priv->dsi) { printf("%s: No display controller address\n", __func__); @@ -814,6 +875,16 @@ static int tegra_dsi_bridge_probe(struct udevice *dev) return log_ret(ret); } + if (priv->version) { + ret = uclass_get_device_by_phandle(UCLASS_MISC, dev, + "nvidia,mipi-calibrate", + >mipi); + if (ret) { + log_debug("%s: cannot get MIPI: error %d\n", __func__, ret); + return ret; + } + } + panel_get_display_timing(priv->panel, >timing)
[PATCH v4 09/13] video: tegra20: add MIPI calibration driver
Dedicated MIPI calibration driver is used on T114 and newer. Before T114 MIPI calibration registers were part of VI and CSI. Tested-by: Svyatoslav Ryhel # Nvidia Tegratab T114 Signed-off-by: Svyatoslav Ryhel --- drivers/video/tegra20/Makefile | 2 +- drivers/video/tegra20/tegra-mipi.c | 188 + 2 files changed, 189 insertions(+), 1 deletion(-) create mode 100644 drivers/video/tegra20/tegra-mipi.c diff --git a/drivers/video/tegra20/Makefile b/drivers/video/tegra20/Makefile index f0b534c579..a75aea2a87 100644 --- a/drivers/video/tegra20/Makefile +++ b/drivers/video/tegra20/Makefile @@ -1,5 +1,5 @@ # SPDX-License-Identifier: GPL-2.0+ obj-$(CONFIG_VIDEO_TEGRA20) += tegra-dc.o -obj-$(CONFIG_VIDEO_DSI_TEGRA30) += tegra-dsi.o mipi-phy.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-mipi.c b/drivers/video/tegra20/tegra-mipi.c new file mode 100644 index 00..2df3c1a994 --- /dev/null +++ b/drivers/video/tegra20/tegra-mipi.c @@ -0,0 +1,188 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2013 NVIDIA Corporation + * Copyright (c) 2023 Svyatoslav Ryhel + */ + +#include +#include +#include +#include +#include + +#include + +/* MIPI control registers 0x00 ~ 0x60 */ +struct mipi_ctlr { + uint mipi_cal_ctrl; + uint mipi_cal_autocal_ctrl; + uint mipi_cal_status; + + uint unused1[2]; + + uint mipi_cal_config_csia; + uint mipi_cal_config_csib; + uint mipi_cal_config_csic; + uint mipi_cal_config_csid; + uint mipi_cal_config_csie; + + uint unused2[4]; + + uint mipi_cal_config_dsia; + uint mipi_cal_config_dsib; + uint mipi_cal_config_dsic; + uint mipi_cal_config_dsid; + + uint unused3[4]; + + uint mipi_cal_bias_pad_cfg0; + uint mipi_cal_bias_pad_cfg1; + uint mipi_cal_bias_pad_cfg2; +}; + +#define MIPI_CAL_CTRL_NOISE_FILTER(x) (((x) & 0xf) << 26) +#define MIPI_CAL_CTRL_PRESCALE(x) (((x) & 0x3) << 24) +#define MIPI_CAL_CTRL_CLKEN_OVRBIT(4) +#define MIPI_CAL_CTRL_STARTBIT(0) + +#define MIPI_CAL_STATUS_DONE BIT(16) +#define MIPI_CAL_STATUS_ACTIVE BIT(0) + +#define MIPI_CAL_OVERIDE(x)(((x) & 0x1) << 30) +#define MIPI_CAL_SEL(x)(((x) & 0x1) << 21) +#define MIPI_CAL_HSPDOS(x) (((x) & 0x1f) << 16) +#define MIPI_CAL_HSPUOS(x) (((x) & 0x1f) << 8) +#define MIPI_CAL_TERMOS(x) (((x) & 0x1f) << 0) + +#define MIPI_CAL_BIAS_PAD_PDVCLAMP BIT(1) +#define MIPI_CAL_BIAS_PAD_E_VCLAMP_REF BIT(0) + +#define MIPI_CAL_BIAS_PAD_DRV_DN_REF(x) (((x) & 0x7) << 16) +#define MIPI_CAL_BIAS_PAD_DRV_UP_REF(x) (((x) & 0x7) << 8) + +#define MIPI_CAL_BIAS_PAD_VCLAMP(x)(((x) & 0x7) << 16) +#define MIPI_CAL_BIAS_PAD_VAUXP(x) (((x) & 0x7) << 4) +#define MIPI_CAL_BIAS_PAD_PDVREG BIT(1) + +struct tegra_mipi_priv { + struct mipi_ctlr*mipi; + struct clk *mipi_cal; +}; + +static int tegra_mipi_calibrate(struct udevice *dev, int offset, const void *buf, + int size) +{ + struct tegra_mipi_priv *priv = dev_get_priv(dev); + u32 value; + + value = MIPI_CAL_BIAS_PAD_DRV_DN_REF(0x2) | + MIPI_CAL_BIAS_PAD_DRV_UP_REF(0x0); + writel(value, >mipi->mipi_cal_bias_pad_cfg1); + + value = readl(>mipi->mipi_cal_bias_pad_cfg2); + value &= ~MIPI_CAL_BIAS_PAD_VCLAMP(0x7); + value &= ~MIPI_CAL_BIAS_PAD_VAUXP(0x7); + writel(value, >mipi->mipi_cal_bias_pad_cfg2); + + value = MIPI_CAL_OVERIDE(0x0) | MIPI_CAL_SEL(0x1) | + MIPI_CAL_HSPDOS(0x0) | MIPI_CAL_HSPUOS(0x4) | + MIPI_CAL_TERMOS(0x5); + writel(value, >mipi->mipi_cal_config_dsia); + writel(value, >mipi->mipi_cal_config_dsib); + + /* Deselect PAD C */ + value = readl(>mipi->mipi_cal_config_dsic); + value &= ~(MIPI_CAL_SEL(0x1)); + writel(value, >mipi->mipi_cal_config_dsic); + + /* Deselect PAD D */ + value = readl(>mipi->mipi_cal_config_dsid); + value &= ~(MIPI_CAL_SEL(0x1)); + writel(value, >mipi->mipi_cal_config_dsid); + + value = readl(>mipi->mipi_cal_ctrl); + value &= ~MIPI_CAL_CTRL_NOISE_FILTER(0xf); + value &= ~MIPI_CAL_CTRL_PRESCALE(0x3); + value |= MIPI_CAL_CTRL_NOISE_FILTER(0xa) | +MIPI_CAL_CTRL_PRESCALE(0x2) | +MIPI_CAL_CTRL_CLKEN_OVR; + writel(value, >mipi->mipi_cal_ctrl); + + /* clear any pending status bits */ + value = readl(>mipi->mipi_cal_status); + writel(value, >mipi->mipi_cal_
[PATCH v4 08/13] video: tegra20: dc: fix the clock divider calculation if PLLD/D2 is used
If DISP1 is a PLLD/D2 child, it cannot go over 370MHz. The cause of this is not quite clear. This can be overcomed by further halving the DISP1 clock if its parent is PLLD/D2 and the target rate is > 400MHz. Tested-by: Andreas Westman Dorcsak # ASUS Grouper E1565 Tested-by: Ion Agorria # HTC One X Tested-by: Svyatoslav Ryhel # Nvidia Tegratab T114 Tested-by: Jonas Schwöbel # Microsoft Surface 2 Signed-off-by: Jonas Schwöbel Signed-off-by: Svyatoslav Ryhel --- drivers/video/tegra20/tegra-dc.c | 41 ++-- 1 file changed, 28 insertions(+), 13 deletions(-) diff --git a/drivers/video/tegra20/tegra-dc.c b/drivers/video/tegra20/tegra-dc.c index 9a18e38cd8..42d91a03b6 100644 --- a/drivers/video/tegra20/tegra-dc.c +++ b/drivers/video/tegra20/tegra-dc.c @@ -48,6 +48,7 @@ struct tegra_lcd_priv { fdt_addr_t frame_buffer;/* Address of frame buffer */ unsigned pixel_clock; /* Pixel clock in Hz */ int dc_clk[2]; /* Contains clk and its parent */ + ulong clk_div; /* Clock divider used by disp_clk_ctrl */ bool rotation; /* 180 degree panel turn */ bool pipe; /* DC controller: 0 for A, 1 for B */ }; @@ -126,8 +127,6 @@ static int update_display_mode(struct tegra_lcd_priv *priv) struct dc_disp_reg *disp = >dc->disp; struct display_timing *dt = >timing; unsigned long val; - unsigned long rate; - unsigned long div; writel(0x0, >disp_timing_opt); @@ -150,21 +149,11 @@ static int update_display_mode(struct tegra_lcd_priv *priv) writel(val, >disp_interface_ctrl); } - /* -* The pixel clock divider is in 7.1 format (where the bottom bit -* represents 0.5). Here we calculate the divider needed to get from -* the display clock (typically 600MHz) to the pixel clock. We round -* up or down as requried. -*/ - rate = clock_get_periph_rate(priv->dc_clk[0], priv->dc_clk[1]); - div = ((rate * 2 + priv->pixel_clock / 2) / priv->pixel_clock) - 2; - debug("Display clock %lu, divider %lu\n", rate, div); - if (priv->soc->has_rgb) writel(0x00010001, >shift_clk_opt); val = PIXEL_CLK_DIVIDER_PCD1 << PIXEL_CLK_DIVIDER_SHIFT; - val |= div << SHIFT_CLK_DIVIDER_SHIFT; + val |= priv->clk_div << SHIFT_CLK_DIVIDER_SHIFT; writel(val, >disp_clk_ctrl); return 0; @@ -314,6 +303,32 @@ static int tegra_display_probe(struct tegra_lcd_priv *priv, rate /= 2; #endif + /* +* The pixel clock divider is in 7.1 format (where the bottom bit +* represents 0.5). Here we calculate the divider needed to get from +* the display clock (typically 600MHz) to the pixel clock. We round +* up or down as required. +*/ + priv->clk_div = ((rate * 2 + priv->pixel_clock / 2) + / priv->pixel_clock) - 2; + debug("Display clock %lu, divider %lu\n", rate, priv->clk_div); + + /* +* BUG: If DISP1 is a PLLD/D2 child, it cannot go over 370MHz. The +* cause of this is not quite clear. This can be overcomed by +* further halving the DISP1 clock if its parent is PLLD/D2 and +* the target rate is > 400MHz. +*/ + if (priv->dc_clk[1] == CLOCK_ID_DISPLAY) + if (rate > 40) + rate /= 2; + +#ifndef CONFIG_TEGRA20 + if (priv->dc_clk[1] == CLOCK_ID_DISPLAY2) + if (rate > 40) + rate /= 2; +#endif + /* * HOST1X is init by default at 150MHz with PLLC as parent */ -- 2.40.1
[PATCH v4 07/13] video: tegra20: dc: add powergate
Add powergate use on T114 to complete resetting of DC. Signed-off-by: Svyatoslav Ryhel --- drivers/video/tegra20/tegra-dc.c | 27 +++ 1 file changed, 27 insertions(+) diff --git a/drivers/video/tegra20/tegra-dc.c b/drivers/video/tegra20/tegra-dc.c index 35abb6fe46..9a18e38cd8 100644 --- a/drivers/video/tegra20/tegra-dc.c +++ b/drivers/video/tegra20/tegra-dc.c @@ -22,6 +22,7 @@ #include #include #include +#include #include #include "tegra-dc.h" @@ -32,6 +33,7 @@ DECLARE_GLOBAL_DATA_PTR; struct tegra_dc_soc_info { bool has_timer; bool has_rgb; + bool has_pgate; }; /* Information about the display controller */ @@ -360,6 +362,28 @@ static int tegra_lcd_probe(struct udevice *dev) clock_disable(priv->dc_clk[0]); + if (priv->soc->has_pgate) { + uint powergate; + + if (priv->pipe) + powergate = TEGRA_POWERGATE_DISB; + else + powergate = TEGRA_POWERGATE_DIS; + + ret = tegra_powergate_power_off(powergate); + if (ret < 0) { + log_err("failed to power off DISP gate: %d", ret); + return ret; + } + + ret = tegra_powergate_sequence_power_up(powergate, + priv->dc_clk[0]); + if (ret < 0) { + log_err("failed to power up DISP gate: %d", ret); + return ret; + } + } + /* Reset everything set before */ reset_assert(_ctl); mdelay(4); @@ -510,16 +534,19 @@ 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, + .has_pgate = false, }; static const struct tegra_dc_soc_info tegra30_dc_soc_info = { .has_timer = false, .has_rgb = true, + .has_pgate = false, }; static const struct tegra_dc_soc_info tegra114_dc_soc_info = { .has_timer = false, .has_rgb = false, + .has_pgate = true, }; static const struct udevice_id tegra_lcd_ids[] = { -- 2.40.1
[PATCH v4 06/13] video: tegra20: dc: add reset support
Implement reset use to discard any changes which could have been applied to DC before and can interfere with current configuration. Tested-by: Agneli # Toshiba AC100 T20 Tested-by: Robert Eckelmann # ASUS TF101 Tested-by: Andreas Westman Dorcsak # ASUS Grouper E1565 Tested-by: Ion Agorria # HTC One X Tested-by: Svyatoslav Ryhel # Nvidia Tegratab T114 Signed-off-by: Svyatoslav Ryhel --- drivers/video/tegra20/tegra-dc.c | 17 + 1 file changed, 17 insertions(+) diff --git a/drivers/video/tegra20/tegra-dc.c b/drivers/video/tegra20/tegra-dc.c index 56a23b3c97..35abb6fe46 100644 --- a/drivers/video/tegra20/tegra-dc.c +++ b/drivers/video/tegra20/tegra-dc.c @@ -10,7 +10,9 @@ #include #include #include +#include #include +#include #include #include #include @@ -342,6 +344,7 @@ static int tegra_lcd_probe(struct udevice *dev) struct video_uc_plat *plat = dev_get_uclass_plat(dev); struct video_priv *uc_priv = dev_get_uclass_priv(dev); struct tegra_lcd_priv *priv = dev_get_priv(dev); + struct reset_ctl reset_ctl; int ret; /* Initialize the Tegra display controller */ @@ -349,6 +352,20 @@ static int tegra_lcd_probe(struct udevice *dev) funcmux_select(PERIPH_ID_DISP1, FUNCMUX_DEFAULT); #endif + ret = reset_get_by_name(dev, "dc", _ctl); + if (ret) { + log_err("reset_get_by_name() failed: %d\n", ret); + return ret; + } + + clock_disable(priv->dc_clk[0]); + + /* Reset everything set before */ + reset_assert(_ctl); + mdelay(4); + reset_deassert(_ctl); + mdelay(4); + if (tegra_display_probe(priv, (void *)plat->base)) { debug("%s: Failed to probe display driver\n", __func__); return -1; -- 2.40.1
[PATCH v4 05/13] video: tegra20: dc: add PLLD2 parent support
T30+ SOC have second PLLD - PLLD2 which can be actively used by DC and act as main DISP1/2 clock parent. Tested-by: Agneli # Toshiba AC100 T20 Tested-by: Robert Eckelmann # ASUS TF101 Tested-by: Andreas Westman Dorcsak # ASUS Grouper E1565 Tested-by: Ion Agorria # HTC One X Tested-by: Svyatoslav Ryhel # Nvidia Tegratab T114 Signed-off-by: Svyatoslav Ryhel --- drivers/video/tegra20/tegra-dc.c | 6 ++ 1 file changed, 6 insertions(+) diff --git a/drivers/video/tegra20/tegra-dc.c b/drivers/video/tegra20/tegra-dc.c index 0e94e665ef..56a23b3c97 100644 --- a/drivers/video/tegra20/tegra-dc.c +++ b/drivers/video/tegra20/tegra-dc.c @@ -304,6 +304,12 @@ static int tegra_display_probe(struct tegra_lcd_priv *priv, if (priv->dc_clk[1] == CLOCK_ID_DISPLAY) rate /= 2; +#ifndef CONFIG_TEGRA20 + /* PLLD2 obeys same rules as PLLD but it is present only on T30+ */ + if (priv->dc_clk[1] == CLOCK_ID_DISPLAY2) + rate /= 2; +#endif + /* * HOST1X is init by default at 150MHz with PLLC as parent */ -- 2.40.1
[PATCH v4 04/13] video: tegra20: dc: pass DC id to internal devices
Tegra SoC has 2 independent display controllers called DC_A and DC_B, they are handled differently by internal video devices like DSI and HDMI controllers so it is important for last to know which display controller is used to properly set up registers. To achieve this, a pipe field was added to pdata to pass display controller id to internal Tegra SoC devices. Tested-by: Agneli # Toshiba AC100 T20 Tested-by: Robert Eckelmann # ASUS TF101 Tested-by: Andreas Westman Dorcsak # ASUS Grouper E1565 Tested-by: Ion Agorria # HTC One X Tested-by: Svyatoslav Ryhel # Nvidia Tegratab T114 Signed-off-by: Svyatoslav Ryhel --- drivers/video/tegra20/tegra-dc.c | 6 ++ drivers/video/tegra20/tegra-dc.h | 3 +++ 2 files changed, 9 insertions(+) diff --git a/drivers/video/tegra20/tegra-dc.c b/drivers/video/tegra20/tegra-dc.c index 5d8874f323..0e94e665ef 100644 --- a/drivers/video/tegra20/tegra-dc.c +++ b/drivers/video/tegra20/tegra-dc.c @@ -45,6 +45,7 @@ struct tegra_lcd_priv { unsigned pixel_clock; /* Pixel clock in Hz */ int dc_clk[2]; /* Contains clk and its parent */ bool rotation; /* 180 degree panel turn */ + bool pipe; /* DC controller: 0 for A, 1 for B */ }; enum { @@ -406,6 +407,9 @@ static int tegra_lcd_of_to_plat(struct udevice *dev) priv->rotation = dev_read_bool(dev, "nvidia,180-rotation"); + if (!strcmp(dev->name, TEGRA_DC_B)) + priv->pipe = 1; + rgb = fdt_subnode_offset(blob, node, "rgb"); if (rgb < 0) { debug("%s: Cannot find rgb subnode for '%s' (ret=%d)\n", @@ -431,12 +435,14 @@ static int tegra_lcd_of_to_plat(struct udevice *dev) return ret; } + /* 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, >timing); diff --git a/drivers/video/tegra20/tegra-dc.h b/drivers/video/tegra20/tegra-dc.h index 5c05221038..75fc0fa4de 100644 --- a/drivers/video/tegra20/tegra-dc.h +++ b/drivers/video/tegra20/tegra-dc.h @@ -14,12 +14,15 @@ /* arch-tegra/dc exists only because T124 uses it */ #include +#define TEGRA_DC_A "dc@5420" +#define TEGRA_DC_B "dc@5424" #define TEGRA_DSI_A"dsi@5430" #define TEGRA_DSI_B"dsi@5440" struct tegra_dc_plat { struct udevice *dev;/* Display controller device */ struct dc_ctlr *dc; /* Display controller regmap */ + bool pipe; /* DC number: 0 for A, 1 for B */ }; /* This holds information about a window which can be displayed */ -- 2.40.1
[PATCH v4 03/13] video: tegra20: consolidate DC header
Consolidate HD headers and place the result into video/tegra20 since it is used only by devices from this directory. Tested-by: Agneli # Toshiba AC100 T20 Tested-by: Robert Eckelmann # ASUS TF101 Tested-by: Andreas Westman Dorcsak # ASUS Grouper E1565 Tested-by: Ion Agorria # HTC One X Tested-by: Svyatoslav Ryhel # Nvidia Tegratab T114 Signed-off-by: Svyatoslav Ryhel --- arch/arm/include/asm/arch-tegra/dc.h | 8 arch/arm/include/asm/arch-tegra114/display.h | 28 - arch/arm/include/asm/arch-tegra20/display.h | 28 - arch/arm/include/asm/arch-tegra30/display.h | 28 - drivers/video/tegra20/tegra-dc.c | 3 +- drivers/video/tegra20/tegra-dc.h | 41 drivers/video/tegra20/tegra-dsi.c| 2 +- drivers/video/tegra20/tegra-pwm-backlight.c | 3 +- 8 files changed, 46 insertions(+), 95 deletions(-) delete mode 100644 arch/arm/include/asm/arch-tegra114/display.h delete mode 100644 arch/arm/include/asm/arch-tegra20/display.h delete mode 100644 arch/arm/include/asm/arch-tegra30/display.h create mode 100644 drivers/video/tegra20/tegra-dc.h diff --git a/arch/arm/include/asm/arch-tegra/dc.h b/arch/arm/include/asm/arch-tegra/dc.h index 7613d84f22..6444af2993 100644 --- a/arch/arm/include/asm/arch-tegra/dc.h +++ b/arch/arm/include/asm/arch-tegra/dc.h @@ -569,12 +569,4 @@ enum { #define DC_N_WINDOWS 5 #define DC_REG_SAVE_SPACE (DC_N_WINDOWS + 5) -#define TEGRA_DSI_A"dsi@5430" -#define TEGRA_DSI_B"dsi@5440" - -struct tegra_dc_plat { - struct udevice *dev;/* Display controller device */ - struct dc_ctlr *dc; /* Display controller regmap */ -}; - #endif /* __ASM_ARCH_TEGRA_DC_H */ diff --git a/arch/arm/include/asm/arch-tegra114/display.h b/arch/arm/include/asm/arch-tegra114/display.h deleted file mode 100644 index 9411525799..00 --- a/arch/arm/include/asm/arch-tegra114/display.h +++ /dev/null @@ -1,28 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ -/* - * (C) Copyright 2010 - * NVIDIA Corporation - */ - -#ifndef __ASM_ARCH_TEGRA_DISPLAY_H -#define __ASM_ARCH_TEGRA_DISPLAY_H - -#include - -/* This holds information about a window which can be displayed */ -struct disp_ctl_win { - enum win_color_depth_id fmt;/* Color depth/format */ - unsigned intbpp;/* Bits per pixel */ - phys_addr_t phys_addr; /* Physical address in memory */ - unsigned intx; /* Horizontal address offset (bytes) */ - unsigned inty; /* Veritical address offset (bytes) */ - unsigned intw; /* Width of source window */ - unsigned inth; /* Height of source window */ - unsigned intstride; /* Number of bytes per line */ - unsigned intout_x; /* Left edge of output window (col) */ - unsigned intout_y; /* Top edge of output window (row) */ - unsigned intout_w; /* Width of output window in pixels */ - unsigned intout_h; /* Height of output window in pixels */ -}; - -#endif /*__ASM_ARCH_TEGRA_DISPLAY_H*/ diff --git a/arch/arm/include/asm/arch-tegra20/display.h b/arch/arm/include/asm/arch-tegra20/display.h deleted file mode 100644 index e7b3cffd46..00 --- a/arch/arm/include/asm/arch-tegra20/display.h +++ /dev/null @@ -1,28 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ -/* - * (C) Copyright 2010 - * NVIDIA Corporation - */ - -#ifndef __ASM_ARCH_TEGRA_DISPLAY_H -#define __ASM_ARCH_TEGRA_DISPLAY_H - -#include - -/* This holds information about a window which can be displayed */ -struct disp_ctl_win { - enum win_color_depth_id fmt;/* Color depth/format */ - unsignedbpp;/* Bits per pixel */ - phys_addr_t phys_addr; /* Physical address in memory */ - unsignedx; /* Horizontal address offset (bytes) */ - unsignedy; /* Veritical address offset (bytes) */ - unsignedw; /* Width of source window */ - unsignedh; /* Height of source window */ - unsignedstride; /* Number of bytes per line */ - unsignedout_x; /* Left edge of output window (col) */ - unsignedout_y; /* Top edge of output window (row) */ - unsignedout_w; /* Width of output window in pixels */ - unsignedout_h; /* Height of output window in pixels */ -}; - -#endif /*__ASM_ARCH_TEGRA_DISPLAY_H*/ diff --git a/arch/arm/include/asm/arch-tegra30/display.h b/arch/arm/include/asm/arch-tegra30/display.h deleted file mode 100644 index 9411525799..00 --- a/arch/arm/include/asm/arch-tegra30/display.h +++ /dev/null @@ -1,28 +0,0 @@ -/* SPDX-License
[PATCH v4 01/13] video: tegra20: dc: diverge DC per-SOC
Diverge DC driver setup to better fit each of supported generations of Tegra SOC. Tested-by: Agneli # Toshiba AC100 T20 Tested-by: Robert Eckelmann # ASUS TF101 Tested-by: Andreas Westman Dorcsak # ASUS Grouper E1565 Tested-by: Ion Agorria # HTC One X Tested-by: Svyatoslav Ryhel # Nvidia Tegratab T114 Signed-off-by: Svyatoslav Ryhel --- arch/arm/dts/tegra114-u-boot.dtsi| 13 +++ arch/arm/dts/tegra114.dtsi | 4 +- arch/arm/dts/tegra30-u-boot.dtsi | 4 + arch/arm/dts/tegra30.dtsi| 2 +- arch/arm/include/asm/arch-tegra114/display.h | 28 + arch/arm/include/asm/arch-tegra114/pwm.h | 13 +++ drivers/video/tegra20/tegra-dc.c | 107 +-- 7 files changed, 133 insertions(+), 38 deletions(-) create mode 100644 arch/arm/include/asm/arch-tegra114/display.h create mode 100644 arch/arm/include/asm/arch-tegra114/pwm.h diff --git a/arch/arm/dts/tegra114-u-boot.dtsi b/arch/arm/dts/tegra114-u-boot.dtsi index 7c11972552..6a02714a25 100644 --- a/arch/arm/dts/tegra114-u-boot.dtsi +++ b/arch/arm/dts/tegra114-u-boot.dtsi @@ -1,3 +1,16 @@ #include #include "tegra-u-boot.dtsi" + +/ { + host1x@5000 { + bootph-all; + dc@5420 { + bootph-all; + }; + + dc@5424 { + bootph-all; + }; + }; +}; diff --git a/arch/arm/dts/tegra114.dtsi b/arch/arm/dts/tegra114.dtsi index 68ee7f3165..250d692f6b 100644 --- a/arch/arm/dts/tegra114.dtsi +++ b/arch/arm/dts/tegra114.dtsi @@ -42,7 +42,7 @@ }; dc@5420 { - compatible = "nvidia,tegra114-dc", "nvidia,tegra20-dc"; + compatible = "nvidia,tegra114-dc"; reg = <0x5420 0x0004>; interrupts = ; clocks = <_car TEGRA114_CLK_DISP1>, @@ -61,7 +61,7 @@ }; dc@5424 { - compatible = "nvidia,tegra114-dc", "nvidia,tegra20-dc"; + compatible = "nvidia,tegra114-dc"; reg = <0x5424 0x0004>; interrupts = ; clocks = <_car TEGRA114_CLK_DISP2>, diff --git a/arch/arm/dts/tegra30-u-boot.dtsi b/arch/arm/dts/tegra30-u-boot.dtsi index 3038227dbe..6a02714a25 100644 --- a/arch/arm/dts/tegra30-u-boot.dtsi +++ b/arch/arm/dts/tegra30-u-boot.dtsi @@ -8,5 +8,9 @@ dc@5420 { bootph-all; }; + + dc@5424 { + bootph-all; + }; }; }; diff --git a/arch/arm/dts/tegra30.dtsi b/arch/arm/dts/tegra30.dtsi index f198bc0edb..1177e2ab1f 100644 --- a/arch/arm/dts/tegra30.dtsi +++ b/arch/arm/dts/tegra30.dtsi @@ -158,7 +158,7 @@ }; dc@5420 { - compatible = "nvidia,tegra30-dc", "nvidia,tegra20-dc"; + compatible = "nvidia,tegra30-dc"; reg = <0x5420 0x0004>; interrupts = ; clocks = <_car TEGRA30_CLK_DISP1>, diff --git a/arch/arm/include/asm/arch-tegra114/display.h b/arch/arm/include/asm/arch-tegra114/display.h new file mode 100644 index 00..9411525799 --- /dev/null +++ b/arch/arm/include/asm/arch-tegra114/display.h @@ -0,0 +1,28 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * (C) Copyright 2010 + * NVIDIA Corporation + */ + +#ifndef __ASM_ARCH_TEGRA_DISPLAY_H +#define __ASM_ARCH_TEGRA_DISPLAY_H + +#include + +/* This holds information about a window which can be displayed */ +struct disp_ctl_win { + enum win_color_depth_id fmt;/* Color depth/format */ + unsigned intbpp;/* Bits per pixel */ + phys_addr_t phys_addr; /* Physical address in memory */ + unsigned intx; /* Horizontal address offset (bytes) */ + unsigned inty; /* Veritical address offset (bytes) */ + unsigned intw; /* Width of source window */ + unsigned inth; /* Height of source window */ + unsigned intstride; /* Number of bytes per line */ + unsigned intout_x; /* Left edge of output window (col) */ + unsigned intout_y; /* Top edge of output window (row) */ + unsigned intout_w; /* Width of output window in pixels */ + unsigned intout_h; /* Height of output window in pixels */ +}; + +#endif /*__ASM_ARCH_TEGRA_DISPLAY_H*/ diff --git a/arch/arm/include/asm/arch-tegra114/pwm.h b/arch/arm/include/asm/arch-tegra114/pwm.h new file mode 100644 index 00..af39151803 --
[PATCH v4 02/13] video: tegra20: dc: fix image shift on rotated panels
Subtracting 1 from x and y fixes image shifting on rotated panels. Tested-by: Robert Eckelmann # ASUS Grouper E1565 Signed-off-by: Svyatoslav Ryhel --- drivers/video/tegra20/tegra-dc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/video/tegra20/tegra-dc.c b/drivers/video/tegra20/tegra-dc.c index 7605e77bc1..bcc2748623 100644 --- a/drivers/video/tegra20/tegra-dc.c +++ b/drivers/video/tegra20/tegra-dc.c @@ -242,8 +242,8 @@ static int setup_window(struct tegra_lcd_priv *priv, struct disp_ctl_win *win) { if (priv->rotation) { - win->x = priv->width * 2; - win->y = priv->height; + win->x = priv->width * 2 - 1; + win->y = priv->height - 1; } else { win->x = 0; win->y = 0; -- 2.40.1
[PATCH v4 00/13] Add T114 video support
T114 is not that different from T30 and all T30 drivers will work on T114 as well with some adjustments. Patches propose general improvements for existing Tegra DC and DSI drivers as well Tegra 114 video support (experimentl). Commits pass buildman for tegra. --- Changes from v3: - fixed the clock divider calculation if PLLD/D2 is used - removed unnecessary pre-configuration - set correct video FIFO depth for DSI Changes from v2: - fixed image distortion on devices with 180deg rotation Changes from v1: - reworked patchset entirely - diverged DC configuration per-SOC - consolidated dc headers from different SOC gen - initial support of DC detection (tegra has 2 DC) - added PLLD2 support, resets and powergating - added T114+ MIPI calibration - added DSI detection (tegra has 2 DSI) and resets --- Jonas Schwöbel (2): video: tegra20: dsi: remove pre-configuration video: tegra20: dsi: set correct fifo depth Svyatoslav Ryhel (11): video: tegra20: dc: diverge DC per-SOC video: tegra20: dc: fix image shift on rotated panels video: tegra20: consolidate DC header video: tegra20: dc: pass DC id to internal devices video: tegra20: dc: add PLLD2 parent support video: tegra20: dc: add reset support video: tegra20: dc: add powergate video: tegra20: dc: fix the clock divider calculation if PLLD/D2 is used video: tegra20: add MIPI calibration driver video: tegra20: dsi: add T114 support video: tegra20: dsi: add reset support arch/arm/dts/tegra114-u-boot.dtsi | 13 ++ arch/arm/dts/tegra114.dtsi| 4 +- arch/arm/dts/tegra30-u-boot.dtsi | 4 + arch/arm/dts/tegra30.dtsi | 2 +- arch/arm/include/asm/arch-tegra/dc.h | 8 - arch/arm/include/asm/arch-tegra114/pwm.h | 13 ++ arch/arm/include/asm/arch-tegra20/display.h | 28 --- arch/arm/include/asm/arch-tegra30/display.h | 28 --- drivers/video/tegra20/Makefile| 2 +- drivers/video/tegra20/tegra-dc.c | 211 +- drivers/video/tegra20/tegra-dc.h | 44 drivers/video/tegra20/tegra-dsi.c | 98 +++- .../video/tegra20/tegra-dsi.h | 24 +- drivers/video/tegra20/tegra-mipi.c| 188 drivers/video/tegra20/tegra-pwm-backlight.c | 3 +- 15 files changed, 540 insertions(+), 130 deletions(-) create mode 100644 arch/arm/include/asm/arch-tegra114/pwm.h delete mode 100644 arch/arm/include/asm/arch-tegra20/display.h delete mode 100644 arch/arm/include/asm/arch-tegra30/display.h create mode 100644 drivers/video/tegra20/tegra-dc.h rename arch/arm/include/asm/arch-tegra30/dsi.h => drivers/video/tegra20/tegra-dsi.h (90%) create mode 100644 drivers/video/tegra20/tegra-mipi.c -- 2.40.1
[PATCH v1 2/2] board: tegra30: switch to standard boot
Switch transformer, endeavoru, grouper and x3_t30 boards to bootflow scan. Signed-off-by: Svyatoslav Ryhel --- configs/endeavoru_defconfig | 2 +- configs/grouper_common_defconfig | 2 +- configs/transformer_t30_defconfig | 2 +- configs/x3_t30_defconfig | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/configs/endeavoru_defconfig b/configs/endeavoru_defconfig index f2c35e4f5f..7136a7e8f2 100644 --- a/configs/endeavoru_defconfig +++ b/configs/endeavoru_defconfig @@ -20,7 +20,7 @@ CONFIG_AUTOBOOT_KEYED=y CONFIG_AUTOBOOT_KEYED_CTRLC=y CONFIG_OF_BOARD_SETUP=y CONFIG_OF_SYSTEM_SETUP=y -CONFIG_BOOTCOMMAND="if run check_button; then bootmenu; fi; run bootcmd_mmc0; poweroff;" +CONFIG_BOOTCOMMAND="if run check_button; then bootmenu; fi; bootflow scan; poweroff;" CONFIG_SYS_PBSIZE=2084 CONFIG_SPL_FOOTPRINT_LIMIT=y CONFIG_SPL_MAX_FOOTPRINT=0x8000 diff --git a/configs/grouper_common_defconfig b/configs/grouper_common_defconfig index 02ed8dbba9..6a1b719142 100644 --- a/configs/grouper_common_defconfig +++ b/configs/grouper_common_defconfig @@ -20,7 +20,7 @@ CONFIG_AUTOBOOT_KEYED=y CONFIG_AUTOBOOT_KEYED_CTRLC=y CONFIG_OF_BOARD_SETUP=y CONFIG_OF_SYSTEM_SETUP=y -CONFIG_BOOTCOMMAND="if run check_button; then bootmenu; fi; run bootcmd_mmc0; poweroff;" +CONFIG_BOOTCOMMAND="if run check_button; then bootmenu; fi; bootflow scan; poweroff;" CONFIG_SYS_PBSIZE=2084 CONFIG_SPL_FOOTPRINT_LIMIT=y CONFIG_SPL_MAX_FOOTPRINT=0x8000 diff --git a/configs/transformer_t30_defconfig b/configs/transformer_t30_defconfig index e4f76973eb..a142d82883 100644 --- a/configs/transformer_t30_defconfig +++ b/configs/transformer_t30_defconfig @@ -20,7 +20,7 @@ CONFIG_AUTOBOOT_KEYED=y CONFIG_AUTOBOOT_KEYED_CTRLC=y CONFIG_OF_BOARD_SETUP=y CONFIG_OF_SYSTEM_SETUP=y -CONFIG_BOOTCOMMAND="setenv skip_boot 0; setenv gpio_button 150; if run check_button; then poweroff; fi; setenv gpio_button 131; if run check_button; then bootmenu; fi; if test ${skip_boot} -eq 1; then; else run bootcmd_usb0; run bootcmd_mmc1; run bootcmd_mmc0; poweroff; fi" +CONFIG_BOOTCOMMAND="setenv skip_boot 0; setenv gpio_button 150; if run check_button; then poweroff; fi; setenv gpio_button 131; if run check_button; then bootmenu; fi; if test ${skip_boot} -eq 1; then; else setenv boot_targets usb mmc1 mmc0; bootflow scan; poweroff; fi" CONFIG_SYS_PBSIZE=2084 CONFIG_SPL_FOOTPRINT_LIMIT=y CONFIG_SPL_MAX_FOOTPRINT=0x8000 diff --git a/configs/x3_t30_defconfig b/configs/x3_t30_defconfig index 094a7d0709..b777d66653 100644 --- a/configs/x3_t30_defconfig +++ b/configs/x3_t30_defconfig @@ -21,7 +21,7 @@ CONFIG_AUTOBOOT_KEYED=y CONFIG_AUTOBOOT_KEYED_CTRLC=y CONFIG_OF_BOARD_SETUP=y CONFIG_OF_SYSTEM_SETUP=y -CONFIG_BOOTCOMMAND="if run check_button; then bootmenu; fi; run bootcmd_mmc1; run bootcmd_mmc0; poweroff;" +CONFIG_BOOTCOMMAND="if run check_button; then bootmenu; fi; bootflow scan; poweroff;" CONFIG_SYS_PBSIZE=2084 CONFIG_SPL_FOOTPRINT_LIMIT=y CONFIG_SPL_MAX_FOOTPRINT=0x8000 -- 2.40.1
[PATCH v1 1/2] ARM: tegra: move to standard boot
Drop the distro-boot scripts and use standard boot instead. Inspired by: 'commit 7755dc58af7b ("rockchip: Move to standard boot")' Signed-off-by: Svyatoslav Ryhel --- arch/arm/Kconfig| 2 +- include/configs/tegra-common-post.h | 30 ++--- 2 files changed, 3 insertions(+), 29 deletions(-) diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 2d4458b7b5..467dc07c06 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -1323,7 +1323,7 @@ config ARCH_ZYNQMP config ARCH_TEGRA bool "NVIDIA Tegra" select GPIO_EXTRA_HEADER - imply DISTRO_DEFAULTS + imply BOOTSTD_DEFAULTS imply FAT_WRITE imply SPL_TIMER if SPL diff --git a/include/configs/tegra-common-post.h b/include/configs/tegra-common-post.h index 0d0965ecce..fc74980f7c 100644 --- a/include/configs/tegra-common-post.h +++ b/include/configs/tegra-common-post.h @@ -7,33 +7,7 @@ #ifndef __TEGRA_COMMON_POST_H #define __TEGRA_COMMON_POST_H -#if IS_ENABLED(CONFIG_CMD_USB) -#define BOOT_TARGET_USB(func) func(USB, usb, 0) -#else -#define BOOT_TARGET_USB(func) -#endif - -#if CONFIG_IS_ENABLED(CMD_DHCP) && CONFIG_IS_ENABLED(CMD_PXE) -#define BOOT_TARGET_PXE(func) func(PXE, pxe, na) -#else -#define BOOT_TARGET_PXE(func) -#endif - -#if CONFIG_IS_ENABLED(CMD_DHCP) -#define BOOT_TARGET_DHCP(func) func(DHCP, dhcp, na) -#else -#define BOOT_TARGET_DHCP(func) -#endif - -#ifndef BOOT_TARGET_DEVICES -#define BOOT_TARGET_DEVICES(func) \ - func(MMC, mmc, 1) \ - func(MMC, mmc, 0) \ - BOOT_TARGET_USB(func) \ - BOOT_TARGET_PXE(func) \ - BOOT_TARGET_DHCP(func) -#endif -#include +#define BOOT_TARGETS "mmc1 mmc0 usb pxe dhcp" #ifdef CONFIG_TEGRA_KEYBOARD #define STDIN_KBD_KBC ",tegra-kbc" @@ -88,7 +62,7 @@ MEM_LAYOUT_ENV_SETTINGS \ "fdt_high=" FDT_HIGH "\0" \ "initrd_high=" INITRD_HIGH "\0" \ - BOOTENV \ + "boot_targets=" BOOT_TARGETS "\0" \ BOARD_EXTRA_ENV_SETTINGS #endif /* __TEGRA_COMMON_POST_H */ -- 2.40.1
[PATCH v1 0/2] ARM: tegra: move to standard boot
Drop the distro-boot scripts and use standard boot instead. Most of tegra boards should support this as is, those which does not are adjusted. Inspired by: 'commit 7755dc58af7b ("rockchip: Move to standard boot")' Passes buildman for all tegra board without errors. Svyatoslav Ryhel (2): ARM: tegra: move to standard boot board: tegra30: switch to standard boot arch/arm/Kconfig| 2 +- configs/endeavoru_defconfig | 2 +- configs/grouper_common_defconfig| 2 +- configs/transformer_t30_defconfig | 2 +- configs/x3_t30_defconfig| 2 +- include/configs/tegra-common-post.h | 30 ++--- 6 files changed, 7 insertions(+), 33 deletions(-) -- 2.40.1
[PATCH v2 1/1] cmd: bootmenu: rename U-Boot console to Exit
It seems that the U-Boot console entry of the bootmenu has lost its original meaning. Now, even if it is chosen, the probability that you will enter the actual U-Boot console is quite low. Boot env, bootflow, bootcommand script may appear, but not the actual console. Hence, let's remove ambiguity and name this entry by what it actually does: 'Exit' the bootmenu. Signed-off-by: Svyatoslav Ryhel --- cmd/bootmenu.c | 10 +- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/cmd/bootmenu.c b/cmd/bootmenu.c index 987b16889f..78184fccab 100644 --- a/cmd/bootmenu.c +++ b/cmd/bootmenu.c @@ -119,7 +119,7 @@ static char *bootmenu_choice_entry(void *data) iter = iter->next; return iter->key; case BKEY_QUIT: - /* Quit by choosing the last entry - U-Boot console */ + /* Quit by choosing the last entry */ iter = menu->first; while (iter->next) iter = iter->next; @@ -361,15 +361,15 @@ static struct bootmenu_data *bootmenu_create(int delay) } #endif - /* Add U-Boot console entry at the end */ + /* Add Exit entry at the end */ if (i <= MAX_COUNT - 1) { entry = malloc(sizeof(struct bootmenu_entry)); if (!entry) goto cleanup; - /* Add Quit entry if entering U-Boot console is disabled */ + /* Add Quit entry if exiting bootmenu is disabled */ if (!IS_ENABLED(CONFIG_BOOTMENU_DISABLE_UBOOT_CONSOLE)) - entry->title = strdup("U-Boot console"); + entry->title = strdup("Exit"); else entry->title = strdup("Quit"); @@ -532,7 +532,7 @@ static enum bootmenu_ret bootmenu_show(int delay) title = strdup(iter->title); command = strdup(iter->command); - /* last entry is U-Boot console or Quit */ + /* last entry exits bootmenu */ if (iter->num == iter->menu->count - 1) { ret = BOOTMENU_RET_QUIT; goto cleanup; -- 2.40.1
[PATCH v2 0/1] bootmenu: rename U-Boot console to Exit
It seems that the U-Boot console entry of the bootmenu has lost its original meaning. Now, even if it is chosen, the probability that you will enter the actual U-Boot console is quite low. Boot env, bootflow, bootcommand script may appear, but not the actual console. Hense, let's remove ambiguity and name this entry by what it actually does: 'Exit' the bootmenu. --- Changes in v2 - fixed typo in commit message - slightly modified comments in the code --- Svyatoslav Ryhel (1): cmd: bootmenu: rename U-Boot console to Exit cmd/bootmenu.c | 10 +- 1 file changed, 5 insertions(+), 5 deletions(-) -- 2.40.1
Re: [PATCH v1 1/1] cmd: bootmenu: rename U-Boot console to Exit
14 січня 2024 р. 16:41:40 GMT+02:00, Peter Robinson написав(-ла): >On Sun, 14 Jan 2024 at 10:23, Svyatoslav Ryhel wrote: >> >> It seems that the U-Boot console entry of the bootmenu has lost >> its original meaning. Now, even if it is chosen, the probability >> that you will enter the actual U-Boot console is quite low. >> Boot env, bootflow, bootcommand script may appear, but not the >> actual console. Hense, let's remove ambiguity and name this > >Hence > Fair >> entry by what it actually does: 'Exit' the bootmenu. >> >> Signed-off-by: Svyatoslav Ryhel >> --- >> cmd/bootmenu.c | 10 +- >> 1 file changed, 5 insertions(+), 5 deletions(-) >> >> diff --git a/cmd/bootmenu.c b/cmd/bootmenu.c >> index 987b16889f..69fca710a8 100644 >> --- a/cmd/bootmenu.c >> +++ b/cmd/bootmenu.c >> @@ -119,7 +119,7 @@ static char *bootmenu_choice_entry(void *data) >> iter = iter->next; >> return iter->key; >> case BKEY_QUIT: >> - /* Quit by choosing the last entry - U-Boot console >> */ >> + /* Quit by choosing the last entry - Exit */ > >I think just put "Set the last entry to Exit" > It can be either Quit or U-Boot console. Since U-Boot console is renamed by this patch, all references in comments are replaced with Exit. >> iter = menu->first; >> while (iter->next) >> iter = iter->next; >> @@ -361,15 +361,15 @@ static struct bootmenu_data *bootmenu_create(int delay) >> } >> #endif >> >> - /* Add U-Boot console entry at the end */ >> + /* Add Exit entry at the end */ >> if (i <= MAX_COUNT - 1) { >> entry = malloc(sizeof(struct bootmenu_entry)); >> if (!entry) >> goto cleanup; >> >> - /* Add Quit entry if entering U-Boot console is disabled */ >> + /* Add Quit entry if exiting to U-Boot console is disabled */ > >s/Quit/Exit/ > >> if (!IS_ENABLED(CONFIG_BOOTMENU_DISABLE_UBOOT_CONSOLE)) >> - entry->title = strdup("U-Boot console"); >> + entry->title = strdup("Exit"); >> else >> entry->title = strdup("Quit"); >> >> @@ -532,7 +532,7 @@ static enum bootmenu_ret bootmenu_show(int delay) >> title = strdup(iter->title); >> command = strdup(iter->command); >> >> - /* last entry is U-Boot console or Quit */ >> + /* last entry is Exit or Quit */ > >"Last entry is Exit" as I don't see Quit referred to. > Check above. >> if (iter->num == iter->menu->count - 1) { >> ret = BOOTMENU_RET_QUIT; >> goto cleanup; >> -- >> 2.40.1 >>
[PATCH v1 1/1] cmd: bootmenu: rename U-Boot console to Exit
It seems that the U-Boot console entry of the bootmenu has lost its original meaning. Now, even if it is chosen, the probability that you will enter the actual U-Boot console is quite low. Boot env, bootflow, bootcommand script may appear, but not the actual console. Hense, let's remove ambiguity and name this entry by what it actually does: 'Exit' the bootmenu. Signed-off-by: Svyatoslav Ryhel --- cmd/bootmenu.c | 10 +- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/cmd/bootmenu.c b/cmd/bootmenu.c index 987b16889f..69fca710a8 100644 --- a/cmd/bootmenu.c +++ b/cmd/bootmenu.c @@ -119,7 +119,7 @@ static char *bootmenu_choice_entry(void *data) iter = iter->next; return iter->key; case BKEY_QUIT: - /* Quit by choosing the last entry - U-Boot console */ + /* Quit by choosing the last entry - Exit */ iter = menu->first; while (iter->next) iter = iter->next; @@ -361,15 +361,15 @@ static struct bootmenu_data *bootmenu_create(int delay) } #endif - /* Add U-Boot console entry at the end */ + /* Add Exit entry at the end */ if (i <= MAX_COUNT - 1) { entry = malloc(sizeof(struct bootmenu_entry)); if (!entry) goto cleanup; - /* Add Quit entry if entering U-Boot console is disabled */ + /* Add Quit entry if exiting to U-Boot console is disabled */ if (!IS_ENABLED(CONFIG_BOOTMENU_DISABLE_UBOOT_CONSOLE)) - entry->title = strdup("U-Boot console"); + entry->title = strdup("Exit"); else entry->title = strdup("Quit"); @@ -532,7 +532,7 @@ static enum bootmenu_ret bootmenu_show(int delay) title = strdup(iter->title); command = strdup(iter->command); - /* last entry is U-Boot console or Quit */ + /* last entry is Exit or Quit */ if (iter->num == iter->menu->count - 1) { ret = BOOTMENU_RET_QUIT; goto cleanup; -- 2.40.1
[PATCH v1 0/1] bootmenu: rename U-Boot console to Exit
It seems that the U-Boot console entry of the bootmenu has lost its original meaning. Now, even if it is chosen, the probability that you will enter the actual U-Boot console is quite low. Boot env, bootflow, bootcommand script may appear, but not the actual console. Hense, let's remove ambiguity and name this entry by what it actually does: 'Exit' the bootmenu. Svyatoslav Ryhel (1): cmd: bootmenu: rename U-Boot console to Exit cmd/bootmenu.c | 10 +- 1 file changed, 5 insertions(+), 5 deletions(-) -- 2.40.1
[PATCH v3 1/1] clk: clk-gpio: add actual gated clock
Existing gpio-gate-clock driver acts like a simple GPIO switch without any effect on gated clock. Add actual clock actions into enable/disable ops and implement get_rate op by passing gated clock if it is enabled. Signed-off-by: Svyatoslav Ryhel --- drivers/clk/clk-gpio.c | 40 ++-- 1 file changed, 34 insertions(+), 6 deletions(-) diff --git a/drivers/clk/clk-gpio.c b/drivers/clk/clk-gpio.c index 26d795b978..d2dd8070fa 100644 --- a/drivers/clk/clk-gpio.c +++ b/drivers/clk/clk-gpio.c @@ -3,19 +3,23 @@ * Copyright (C) 2023 Marek Vasut */ -#include -#include -#include +#include #include +#include +#include + +#include struct clk_gpio_priv { - struct gpio_descenable; + struct gpio_descenable; /* GPIO, controlling the gate */ + struct clk *clk; /* Gated clock */ }; static int clk_gpio_enable(struct clk *clk) { struct clk_gpio_priv *priv = dev_get_priv(clk->dev); + clk_enable(priv->clk); dm_gpio_set_value(>enable, 1); return 0; @@ -26,21 +30,45 @@ static int clk_gpio_disable(struct clk *clk) struct clk_gpio_priv *priv = dev_get_priv(clk->dev); dm_gpio_set_value(>enable, 0); + clk_disable(priv->clk); return 0; } +static ulong clk_gpio_get_rate(struct clk *clk) +{ + struct clk_gpio_priv *priv = dev_get_priv(clk->dev); + + return clk_get_rate(priv->clk); +} + const struct clk_ops clk_gpio_ops = { .enable = clk_gpio_enable, .disable= clk_gpio_disable, + .get_rate = clk_gpio_get_rate, }; static int clk_gpio_probe(struct udevice *dev) { struct clk_gpio_priv *priv = dev_get_priv(dev); + int ret; - return gpio_request_by_name(dev, "enable-gpios", 0, - >enable, GPIOD_IS_OUT); + priv->clk = devm_clk_get(dev, NULL); + if (IS_ERR(priv->clk)) { + log_debug("%s: Could not get gated clock: %ld\n", + __func__, PTR_ERR(priv->clk)); + return PTR_ERR(priv->clk); + } + + ret = gpio_request_by_name(dev, "enable-gpios", 0, + >enable, GPIOD_IS_OUT); + if (ret) { + log_debug("%s: Could not decode enable-gpios (%d)\n", + __func__, ret); + return ret; + } + + return 0; } /* -- 2.40.1
[PATCH v3 0/1] Fix clk-gpio driver
Existing gpio-gate-clock driver acts like a simple GPIO switch without any effect on gated clock. Add actual clock actions into enable/disable ops and implement get_rate op by passing gated clock if it is enabled. Testing current driver implementation shows that it is not fully capable and lacks gated clock manipulations. --- Changes from v2 - restored probe Changes from v1 - added comments for priv struct members - return gatet clock rate unconditionally - switch log_err > log_debug on of_to_plat --- Svyatoslav Ryhel (1): clk: clk-gpio: add actual gated clock drivers/clk/clk-gpio.c | 40 ++-- 1 file changed, 34 insertions(+), 6 deletions(-) -- 2.40.1
Re: [PATCH v2 1/1] clk: clk-gpio: add actual gated clock
10 січня 2024 р. 17:45:57 GMT+02:00, Sean Anderson написав(-ла): >On 12/16/23 10:37, Sean Anderson wrote: >> On 12/16/23 03:48, Svyatoslav Ryhel wrote: >>> Existing gpio-gate-clock driver acts like a simple GPIO switch without any >>> effect on gated clock. Add actual clock actions into enable/disable ops and >>> implement get_rate op by passing gated clock if it is enabled. >>> >>> Signed-off-by: Svyatoslav Ryhel >>> --- >>> drivers/clk/clk-gpio.c | 44 ++ >>> 1 file changed, 36 insertions(+), 8 deletions(-) >>> >>> diff --git a/drivers/clk/clk-gpio.c b/drivers/clk/clk-gpio.c >>> index 26d795b978..72d9747a47 100644 >>> --- a/drivers/clk/clk-gpio.c >>> +++ b/drivers/clk/clk-gpio.c >>> @@ -3,19 +3,23 @@ >>> * Copyright (C) 2023 Marek Vasut >>> */ >>> -#include >>> -#include >>> -#include >>> +#include >>> #include >>> +#include >>> +#include >>> + >>> +#include >>> struct clk_gpio_priv { >>> - struct gpio_desc enable; >>> + struct gpio_desc enable; /* GPIO, controlling the gate */ >>> + struct clk *clk; /* Gated clock */ >>> }; >>> static int clk_gpio_enable(struct clk *clk) >>> { >>> struct clk_gpio_priv *priv = dev_get_priv(clk->dev); >>> + clk_enable(priv->clk); >>> dm_gpio_set_value(>enable, 1); >>> return 0; >>> @@ -26,21 +30,45 @@ static int clk_gpio_disable(struct clk *clk) >>> struct clk_gpio_priv *priv = dev_get_priv(clk->dev); >>> dm_gpio_set_value(>enable, 0); >>> + clk_disable(priv->clk); >>> return 0; >>> } >>> +static ulong clk_gpio_get_rate(struct clk *clk) >>> +{ >>> + struct clk_gpio_priv *priv = dev_get_priv(clk->dev); >>> + >>> + return clk_get_rate(priv->clk); >>> +} >>> + >>> const struct clk_ops clk_gpio_ops = { >>> .enable = clk_gpio_enable, >>> .disable = clk_gpio_disable, >>> + .get_rate = clk_gpio_get_rate, >>> }; >>> -static int clk_gpio_probe(struct udevice *dev) >>> +static int clk_gpio_of_to_plat(struct udevice *dev) > >Same comment as the first time: > >Why the conversion from probe to of_to_plat? > Same answer as the first time. You propose to spam commits for this small adjustment? >--Sean > >>> { >>> struct clk_gpio_priv *priv = dev_get_priv(dev); >>> + int ret; >>> - return gpio_request_by_name(dev, "enable-gpios", 0, >>> - >enable, GPIOD_IS_OUT); >>> + priv->clk = devm_clk_get(dev, NULL); >>> + if (IS_ERR(priv->clk)) { >>> + log_debug("%s: Could not get gated clock: %ld\n", >>> + __func__, PTR_ERR(priv->clk)); >>> + return PTR_ERR(priv->clk); >>> + } >>> + >>> + ret = gpio_request_by_name(dev, "enable-gpios", 0, >>> + >enable, GPIOD_IS_OUT); >>> + if (ret) { >>> + log_debug("%s: Could not decode enable-gpios (%d)\n", >>> + __func__, ret); >>> + return ret; >>> + } >>> + >>> + return 0; >>> } >>> /* >>> @@ -59,7 +87,7 @@ U_BOOT_DRIVER(gpio_gate_clock) = { >>> .name = "gpio_clock", >>> .id = UCLASS_CLK, >>> .of_match = clk_gpio_match, >>> - .probe = clk_gpio_probe, >>> + .of_to_plat = clk_gpio_of_to_plat, >>> .priv_auto = sizeof(struct clk_gpio_priv), >>> .ops = _gpio_ops, >>> .flags = DM_FLAG_PRE_RELOC, >> >> +CC Marek >
[PATCH v3 10/10] video: tegra20: dsi: add reset support
Implement reset use to discard any changes which could have been applied to DSI before and can interfere with current configuration. Tested-by: Ion Agorria # HTC One X Tested-by: Svyatoslav Ryhel # Nvidia Tegratab T114 Signed-off-by: Svyatoslav Ryhel --- drivers/video/tegra20/tegra-dsi.c | 14 ++ 1 file changed, 14 insertions(+) diff --git a/drivers/video/tegra20/tegra-dsi.c b/drivers/video/tegra20/tegra-dsi.c index f4743e8458..6408026808 100644 --- a/drivers/video/tegra20/tegra-dsi.c +++ b/drivers/video/tegra20/tegra-dsi.c @@ -12,6 +12,7 @@ #include #include #include +#include #include #include #include @@ -849,6 +850,7 @@ static int tegra_dsi_bridge_probe(struct udevice *dev) struct tegra_dsi_priv *priv = dev_get_priv(dev); struct mipi_dsi_device *device = >device; struct mipi_dsi_panel_plat *mipi_plat; + struct reset_ctl reset_ctl; int ret; priv->version = dev_get_driver_data(dev); @@ -862,6 +864,13 @@ static int tegra_dsi_bridge_probe(struct udevice *dev) priv->video_fifo_depth = 480; priv->host_fifo_depth = 64; + ret = reset_get_by_name(dev, "dsi", _ctl); + if (ret) { + log_debug("%s: reset_get_by_name() failed: %d\n", + __func__, ret); + return ret; + } + ret = uclass_get_device_by_phandle(UCLASS_REGULATOR, dev, "avdd-dsi-csi-supply", >avdd); if (ret) @@ -900,12 +909,17 @@ static int tegra_dsi_bridge_probe(struct udevice *dev) tegra_dsi_get_format(device->format, >format); + reset_assert(_ctl); + ret = regulator_set_enable_if_allowed(priv->avdd, true); if (ret && ret != -ENOSYS) return ret; tegra_dsi_init_clocks(dev); + mdelay(2); + reset_deassert(_ctl); + return 0; } -- 2.40.1
[PATCH v3 09/10] video: tegra20: dsi: add T114 support
Existing Tegra DSI driver mostly fits T114 apart MIPI calibration which on T114 has dedicated driver. To resolve this MIPI calibration logic was split for pre-T114 and T114+ devices. Tested-by: Ion Agorria # HTC One X Tested-by: Svyatoslav Ryhel # Nvidia Tegratab T114 Signed-off-by: Svyatoslav Ryhel --- drivers/video/tegra20/tegra-dsi.c | 78 ++- .../video/tegra20/tegra-dsi.h | 24 +- 2 files changed, 96 insertions(+), 6 deletions(-) rename arch/arm/include/asm/arch-tegra30/dsi.h => drivers/video/tegra20/tegra-dsi.h (90%) diff --git a/drivers/video/tegra20/tegra-dsi.c b/drivers/video/tegra20/tegra-dsi.c index 72b91ed26b..f4743e8458 100644 --- a/drivers/video/tegra20/tegra-dsi.c +++ b/drivers/video/tegra20/tegra-dsi.c @@ -20,17 +20,24 @@ #include #include #include -#include #include "tegra-dc.h" +#include "tegra-dsi.h" #include "mipi-phy.h" +/* List of supported DSI bridges */ +enum { + DSI_V0, + DSI_V1, +}; + struct tegra_dsi_priv { struct mipi_dsi_host host; struct mipi_dsi_device device; struct mipi_dphy_timing dphy_timing; struct udevice *panel; + struct udevice *mipi; struct display_timing timing; struct dsi_ctlr *dsi; @@ -41,6 +48,8 @@ struct tegra_dsi_priv { int dsi_clk; int video_fifo_depth; int host_fifo_depth; + + u32 version; }; static void tegra_dc_enable_controller(struct udevice *dev) @@ -501,6 +510,41 @@ static void tegra_dsi_pad_calibrate(struct dsi_pad_ctrl_reg *pad) writel(value, TEGRA_VI_BASE + (CSI_CIL_PAD_CONFIG << 2)); } +static void tegra_dsi_mipi_calibrate(struct tegra_dsi_priv *priv) +{ + struct dsi_pad_ctrl_reg *pad = >dsi->pad; + u32 value; + int ret; + + ret = misc_set_enabled(priv->mipi, true); + if (ret) + log_debug("%s: failed to enable MIPI calibration: %d\n", + __func__, ret); + + writel(0, >pad_ctrl); + writel(0, >pad_ctrl_1); + writel(0, >pad_ctrl_2); + writel(0, >pad_ctrl_3); + writel(0, >pad_ctrl_4); + + /* DSI pad enable */ + value = DSI_PAD_CONTROL_VS1_PULLDN(0) | DSI_PAD_CONTROL_VS1_PDIO(0); + writel(value, >pad_ctrl); + + value = DSI_PAD_SLEW_UP(0x7) | DSI_PAD_SLEW_DN(0x7) | + DSI_PAD_LP_UP(0x1) | DSI_PAD_LP_DN(0x1) | + DSI_PAD_OUT_CLK(0x0); + writel(value, >pad_ctrl_2); + + value = DSI_PAD_PREEMP_PD_CLK(0x3) | DSI_PAD_PREEMP_PU_CLK(0x3) | + DSI_PAD_PREEMP_PD(0x03) | DSI_PAD_PREEMP_PU(0x3); + writel(value, >pad_ctrl_3); + + ret = misc_write(priv->mipi, 0, NULL, 0); + if (ret) + log_debug("%s: MIPI calibration failed %d\n", __func__, ret); +} + static void tegra_dsi_set_timeout(struct dsi_timeout_reg *rtimeout, unsigned long bclk, unsigned int vrefresh) @@ -664,10 +708,25 @@ static int tegra_dsi_encoder_enable(struct udevice *dev) u32 value; int ret; + /* If for some reasone DSI is enabled then it needs to +* be disabled in order for the panel initialization +* commands to be properly sent. +*/ + value = readl(>dsi_pwr_ctrl); + + if (value & DSI_POWER_CONTROL_ENABLE) { + value = readl(>dsi_pwr_ctrl); + value &= ~DSI_POWER_CONTROL_ENABLE; + writel(value, >dsi_pwr_ctrl); + } + /* Disable interrupt */ writel(0, >int_enable); - tegra_dsi_pad_calibrate(>dsi->pad); + if (priv->version) + tegra_dsi_mipi_calibrate(priv); + else + tegra_dsi_pad_calibrate(>dsi->pad); tegra_dsi_get_muldiv(device->format, , ); @@ -792,6 +851,8 @@ static int tegra_dsi_bridge_probe(struct udevice *dev) struct mipi_dsi_panel_plat *mipi_plat; int ret; + priv->version = dev_get_driver_data(dev); + priv->dsi = (struct dsi_ctlr *)dev_read_addr_ptr(dev); if (!priv->dsi) { printf("%s: No display controller address\n", __func__); @@ -814,6 +875,16 @@ static int tegra_dsi_bridge_probe(struct udevice *dev) return log_ret(ret); } + if (priv->version) { + ret = uclass_get_device_by_phandle(UCLASS_MISC, dev, + "nvidia,mipi-calibrate", + >mipi); + if (ret) { + log_debug("%s: cannot get MIPI: error %d\n", __func__, ret); + return ret; + } + } + panel_get_display_timing(priv->panel, >timing)
[PATCH v3 08/10] video: tegra20: add MIPI calibration driver
Dedicated MIPI calibration driver is used on T114 and newer. Before T114 MIPI calibration registers were part of VI and CSI. Tested-by: Svyatoslav Ryhel # Nvidia Tegratab T114 Signed-off-by: Svyatoslav Ryhel --- drivers/video/tegra20/Makefile | 2 +- drivers/video/tegra20/tegra-mipi.c | 188 + 2 files changed, 189 insertions(+), 1 deletion(-) create mode 100644 drivers/video/tegra20/tegra-mipi.c diff --git a/drivers/video/tegra20/Makefile b/drivers/video/tegra20/Makefile index f0b534c579..a75aea2a87 100644 --- a/drivers/video/tegra20/Makefile +++ b/drivers/video/tegra20/Makefile @@ -1,5 +1,5 @@ # SPDX-License-Identifier: GPL-2.0+ obj-$(CONFIG_VIDEO_TEGRA20) += tegra-dc.o -obj-$(CONFIG_VIDEO_DSI_TEGRA30) += tegra-dsi.o mipi-phy.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-mipi.c b/drivers/video/tegra20/tegra-mipi.c new file mode 100644 index 00..2df3c1a994 --- /dev/null +++ b/drivers/video/tegra20/tegra-mipi.c @@ -0,0 +1,188 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2013 NVIDIA Corporation + * Copyright (c) 2023 Svyatoslav Ryhel + */ + +#include +#include +#include +#include +#include + +#include + +/* MIPI control registers 0x00 ~ 0x60 */ +struct mipi_ctlr { + uint mipi_cal_ctrl; + uint mipi_cal_autocal_ctrl; + uint mipi_cal_status; + + uint unused1[2]; + + uint mipi_cal_config_csia; + uint mipi_cal_config_csib; + uint mipi_cal_config_csic; + uint mipi_cal_config_csid; + uint mipi_cal_config_csie; + + uint unused2[4]; + + uint mipi_cal_config_dsia; + uint mipi_cal_config_dsib; + uint mipi_cal_config_dsic; + uint mipi_cal_config_dsid; + + uint unused3[4]; + + uint mipi_cal_bias_pad_cfg0; + uint mipi_cal_bias_pad_cfg1; + uint mipi_cal_bias_pad_cfg2; +}; + +#define MIPI_CAL_CTRL_NOISE_FILTER(x) (((x) & 0xf) << 26) +#define MIPI_CAL_CTRL_PRESCALE(x) (((x) & 0x3) << 24) +#define MIPI_CAL_CTRL_CLKEN_OVRBIT(4) +#define MIPI_CAL_CTRL_STARTBIT(0) + +#define MIPI_CAL_STATUS_DONE BIT(16) +#define MIPI_CAL_STATUS_ACTIVE BIT(0) + +#define MIPI_CAL_OVERIDE(x)(((x) & 0x1) << 30) +#define MIPI_CAL_SEL(x)(((x) & 0x1) << 21) +#define MIPI_CAL_HSPDOS(x) (((x) & 0x1f) << 16) +#define MIPI_CAL_HSPUOS(x) (((x) & 0x1f) << 8) +#define MIPI_CAL_TERMOS(x) (((x) & 0x1f) << 0) + +#define MIPI_CAL_BIAS_PAD_PDVCLAMP BIT(1) +#define MIPI_CAL_BIAS_PAD_E_VCLAMP_REF BIT(0) + +#define MIPI_CAL_BIAS_PAD_DRV_DN_REF(x) (((x) & 0x7) << 16) +#define MIPI_CAL_BIAS_PAD_DRV_UP_REF(x) (((x) & 0x7) << 8) + +#define MIPI_CAL_BIAS_PAD_VCLAMP(x)(((x) & 0x7) << 16) +#define MIPI_CAL_BIAS_PAD_VAUXP(x) (((x) & 0x7) << 4) +#define MIPI_CAL_BIAS_PAD_PDVREG BIT(1) + +struct tegra_mipi_priv { + struct mipi_ctlr*mipi; + struct clk *mipi_cal; +}; + +static int tegra_mipi_calibrate(struct udevice *dev, int offset, const void *buf, + int size) +{ + struct tegra_mipi_priv *priv = dev_get_priv(dev); + u32 value; + + value = MIPI_CAL_BIAS_PAD_DRV_DN_REF(0x2) | + MIPI_CAL_BIAS_PAD_DRV_UP_REF(0x0); + writel(value, >mipi->mipi_cal_bias_pad_cfg1); + + value = readl(>mipi->mipi_cal_bias_pad_cfg2); + value &= ~MIPI_CAL_BIAS_PAD_VCLAMP(0x7); + value &= ~MIPI_CAL_BIAS_PAD_VAUXP(0x7); + writel(value, >mipi->mipi_cal_bias_pad_cfg2); + + value = MIPI_CAL_OVERIDE(0x0) | MIPI_CAL_SEL(0x1) | + MIPI_CAL_HSPDOS(0x0) | MIPI_CAL_HSPUOS(0x4) | + MIPI_CAL_TERMOS(0x5); + writel(value, >mipi->mipi_cal_config_dsia); + writel(value, >mipi->mipi_cal_config_dsib); + + /* Deselect PAD C */ + value = readl(>mipi->mipi_cal_config_dsic); + value &= ~(MIPI_CAL_SEL(0x1)); + writel(value, >mipi->mipi_cal_config_dsic); + + /* Deselect PAD D */ + value = readl(>mipi->mipi_cal_config_dsid); + value &= ~(MIPI_CAL_SEL(0x1)); + writel(value, >mipi->mipi_cal_config_dsid); + + value = readl(>mipi->mipi_cal_ctrl); + value &= ~MIPI_CAL_CTRL_NOISE_FILTER(0xf); + value &= ~MIPI_CAL_CTRL_PRESCALE(0x3); + value |= MIPI_CAL_CTRL_NOISE_FILTER(0xa) | +MIPI_CAL_CTRL_PRESCALE(0x2) | +MIPI_CAL_CTRL_CLKEN_OVR; + writel(value, >mipi->mipi_cal_ctrl); + + /* clear any pending status bits */ + value = readl(>mipi->mipi_cal_status); + writel(value, >mipi->mipi_cal_
[PATCH v3 07/10] video: tegra20: dc: add powergate
Add powergate use on T114 to complete resetting of DC. Signed-off-by: Svyatoslav Ryhel --- drivers/video/tegra20/tegra-dc.c | 27 +++ 1 file changed, 27 insertions(+) diff --git a/drivers/video/tegra20/tegra-dc.c b/drivers/video/tegra20/tegra-dc.c index 35abb6fe46..9a18e38cd8 100644 --- a/drivers/video/tegra20/tegra-dc.c +++ b/drivers/video/tegra20/tegra-dc.c @@ -22,6 +22,7 @@ #include #include #include +#include #include #include "tegra-dc.h" @@ -32,6 +33,7 @@ DECLARE_GLOBAL_DATA_PTR; struct tegra_dc_soc_info { bool has_timer; bool has_rgb; + bool has_pgate; }; /* Information about the display controller */ @@ -360,6 +362,28 @@ static int tegra_lcd_probe(struct udevice *dev) clock_disable(priv->dc_clk[0]); + if (priv->soc->has_pgate) { + uint powergate; + + if (priv->pipe) + powergate = TEGRA_POWERGATE_DISB; + else + powergate = TEGRA_POWERGATE_DIS; + + ret = tegra_powergate_power_off(powergate); + if (ret < 0) { + log_err("failed to power off DISP gate: %d", ret); + return ret; + } + + ret = tegra_powergate_sequence_power_up(powergate, + priv->dc_clk[0]); + if (ret < 0) { + log_err("failed to power up DISP gate: %d", ret); + return ret; + } + } + /* Reset everything set before */ reset_assert(_ctl); mdelay(4); @@ -510,16 +534,19 @@ 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, + .has_pgate = false, }; static const struct tegra_dc_soc_info tegra30_dc_soc_info = { .has_timer = false, .has_rgb = true, + .has_pgate = false, }; static const struct tegra_dc_soc_info tegra114_dc_soc_info = { .has_timer = false, .has_rgb = false, + .has_pgate = true, }; static const struct udevice_id tegra_lcd_ids[] = { -- 2.40.1
[PATCH v3 06/10] video: tegra20: dc: add reset support
Implement reset use to discard any changes which could have been applied to DC before and can interfere with current configuration. Tested-by: Agneli # Toshiba AC100 T20 Tested-by: Robert Eckelmann # ASUS TF101 Tested-by: Andreas Westman Dorcsak # ASUS Grouper E1565 Tested-by: Ion Agorria # HTC One X Tested-by: Svyatoslav Ryhel # Nvidia Tegratab T114 Signed-off-by: Svyatoslav Ryhel --- drivers/video/tegra20/tegra-dc.c | 17 + 1 file changed, 17 insertions(+) diff --git a/drivers/video/tegra20/tegra-dc.c b/drivers/video/tegra20/tegra-dc.c index 56a23b3c97..35abb6fe46 100644 --- a/drivers/video/tegra20/tegra-dc.c +++ b/drivers/video/tegra20/tegra-dc.c @@ -10,7 +10,9 @@ #include #include #include +#include #include +#include #include #include #include @@ -342,6 +344,7 @@ static int tegra_lcd_probe(struct udevice *dev) struct video_uc_plat *plat = dev_get_uclass_plat(dev); struct video_priv *uc_priv = dev_get_uclass_priv(dev); struct tegra_lcd_priv *priv = dev_get_priv(dev); + struct reset_ctl reset_ctl; int ret; /* Initialize the Tegra display controller */ @@ -349,6 +352,20 @@ static int tegra_lcd_probe(struct udevice *dev) funcmux_select(PERIPH_ID_DISP1, FUNCMUX_DEFAULT); #endif + ret = reset_get_by_name(dev, "dc", _ctl); + if (ret) { + log_err("reset_get_by_name() failed: %d\n", ret); + return ret; + } + + clock_disable(priv->dc_clk[0]); + + /* Reset everything set before */ + reset_assert(_ctl); + mdelay(4); + reset_deassert(_ctl); + mdelay(4); + if (tegra_display_probe(priv, (void *)plat->base)) { debug("%s: Failed to probe display driver\n", __func__); return -1; -- 2.40.1
[PATCH v3 04/10] video: tegra20: dc: pass DC id to internal devices
Tegra SoC has 2 independent display controllers called DC_A and DC_B, they are handled differently by internal video devices like DSI and HDMI controllers so it is important for last to know which display controller is used to properly set up registers. To achieve this, a pipe field was added to pdata to pass display controller id to internal Tegra SoC devices. Tested-by: Agneli # Toshiba AC100 T20 Tested-by: Robert Eckelmann # ASUS TF101 Tested-by: Andreas Westman Dorcsak # ASUS Grouper E1565 Tested-by: Ion Agorria # HTC One X Tested-by: Svyatoslav Ryhel # Nvidia Tegratab T114 Signed-off-by: Svyatoslav Ryhel --- drivers/video/tegra20/tegra-dc.c | 6 ++ drivers/video/tegra20/tegra-dc.h | 3 +++ 2 files changed, 9 insertions(+) diff --git a/drivers/video/tegra20/tegra-dc.c b/drivers/video/tegra20/tegra-dc.c index 5d8874f323..0e94e665ef 100644 --- a/drivers/video/tegra20/tegra-dc.c +++ b/drivers/video/tegra20/tegra-dc.c @@ -45,6 +45,7 @@ struct tegra_lcd_priv { unsigned pixel_clock; /* Pixel clock in Hz */ int dc_clk[2]; /* Contains clk and its parent */ bool rotation; /* 180 degree panel turn */ + bool pipe; /* DC controller: 0 for A, 1 for B */ }; enum { @@ -406,6 +407,9 @@ static int tegra_lcd_of_to_plat(struct udevice *dev) priv->rotation = dev_read_bool(dev, "nvidia,180-rotation"); + if (!strcmp(dev->name, TEGRA_DC_B)) + priv->pipe = 1; + rgb = fdt_subnode_offset(blob, node, "rgb"); if (rgb < 0) { debug("%s: Cannot find rgb subnode for '%s' (ret=%d)\n", @@ -431,12 +435,14 @@ static int tegra_lcd_of_to_plat(struct udevice *dev) return ret; } + /* 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, >timing); diff --git a/drivers/video/tegra20/tegra-dc.h b/drivers/video/tegra20/tegra-dc.h index 5c05221038..75fc0fa4de 100644 --- a/drivers/video/tegra20/tegra-dc.h +++ b/drivers/video/tegra20/tegra-dc.h @@ -14,12 +14,15 @@ /* arch-tegra/dc exists only because T124 uses it */ #include +#define TEGRA_DC_A "dc@5420" +#define TEGRA_DC_B "dc@5424" #define TEGRA_DSI_A"dsi@5430" #define TEGRA_DSI_B"dsi@5440" struct tegra_dc_plat { struct udevice *dev;/* Display controller device */ struct dc_ctlr *dc; /* Display controller regmap */ + bool pipe; /* DC number: 0 for A, 1 for B */ }; /* This holds information about a window which can be displayed */ -- 2.40.1
[PATCH v3 05/10] video: tegra20: dc: add PLLD2 parent support
T30+ SOC have second PLLD - PLLD2 which can be actively used by DC and act as main DISP1/2 clock parent. Tested-by: Agneli # Toshiba AC100 T20 Tested-by: Robert Eckelmann # ASUS TF101 Tested-by: Andreas Westman Dorcsak # ASUS Grouper E1565 Tested-by: Ion Agorria # HTC One X Tested-by: Svyatoslav Ryhel # Nvidia Tegratab T114 Signed-off-by: Svyatoslav Ryhel --- drivers/video/tegra20/tegra-dc.c | 6 ++ 1 file changed, 6 insertions(+) diff --git a/drivers/video/tegra20/tegra-dc.c b/drivers/video/tegra20/tegra-dc.c index 0e94e665ef..56a23b3c97 100644 --- a/drivers/video/tegra20/tegra-dc.c +++ b/drivers/video/tegra20/tegra-dc.c @@ -304,6 +304,12 @@ static int tegra_display_probe(struct tegra_lcd_priv *priv, if (priv->dc_clk[1] == CLOCK_ID_DISPLAY) rate /= 2; +#ifndef CONFIG_TEGRA20 + /* PLLD2 obeys same rules as PLLD but it is present only on T30+ */ + if (priv->dc_clk[1] == CLOCK_ID_DISPLAY2) + rate /= 2; +#endif + /* * HOST1X is init by default at 150MHz with PLLC as parent */ -- 2.40.1
[PATCH v3 03/10] video: tegra20: consolidate DC header
Consolidate HD headers and place the result into video/tegra20 since it is used only by devices from this directory. Tested-by: Agneli # Toshiba AC100 T20 Tested-by: Robert Eckelmann # ASUS TF101 Tested-by: Andreas Westman Dorcsak # ASUS Grouper E1565 Tested-by: Ion Agorria # HTC One X Tested-by: Svyatoslav Ryhel # Nvidia Tegratab T114 Signed-off-by: Svyatoslav Ryhel --- arch/arm/include/asm/arch-tegra/dc.h | 8 arch/arm/include/asm/arch-tegra114/display.h | 28 - arch/arm/include/asm/arch-tegra20/display.h | 28 - arch/arm/include/asm/arch-tegra30/display.h | 28 - drivers/video/tegra20/tegra-dc.c | 3 +- drivers/video/tegra20/tegra-dc.h | 41 drivers/video/tegra20/tegra-dsi.c| 2 +- drivers/video/tegra20/tegra-pwm-backlight.c | 3 +- 8 files changed, 46 insertions(+), 95 deletions(-) delete mode 100644 arch/arm/include/asm/arch-tegra114/display.h delete mode 100644 arch/arm/include/asm/arch-tegra20/display.h delete mode 100644 arch/arm/include/asm/arch-tegra30/display.h create mode 100644 drivers/video/tegra20/tegra-dc.h diff --git a/arch/arm/include/asm/arch-tegra/dc.h b/arch/arm/include/asm/arch-tegra/dc.h index 7613d84f22..6444af2993 100644 --- a/arch/arm/include/asm/arch-tegra/dc.h +++ b/arch/arm/include/asm/arch-tegra/dc.h @@ -569,12 +569,4 @@ enum { #define DC_N_WINDOWS 5 #define DC_REG_SAVE_SPACE (DC_N_WINDOWS + 5) -#define TEGRA_DSI_A"dsi@5430" -#define TEGRA_DSI_B"dsi@5440" - -struct tegra_dc_plat { - struct udevice *dev;/* Display controller device */ - struct dc_ctlr *dc; /* Display controller regmap */ -}; - #endif /* __ASM_ARCH_TEGRA_DC_H */ diff --git a/arch/arm/include/asm/arch-tegra114/display.h b/arch/arm/include/asm/arch-tegra114/display.h deleted file mode 100644 index 9411525799..00 --- a/arch/arm/include/asm/arch-tegra114/display.h +++ /dev/null @@ -1,28 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ -/* - * (C) Copyright 2010 - * NVIDIA Corporation - */ - -#ifndef __ASM_ARCH_TEGRA_DISPLAY_H -#define __ASM_ARCH_TEGRA_DISPLAY_H - -#include - -/* This holds information about a window which can be displayed */ -struct disp_ctl_win { - enum win_color_depth_id fmt;/* Color depth/format */ - unsigned intbpp;/* Bits per pixel */ - phys_addr_t phys_addr; /* Physical address in memory */ - unsigned intx; /* Horizontal address offset (bytes) */ - unsigned inty; /* Veritical address offset (bytes) */ - unsigned intw; /* Width of source window */ - unsigned inth; /* Height of source window */ - unsigned intstride; /* Number of bytes per line */ - unsigned intout_x; /* Left edge of output window (col) */ - unsigned intout_y; /* Top edge of output window (row) */ - unsigned intout_w; /* Width of output window in pixels */ - unsigned intout_h; /* Height of output window in pixels */ -}; - -#endif /*__ASM_ARCH_TEGRA_DISPLAY_H*/ diff --git a/arch/arm/include/asm/arch-tegra20/display.h b/arch/arm/include/asm/arch-tegra20/display.h deleted file mode 100644 index e7b3cffd46..00 --- a/arch/arm/include/asm/arch-tegra20/display.h +++ /dev/null @@ -1,28 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ -/* - * (C) Copyright 2010 - * NVIDIA Corporation - */ - -#ifndef __ASM_ARCH_TEGRA_DISPLAY_H -#define __ASM_ARCH_TEGRA_DISPLAY_H - -#include - -/* This holds information about a window which can be displayed */ -struct disp_ctl_win { - enum win_color_depth_id fmt;/* Color depth/format */ - unsignedbpp;/* Bits per pixel */ - phys_addr_t phys_addr; /* Physical address in memory */ - unsignedx; /* Horizontal address offset (bytes) */ - unsignedy; /* Veritical address offset (bytes) */ - unsignedw; /* Width of source window */ - unsignedh; /* Height of source window */ - unsignedstride; /* Number of bytes per line */ - unsignedout_x; /* Left edge of output window (col) */ - unsignedout_y; /* Top edge of output window (row) */ - unsignedout_w; /* Width of output window in pixels */ - unsignedout_h; /* Height of output window in pixels */ -}; - -#endif /*__ASM_ARCH_TEGRA_DISPLAY_H*/ diff --git a/arch/arm/include/asm/arch-tegra30/display.h b/arch/arm/include/asm/arch-tegra30/display.h deleted file mode 100644 index 9411525799..00 --- a/arch/arm/include/asm/arch-tegra30/display.h +++ /dev/null @@ -1,28 +0,0 @@ -/* SPDX-License
[PATCH v3 01/10] video: tegra20: dc: diverge DC per-SOC
Diverge DC driver setup to better fit each of supported generations of Tegra SOC. Tested-by: Agneli # Toshiba AC100 T20 Tested-by: Robert Eckelmann # ASUS TF101 Tested-by: Andreas Westman Dorcsak # ASUS Grouper E1565 Tested-by: Ion Agorria # HTC One X Tested-by: Svyatoslav Ryhel # Nvidia Tegratab T114 Signed-off-by: Svyatoslav Ryhel --- arch/arm/dts/tegra114-u-boot.dtsi| 13 +++ arch/arm/dts/tegra114.dtsi | 4 +- arch/arm/dts/tegra30-u-boot.dtsi | 4 + arch/arm/dts/tegra30.dtsi| 2 +- arch/arm/include/asm/arch-tegra114/display.h | 28 + arch/arm/include/asm/arch-tegra114/pwm.h | 13 +++ drivers/video/tegra20/tegra-dc.c | 107 +-- 7 files changed, 133 insertions(+), 38 deletions(-) create mode 100644 arch/arm/include/asm/arch-tegra114/display.h create mode 100644 arch/arm/include/asm/arch-tegra114/pwm.h diff --git a/arch/arm/dts/tegra114-u-boot.dtsi b/arch/arm/dts/tegra114-u-boot.dtsi index 7c11972552..6a02714a25 100644 --- a/arch/arm/dts/tegra114-u-boot.dtsi +++ b/arch/arm/dts/tegra114-u-boot.dtsi @@ -1,3 +1,16 @@ #include #include "tegra-u-boot.dtsi" + +/ { + host1x@5000 { + bootph-all; + dc@5420 { + bootph-all; + }; + + dc@5424 { + bootph-all; + }; + }; +}; diff --git a/arch/arm/dts/tegra114.dtsi b/arch/arm/dts/tegra114.dtsi index 68ee7f3165..250d692f6b 100644 --- a/arch/arm/dts/tegra114.dtsi +++ b/arch/arm/dts/tegra114.dtsi @@ -42,7 +42,7 @@ }; dc@5420 { - compatible = "nvidia,tegra114-dc", "nvidia,tegra20-dc"; + compatible = "nvidia,tegra114-dc"; reg = <0x5420 0x0004>; interrupts = ; clocks = <_car TEGRA114_CLK_DISP1>, @@ -61,7 +61,7 @@ }; dc@5424 { - compatible = "nvidia,tegra114-dc", "nvidia,tegra20-dc"; + compatible = "nvidia,tegra114-dc"; reg = <0x5424 0x0004>; interrupts = ; clocks = <_car TEGRA114_CLK_DISP2>, diff --git a/arch/arm/dts/tegra30-u-boot.dtsi b/arch/arm/dts/tegra30-u-boot.dtsi index 3038227dbe..6a02714a25 100644 --- a/arch/arm/dts/tegra30-u-boot.dtsi +++ b/arch/arm/dts/tegra30-u-boot.dtsi @@ -8,5 +8,9 @@ dc@5420 { bootph-all; }; + + dc@5424 { + bootph-all; + }; }; }; diff --git a/arch/arm/dts/tegra30.dtsi b/arch/arm/dts/tegra30.dtsi index f198bc0edb..1177e2ab1f 100644 --- a/arch/arm/dts/tegra30.dtsi +++ b/arch/arm/dts/tegra30.dtsi @@ -158,7 +158,7 @@ }; dc@5420 { - compatible = "nvidia,tegra30-dc", "nvidia,tegra20-dc"; + compatible = "nvidia,tegra30-dc"; reg = <0x5420 0x0004>; interrupts = ; clocks = <_car TEGRA30_CLK_DISP1>, diff --git a/arch/arm/include/asm/arch-tegra114/display.h b/arch/arm/include/asm/arch-tegra114/display.h new file mode 100644 index 00..9411525799 --- /dev/null +++ b/arch/arm/include/asm/arch-tegra114/display.h @@ -0,0 +1,28 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * (C) Copyright 2010 + * NVIDIA Corporation + */ + +#ifndef __ASM_ARCH_TEGRA_DISPLAY_H +#define __ASM_ARCH_TEGRA_DISPLAY_H + +#include + +/* This holds information about a window which can be displayed */ +struct disp_ctl_win { + enum win_color_depth_id fmt;/* Color depth/format */ + unsigned intbpp;/* Bits per pixel */ + phys_addr_t phys_addr; /* Physical address in memory */ + unsigned intx; /* Horizontal address offset (bytes) */ + unsigned inty; /* Veritical address offset (bytes) */ + unsigned intw; /* Width of source window */ + unsigned inth; /* Height of source window */ + unsigned intstride; /* Number of bytes per line */ + unsigned intout_x; /* Left edge of output window (col) */ + unsigned intout_y; /* Top edge of output window (row) */ + unsigned intout_w; /* Width of output window in pixels */ + unsigned intout_h; /* Height of output window in pixels */ +}; + +#endif /*__ASM_ARCH_TEGRA_DISPLAY_H*/ diff --git a/arch/arm/include/asm/arch-tegra114/pwm.h b/arch/arm/include/asm/arch-tegra114/pwm.h new file mode 100644 index 00..af39151803 --
[PATCH v3 02/10] video: tegra20: dc: fix image shift on rotated panels
Subtracting 1 from x and y fixes image shifting on rotated panels. Tested-by: Robert Eckelmann # ASUS Grouper E1565 Signed-off-by: Svyatoslav Ryhel --- drivers/video/tegra20/tegra-dc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/video/tegra20/tegra-dc.c b/drivers/video/tegra20/tegra-dc.c index 7605e77bc1..bcc2748623 100644 --- a/drivers/video/tegra20/tegra-dc.c +++ b/drivers/video/tegra20/tegra-dc.c @@ -242,8 +242,8 @@ static int setup_window(struct tegra_lcd_priv *priv, struct disp_ctl_win *win) { if (priv->rotation) { - win->x = priv->width * 2; - win->y = priv->height; + win->x = priv->width * 2 - 1; + win->y = priv->height - 1; } else { win->x = 0; win->y = 0; -- 2.40.1