- More Tegra video improvements
This commit is contained in:
Tom Rini 2025-03-26 14:07:37 -06:00
commit 4adbf64ff8
56 changed files with 4721 additions and 491 deletions

View file

@ -113,6 +113,7 @@ dtb-$(CONFIG_ARCH_TEGRA) += \
tegra30-lg-p880.dtb \
tegra30-lg-p895.dtb \
tegra30-microsoft-surface-rt.dtb \
tegra30-ouya.dtb \
tegra30-tec-ng.dtb \
tegra30-wexler-qc750.dtb \
tegra114-dalmore.dtb \

View file

@ -215,8 +215,8 @@
nvidia,pull = <TEGRA_PIN_PULL_NONE>;
nvidia,tristate = <TEGRA_PIN_DISABLE>;
nvidia,enable-input = <TEGRA_PIN_ENABLE>;
nvidia,lock = <1>;
nvidia,open-drain = <1>;
nvidia,lock = <TEGRA_PIN_DISABLE>;
nvidia,open-drain = <TEGRA_PIN_DISABLE>;
};
gen2-i2c {
nvidia,pins = "gen2_i2c_scl_pt5",
@ -225,8 +225,8 @@
nvidia,pull = <TEGRA_PIN_PULL_NONE>;
nvidia,tristate = <TEGRA_PIN_DISABLE>;
nvidia,enable-input = <TEGRA_PIN_ENABLE>;
nvidia,lock = <1>;
nvidia,open-drain = <1>;
nvidia,lock = <TEGRA_PIN_DISABLE>;
nvidia,open-drain = <TEGRA_PIN_DISABLE>;
};
cam-i2c {
nvidia,pins = "cam_i2c_scl_pbb1",
@ -235,8 +235,8 @@
nvidia,pull = <TEGRA_PIN_PULL_NONE>;
nvidia,tristate = <TEGRA_PIN_DISABLE>;
nvidia,enable-input = <TEGRA_PIN_ENABLE>;
nvidia,lock = <1>;
nvidia,open-drain = <1>;
nvidia,lock = <TEGRA_PIN_DISABLE>;
nvidia,open-drain = <TEGRA_PIN_DISABLE>;
};
ddc-i2c {
nvidia,pins = "ddc_scl_pv4",
@ -253,7 +253,7 @@
nvidia,pull = <TEGRA_PIN_PULL_NONE>;
nvidia,tristate = <TEGRA_PIN_DISABLE>;
nvidia,enable-input = <TEGRA_PIN_ENABLE>;
nvidia,open-drain = <1>;
nvidia,open-drain = <TEGRA_PIN_DISABLE>;
};
dsi-b {

View file

@ -34,20 +34,10 @@
host1x@50000000 {
dc@54200000 {
clocks = <&tegra_car TEGRA30_CLK_DISP1>,
<&tegra_car TEGRA30_CLK_PLL_D_OUT0>;
rgb {
status = "okay";
nvidia,panel = <&hdmi>;
};
status = "disabled";
};
hdmi: hdmi@54280000 {
clocks = <&tegra_car TEGRA30_CLK_HDMI>,
<&tegra_car TEGRA30_CLK_PLL_D_OUT0>;
status = "okay";
hdmi-supply = <&hdmi_5v0_sys>;
@ -118,8 +108,8 @@
nvidia,pull = <TEGRA_PIN_PULL_NONE>;
nvidia,tristate = <TEGRA_PIN_DISABLE>;
nvidia,enable-input = <TEGRA_PIN_ENABLE>;
nvidia,lock = <1>;
nvidia,io-reset = <1>;
nvidia,lock = <TEGRA_PIN_DISABLE>;
nvidia,io-reset = <TEGRA_PIN_DISABLE>;
};
/* SDMMC3 pinmux */
@ -203,7 +193,7 @@
nvidia,tristate = <TEGRA_PIN_DISABLE>;
nvidia,enable-input = <TEGRA_PIN_ENABLE>;
nvidia,open-drain = <TEGRA_PIN_ENABLE>;
nvidia,lock = <1>;
nvidia,lock = <TEGRA_PIN_DISABLE>;
};
gen2_i2c {
nvidia,pins = "gen2_i2c_scl_pt5",
@ -213,7 +203,7 @@
nvidia,tristate = <TEGRA_PIN_DISABLE>;
nvidia,enable-input = <TEGRA_PIN_ENABLE>;
nvidia,open-drain = <TEGRA_PIN_ENABLE>;
nvidia,lock = <1>;
nvidia,lock = <TEGRA_PIN_DISABLE>;
};
cam_i2c {
nvidia,pins = "cam_i2c_scl_pbb1",
@ -223,7 +213,7 @@
nvidia,tristate = <TEGRA_PIN_DISABLE>;
nvidia,enable-input = <TEGRA_PIN_ENABLE>;
nvidia,open-drain = <TEGRA_PIN_ENABLE>;
nvidia,lock = <1>;
nvidia,lock = <TEGRA_PIN_DISABLE>;
};
ddc_i2c {
nvidia,pins = "ddc_scl_pv4",
@ -232,7 +222,7 @@
nvidia,pull = <TEGRA_PIN_PULL_NONE>;
nvidia,tristate = <TEGRA_PIN_DISABLE>;
nvidia,enable-input = <TEGRA_PIN_ENABLE>;
nvidia,lock = <1>;
nvidia,lock = <TEGRA_PIN_DISABLE>;
};
pwr_i2c {
nvidia,pins = "pwr_i2c_scl_pz6",
@ -242,7 +232,7 @@
nvidia,tristate = <TEGRA_PIN_DISABLE>;
nvidia,enable-input = <TEGRA_PIN_ENABLE>;
nvidia,open-drain = <TEGRA_PIN_ENABLE>;
nvidia,lock = <1>;
nvidia,lock = <TEGRA_PIN_DISABLE>;
};
hotplug_i2c {
nvidia,pins = "pu4";
@ -260,7 +250,7 @@
nvidia,tristate = <TEGRA_PIN_DISABLE>;
nvidia,enable-input = <TEGRA_PIN_ENABLE>;
nvidia,open-drain = <TEGRA_PIN_ENABLE>;
nvidia,lock = <1>;
nvidia,lock = <TEGRA_PIN_DISABLE>;
};
hdmi_hpd {
nvidia,pins = "hdmi_int_pn7";
@ -632,8 +622,8 @@
nvidia,pull = <TEGRA_PIN_PULL_UP>;
nvidia,tristate = <TEGRA_PIN_ENABLE>;
nvidia,enable-input = <TEGRA_PIN_ENABLE>;
nvidia,lock = <1>;
nvidia,io-reset = <1>;
nvidia,lock = <TEGRA_PIN_DISABLE>;
nvidia,io-reset = <TEGRA_PIN_DISABLE>;
};
/* GPIO keys pinmux */
@ -718,8 +708,8 @@
nvidia,pull = <TEGRA_PIN_PULL_NONE>;
nvidia,tristate = <TEGRA_PIN_DISABLE>;
nvidia,enable-input = <TEGRA_PIN_ENABLE>;
nvidia,lock = <1>;
nvidia,io-reset = <1>;
nvidia,lock = <TEGRA_PIN_DISABLE>;
nvidia,io-reset = <TEGRA_PIN_DISABLE>;
};
vi_d10_pt2 {
nvidia,pins = "vi_d10_pt2",
@ -838,8 +828,8 @@
nvidia,pull = <TEGRA_PIN_PULL_NONE>;
nvidia,tristate = <TEGRA_PIN_DISABLE>;
nvidia,enable-input = <TEGRA_PIN_DISABLE>;
nvidia,lock = <1>;
nvidia,io-reset = <1>;
nvidia,lock = <TEGRA_PIN_DISABLE>;
nvidia,io-reset = <TEGRA_PIN_DISABLE>;
};
vi_mclk_pt1 {
nvidia,pins = "vi_mclk_pt1";

View file

@ -90,8 +90,8 @@
nvidia,pull = <TEGRA_PIN_PULL_UP>;
nvidia,tristate = <TEGRA_PIN_DISABLE>;
nvidia,enable-input = <TEGRA_PIN_ENABLE>;
nvidia,lock = <1>;
nvidia,io-reset = <1>;
nvidia,lock = <TEGRA_PIN_DISABLE>;
nvidia,io-reset = <TEGRA_PIN_DISABLE>;
};
/* SDMMC2 pinmux */
@ -107,8 +107,8 @@
nvidia,pull = <TEGRA_PIN_PULL_NONE>;
nvidia,tristate = <TEGRA_PIN_DISABLE>;
nvidia,enable-input = <TEGRA_PIN_ENABLE>;
nvidia,lock = <1>;
nvidia,io-reset = <1>;
nvidia,lock = <TEGRA_PIN_DISABLE>;
nvidia,io-reset = <TEGRA_PIN_DISABLE>;
};
/* SDMMC3 pinmux */
@ -142,8 +142,8 @@
nvidia,pull = <TEGRA_PIN_PULL_NONE>;
nvidia,tristate = <TEGRA_PIN_DISABLE>;
nvidia,enable-input = <TEGRA_PIN_ENABLE>;
nvidia,lock = <1>;
nvidia,io-reset = <1>;
nvidia,lock = <TEGRA_PIN_DISABLE>;
nvidia,io-reset = <TEGRA_PIN_DISABLE>;
};
sdmmc4_cmd {
nvidia,pins = "sdmmc4_cmd_pt7",
@ -159,8 +159,8 @@
nvidia,pull = <TEGRA_PIN_PULL_UP>;
nvidia,tristate = <TEGRA_PIN_DISABLE>;
nvidia,enable-input = <TEGRA_PIN_ENABLE>;
nvidia,lock = <1>;
nvidia,io-reset = <1>;
nvidia,lock = <TEGRA_PIN_DISABLE>;
nvidia,io-reset = <TEGRA_PIN_DISABLE>;
};
sdmmc4_rst_n {
nvidia,pins = "sdmmc4_rst_n_pcc3";
@ -186,7 +186,7 @@
nvidia,tristate = <TEGRA_PIN_DISABLE>;
nvidia,enable-input = <TEGRA_PIN_ENABLE>;
nvidia,open-drain = <TEGRA_PIN_ENABLE>;
nvidia,lock = <0>;
nvidia,lock = <TEGRA_PIN_DISABLE>;
};
gen2_i2c {
nvidia,pins = "gen2_i2c_scl_pt5",
@ -196,7 +196,7 @@
nvidia,tristate = <TEGRA_PIN_DISABLE>;
nvidia,enable-input = <TEGRA_PIN_ENABLE>;
nvidia,open-drain = <TEGRA_PIN_ENABLE>;
nvidia,lock = <0>;
nvidia,lock = <TEGRA_PIN_DISABLE>;
};
cam_i2c {
nvidia,pins = "cam_i2c_scl_pbb1",
@ -206,7 +206,7 @@
nvidia,tristate = <TEGRA_PIN_DISABLE>;
nvidia,enable-input = <TEGRA_PIN_ENABLE>;
nvidia,open-drain = <TEGRA_PIN_ENABLE>;
nvidia,lock = <0>;
nvidia,lock = <TEGRA_PIN_DISABLE>;
};
ddc_i2c {
nvidia,pins = "ddc_scl_pv4",
@ -215,7 +215,7 @@
nvidia,pull = <TEGRA_PIN_PULL_NONE>;
nvidia,tristate = <TEGRA_PIN_DISABLE>;
nvidia,enable-input = <TEGRA_PIN_ENABLE>;
nvidia,lock = <0>;
nvidia,lock = <TEGRA_PIN_DISABLE>;
};
pwr_i2c {
nvidia,pins = "pwr_i2c_scl_pz6",
@ -225,7 +225,7 @@
nvidia,tristate = <TEGRA_PIN_DISABLE>;
nvidia,enable-input = <TEGRA_PIN_ENABLE>;
nvidia,open-drain = <TEGRA_PIN_ENABLE>;
nvidia,lock = <0>;
nvidia,lock = <TEGRA_PIN_DISABLE>;
};
hotplug_i2c {
nvidia,pins = "pu4";
@ -243,7 +243,7 @@
nvidia,tristate = <TEGRA_PIN_DISABLE>;
nvidia,enable-input = <TEGRA_PIN_ENABLE>;
nvidia,open-drain = <TEGRA_PIN_ENABLE>;
nvidia,lock = <0>;
nvidia,lock = <TEGRA_PIN_DISABLE>;
};
hdmi_hpd {
nvidia,pins = "hdmi_int_pn7";
@ -613,8 +613,8 @@
nvidia,pull = <TEGRA_PIN_PULL_UP>;
nvidia,tristate = <TEGRA_PIN_ENABLE>;
nvidia,enable-input = <TEGRA_PIN_ENABLE>;
nvidia,lock = <1>;
nvidia,io-reset = <1>;
nvidia,lock = <TEGRA_PIN_DISABLE>;
nvidia,io-reset = <TEGRA_PIN_DISABLE>;
};
/* GPIO keys pinmux */
@ -701,8 +701,8 @@
nvidia,pull = <TEGRA_PIN_PULL_NONE>;
nvidia,tristate = <TEGRA_PIN_DISABLE>;
nvidia,enable-input = <TEGRA_PIN_ENABLE>;
nvidia,lock = <1>;
nvidia,io-reset = <1>;
nvidia,lock = <TEGRA_PIN_DISABLE>;
nvidia,io-reset = <TEGRA_PIN_DISABLE>;
};
pbb0 {
nvidia,pins = "pbb0";
@ -827,8 +827,8 @@
nvidia,pull = <TEGRA_PIN_PULL_NONE>;
nvidia,tristate = <TEGRA_PIN_DISABLE>;
nvidia,enable-input = <TEGRA_PIN_DISABLE>;
nvidia,lock = <1>;
nvidia,io-reset = <1>;
nvidia,lock = <TEGRA_PIN_DISABLE>;
nvidia,io-reset = <TEGRA_PIN_DISABLE>;
};
vi_mclk_pt1 {
nvidia,pins = "vi_mclk_pt1";
@ -836,8 +836,8 @@
nvidia,pull = <TEGRA_PIN_PULL_UP>;
nvidia,tristate = <TEGRA_PIN_DISABLE>;
nvidia,enable-input = <TEGRA_PIN_ENABLE>;
nvidia,lock = <1>;
nvidia,io-reset = <1>;
nvidia,lock = <TEGRA_PIN_DISABLE>;
nvidia,io-reset = <TEGRA_PIN_DISABLE>;
};
jtag {

View file

@ -15,7 +15,14 @@
rgb {
status = "okay";
nvidia,panel = <&tc358768>;
/delete-property/ nvidia,panel;
port {
dpi_output: endpoint {
remote-endpoint = <&bridge_input>;
bus-width = <24>;
};
};
};
};
};
@ -118,38 +125,69 @@
vddio-supply = <&vdd_1v8_vio>;
vddmipi-supply = <&vdd_1v2_mipi>;
panel = <&panel>;
/*
* Panasonic VVX10F004B00 or HYDIS HV101WU1-1E1
* LCD SuperIPS+ Full HD panel.
*/
panel@1 {
compatible = "panasonic,vvx10f004b00";
reg = <1>;
power-supply = <&vdd_pnl_reg>;
backlight = <&backlight>;
display-timings {
timing@0 {
/* 1920x1200@60Hz */
clock-frequency = <154000000>;
hactive = <1920>;
hfront-porch = <48>;
hback-porch = <80>;
hsync-len = <32>;
hsync-active = <1>;
vactive = <1200>;
vfront-porch = <3>;
vback-porch = <26>;
vsync-len = <6>;
vsync-active = <1>;
};
};
port {
panel_input: endpoint {
remote-endpoint = <&bridge_output>;
};
};
};
ports {
#address-cells = <1>;
#size-cells = <0>;
port@0 {
reg = <0>;
bridge_input: endpoint {
remote-endpoint = <&dpi_output>;
bus-width = <24>;
};
};
port@1 {
reg = <1>;
bridge_output: endpoint {
remote-endpoint = <&panel_input>;
};
};
};
};
};
};
panel: panel {
compatible = "panasonic,vvx10f004b00";
power-supply = <&vdd_pnl_reg>;
backlight = <&backlight>;
/delete-property/ enable-gpios;
display-timings {
timing@0 {
/* 1920x1200@60Hz */
clock-frequency = <154000000>;
hactive = <1920>;
hfront-porch = <48>;
hback-porch = <80>;
hsync-len = <32>;
hsync-active = <1>;
vactive = <1200>;
vfront-porch = <3>;
vback-porch = <26>;
vsync-len = <6>;
vsync-active = <1>;
};
};
};
/delete-node/ panel;
vdd_1v2_mipi: regulator-mipi {
compatible = "regulator-fixed";

View file

@ -99,8 +99,8 @@
nvidia,pull = <TEGRA_PIN_PULL_NONE>;
nvidia,tristate = <TEGRA_PIN_DISABLE>;
nvidia,enable-input = <TEGRA_PIN_ENABLE>;
nvidia,lock = <1>;
nvidia,io-reset = <1>;
nvidia,lock = <TEGRA_PIN_DISABLE>;
nvidia,io-reset = <TEGRA_PIN_DISABLE>;
};
/* SDMMC3 pinmux */
@ -189,7 +189,7 @@
nvidia,tristate = <TEGRA_PIN_DISABLE>;
nvidia,enable-input = <TEGRA_PIN_ENABLE>;
nvidia,open-drain = <TEGRA_PIN_ENABLE>;
nvidia,lock = <1>;
nvidia,lock = <TEGRA_PIN_DISABLE>;
};
gen2_i2c {
@ -200,7 +200,7 @@
nvidia,tristate = <TEGRA_PIN_DISABLE>;
nvidia,enable-input = <TEGRA_PIN_ENABLE>;
nvidia,open-drain = <TEGRA_PIN_ENABLE>;
nvidia,lock = <1>;
nvidia,lock = <TEGRA_PIN_DISABLE>;
};
cam_i2c {
@ -211,7 +211,7 @@
nvidia,tristate = <TEGRA_PIN_DISABLE>;
nvidia,enable-input = <TEGRA_PIN_ENABLE>;
nvidia,open-drain = <TEGRA_PIN_ENABLE>;
nvidia,lock = <1>;
nvidia,lock = <TEGRA_PIN_DISABLE>;
};
ddc_i2c {
@ -221,7 +221,7 @@
nvidia,pull = <TEGRA_PIN_PULL_NONE>;
nvidia,tristate = <TEGRA_PIN_DISABLE>;
nvidia,enable-input = <TEGRA_PIN_ENABLE>;
nvidia,lock = <1>;
nvidia,lock = <TEGRA_PIN_DISABLE>;
};
pwr_i2c {
@ -232,7 +232,7 @@
nvidia,tristate = <TEGRA_PIN_DISABLE>;
nvidia,enable-input = <TEGRA_PIN_ENABLE>;
nvidia,open-drain = <TEGRA_PIN_ENABLE>;
nvidia,lock = <1>;
nvidia,lock = <TEGRA_PIN_DISABLE>;
};
hotplug_i2c {
@ -647,8 +647,8 @@
nvidia,pull = <TEGRA_PIN_PULL_UP>;
nvidia,tristate = <TEGRA_PIN_ENABLE>;
nvidia,enable-input = <TEGRA_PIN_ENABLE>;
nvidia,lock = <1>;
nvidia,io-reset = <1>;
nvidia,lock = <TEGRA_PIN_DISABLE>;
nvidia,io-reset = <TEGRA_PIN_DISABLE>;
};
/* GPIO keys pinmux */
@ -741,8 +741,8 @@
nvidia,pull = <TEGRA_PIN_PULL_NONE>;
nvidia,tristate = <TEGRA_PIN_DISABLE>;
nvidia,enable-input = <TEGRA_PIN_ENABLE>;
nvidia,lock = <1>;
nvidia,io-reset = <1>;
nvidia,lock = <TEGRA_PIN_DISABLE>;
nvidia,io-reset = <TEGRA_PIN_DISABLE>;
};
vi_d10_pt2 {
@ -879,8 +879,8 @@
nvidia,pull = <TEGRA_PIN_PULL_NONE>;
nvidia,tristate = <TEGRA_PIN_DISABLE>;
nvidia,enable-input = <TEGRA_PIN_DISABLE>;
nvidia,lock = <1>;
nvidia,io-reset = <1>;
nvidia,lock = <TEGRA_PIN_DISABLE>;
nvidia,io-reset = <TEGRA_PIN_DISABLE>;
};
vi_mclk_pt1 {

View file

@ -33,13 +33,11 @@
host1x@50000000 {
dc@54200000 {
clocks = <&tegra_car TEGRA30_CLK_DISP1>,
<&tegra_car TEGRA30_CLK_PLL_D_OUT0>;
backlight: backlight {
compatible = "nvidia,tegra-pwm-backlight";
rgb {
status = "okay";
nvidia,panel = <&dsia>;
nvidia,pwm-source = <1>;
nvidia,default-brightness = <0x8E>;
};
};
@ -1265,13 +1263,6 @@
nvidia,xcvr-lsrslew = <2>;
};
backlight: backlight {
compatible = "nvidia,tegra-pwm-backlight";
nvidia,pwm-source = <1>;
nvidia,default-brightness = <0x8E>;
};
/* PMIC has a built-in 32KHz oscillator which is used by PMC */
clk32k_in: clock-32k {
compatible = "fixed-clock";

View file

@ -109,8 +109,8 @@
nvidia,pull = <TEGRA_PIN_PULL_NONE>;
nvidia,tristate = <TEGRA_PIN_DISABLE>;
nvidia,enable-input = <TEGRA_PIN_ENABLE>;
nvidia,lock = <1>;
nvidia,io-reset = <1>;
nvidia,lock = <TEGRA_PIN_DISABLE>;
nvidia,io-reset = <TEGRA_PIN_DISABLE>;
};
sdmmc4-cmd {
nvidia,pins = "sdmmc4_cmd_pt7",
@ -127,8 +127,8 @@
nvidia,pull = <TEGRA_PIN_PULL_UP>;
nvidia,tristate = <TEGRA_PIN_DISABLE>;
nvidia,enable-input = <TEGRA_PIN_ENABLE>;
nvidia,lock = <1>;
nvidia,io-reset = <1>;
nvidia,lock = <TEGRA_PIN_DISABLE>;
nvidia,io-reset = <TEGRA_PIN_DISABLE>;
};
cam-mclk {
nvidia,pins = "cam_mclk_pcc0";
@ -147,7 +147,7 @@
nvidia,tristate = <TEGRA_PIN_DISABLE>;
nvidia,enable-input = <TEGRA_PIN_ENABLE>;
nvidia,open-drain = <TEGRA_PIN_ENABLE>;
nvidia,lock = <1>;
nvidia,lock = <TEGRA_PIN_DISABLE>;
};
gen2-i2c {
nvidia,pins = "gen2_i2c_scl_pt5",
@ -157,7 +157,7 @@
nvidia,tristate = <TEGRA_PIN_DISABLE>;
nvidia,enable-input = <TEGRA_PIN_ENABLE>;
nvidia,open-drain = <TEGRA_PIN_ENABLE>;
nvidia,lock = <1>;
nvidia,lock = <TEGRA_PIN_DISABLE>;
};
cam-i2c {
nvidia,pins = "cam_i2c_scl_pbb1",
@ -167,7 +167,7 @@
nvidia,tristate = <TEGRA_PIN_DISABLE>;
nvidia,enable-input = <TEGRA_PIN_ENABLE>;
nvidia,open-drain = <TEGRA_PIN_ENABLE>;
nvidia,lock = <1>;
nvidia,lock = <TEGRA_PIN_DISABLE>;
};
ddc-i2c {
nvidia,pins = "ddc_scl_pv4",
@ -176,7 +176,7 @@
nvidia,pull = <TEGRA_PIN_PULL_NONE>;
nvidia,tristate = <TEGRA_PIN_DISABLE>;
nvidia,enable-input = <TEGRA_PIN_ENABLE>;
nvidia,lock = <1>;
nvidia,lock = <TEGRA_PIN_DISABLE>;
};
pwr-i2c {
nvidia,pins = "pwr_i2c_scl_pz6",
@ -186,7 +186,7 @@
nvidia,tristate = <TEGRA_PIN_DISABLE>;
nvidia,enable-input = <TEGRA_PIN_ENABLE>;
nvidia,open-drain = <TEGRA_PIN_ENABLE>;
nvidia,lock = <1>;
nvidia,lock = <TEGRA_PIN_DISABLE>;
};
/* HDMI pinmux */
@ -724,8 +724,8 @@
nvidia,pull = <TEGRA_PIN_PULL_NONE>;
nvidia,tristate = <TEGRA_PIN_ENABLE>;
nvidia,enable-input = <TEGRA_PIN_ENABLE>;
nvidia,lock = <1>;
nvidia,io-reset = <1>;
nvidia,lock = <TEGRA_PIN_DISABLE>;
nvidia,io-reset = <TEGRA_PIN_DISABLE>;
};
vi-vsync-pd6 {
nvidia,pins = "vi_vsync_pd6",
@ -736,8 +736,8 @@
nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
nvidia,tristate = <TEGRA_PIN_ENABLE>;
nvidia,enable-input = <TEGRA_PIN_ENABLE>;
nvidia,lock = <1>;
nvidia,io-reset = <2>;
nvidia,lock = <TEGRA_PIN_DISABLE>;
nvidia,io-reset = <TEGRA_PIN_ENABLE>;
};
vi-hsync-pd7 {
nvidia,pins = "vi_hsync_pd7",
@ -749,8 +749,8 @@
nvidia,pull = <TEGRA_PIN_PULL_NONE>;
nvidia,tristate = <TEGRA_PIN_DISABLE>;
nvidia,enable-input = <TEGRA_PIN_DISABLE>;
nvidia,lock = <1>;
nvidia,io-reset = <1>;
nvidia,lock = <TEGRA_PIN_DISABLE>;
nvidia,io-reset = <TEGRA_PIN_DISABLE>;
};
vi-d2-pl0 {
nvidia,pins = "vi_d2_pl0",
@ -760,8 +760,8 @@
nvidia,pull = <TEGRA_PIN_PULL_UP>;
nvidia,tristate = <TEGRA_PIN_DISABLE>;
nvidia,enable-input = <TEGRA_PIN_ENABLE>;
nvidia,lock = <1>;
nvidia,io-reset = <1>;
nvidia,lock = <TEGRA_PIN_DISABLE>;
nvidia,io-reset = <TEGRA_PIN_DISABLE>;
};
vi-mclk-pt1 {
nvidia,pins = "vi_mclk_pt1";
@ -769,8 +769,8 @@
nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
nvidia,tristate = <TEGRA_PIN_ENABLE>;
nvidia,enable-input = <TEGRA_PIN_ENABLE>;
nvidia,lock = <1>;
nvidia,io-reset = <2>;
nvidia,lock = <TEGRA_PIN_DISABLE>;
nvidia,io-reset = <TEGRA_PIN_ENABLE>;
};
vi-d11-pt3 {
nvidia,pins = "vi_d11_pt3";
@ -778,8 +778,8 @@
nvidia,pull = <TEGRA_PIN_PULL_UP>;
nvidia,tristate = <TEGRA_PIN_ENABLE>;
nvidia,enable-input = <TEGRA_PIN_ENABLE>;
nvidia,lock = <1>;
nvidia,io-reset = <1>;
nvidia,lock = <TEGRA_PIN_DISABLE>;
nvidia,io-reset = <TEGRA_PIN_DISABLE>;
};
vi-d5-pl3 {
nvidia,pins = "vi_d5_pl3";
@ -787,8 +787,8 @@
nvidia,pull = <TEGRA_PIN_PULL_NONE>;
nvidia,tristate = <TEGRA_PIN_DISABLE>;
nvidia,enable-input = <TEGRA_PIN_ENABLE>;
nvidia,lock = <1>;
nvidia,io-reset = <1>;
nvidia,lock = <TEGRA_PIN_DISABLE>;
nvidia,io-reset = <TEGRA_PIN_DISABLE>;
};
/* PORT U */

View file

@ -101,6 +101,31 @@
};
};
spi@7000dc00 {
bridge-spi@2 {
/*
* JDI 4.57" 720x1280 DX12D100VM0EAA MIPI DSI panel
*/
panel@0 {
compatible = "jdi,dx12d100vm0eaa";
reg = <0>;
reset-gpios = <&gpio TEGRA_GPIO(W, 0) GPIO_ACTIVE_LOW>;
vdd-supply = <&vcc_3v0_lcd>;
vddio-supply = <&iovcc_1v8_lcd>;
backlight = <&backlight>;
port {
panel_input: endpoint {
remote-endpoint = <&bridge_output>;
};
};
};
};
};
sdmmc3: sdhci@78000400 {
status = "okay";
bus-width = <4>;
@ -118,13 +143,4 @@
linux,code = <KEY_UP>;
};
};
panel: panel {
compatible = "jdi,dx12d100vm0eaa";
enable-gpios = <&gpio TEGRA_GPIO(Y, 0) GPIO_ACTIVE_HIGH>;
reset-gpios = <&gpio TEGRA_GPIO(W, 0) GPIO_ACTIVE_HIGH>;
backlight = <&backlight>;
};
};

View file

@ -108,36 +108,37 @@
};
};
panel: panel {
compatible = "hitachi,tx13d100vm0eaa";
spi@7000dc00 {
bridge-spi@2 {
/*
* HITACHI/KOE 5" 768x1024 TX13D100VM0EAA MIPI DSI panel
*/
panel@0 {
compatible = "koe,tx13d100vm0eaa";
reg = <0>;
reset-gpios = <&gpio TEGRA_GPIO(W, 0) GPIO_ACTIVE_HIGH>;
reset-gpios = <&gpio TEGRA_GPIO(W, 0) GPIO_ACTIVE_LOW>;
renesas,gamma = <3>;
renesas,inversion;
renesas,contrast;
renesas,gamma = <3>;
renesas,inversion;
renesas,contrast;
vcc-supply = <&vcc_3v0_lcd>;
iovcc-supply = <&iovcc_1v8_lcd>;
vcc-supply = <&vcc_3v0_lcd>;
iovcc-supply = <&iovcc_1v8_lcd>;
backlight = <&backlight>;
backlight = <&backlight>;
port {
panel_input: endpoint {
remote-endpoint = <&bridge_output>;
};
};
};
};
};
vcc_3v0_lcd: regulator-lcd {
compatible = "regulator-fixed";
regulator-name = "vcc_3v0_lcd";
regulator-min-microvolt = <3000000>;
regulator-max-microvolt = <3000000>;
regulator-lcd3v {
gpio = <&gpio TEGRA_GPIO(BB, 0) GPIO_ACTIVE_HIGH>;
enable-active-high;
};
iovcc_1v8_lcd: regulator-lcdvio {
compatible = "regulator-fixed";
regulator-name = "iovcc_1v8_lcd";
regulator-min-microvolt = <1800000>;
regulator-max-microvolt = <1800000>;
gpio = <&gpio TEGRA_GPIO(Y, 0) GPIO_ACTIVE_HIGH>;
enable-active-high;
};
};

View file

@ -32,7 +32,12 @@
rgb {
status = "okay";
nvidia,panel = <&bridge>;
port {
dpi_output: endpoint {
remote-endpoint = <&bridge_input>;
bus-width = <24>;
};
};
};
};
};
@ -890,12 +895,22 @@
status = "okay";
clock-frequency = <400000>;
backlight: lm3533@36 {
backlight: led-controller@36 {
compatible = "ti,lm3533";
reg = <0x36>;
enable-gpios = <&gpio TEGRA_GPIO(N, 6) GPIO_ACTIVE_HIGH>;
default-brightness-level = <128>;
ti,boost-ovp-microvolt = <24000000>;
ti,boost-freq-hz = <500000>;
backlight-0 {
compatible = "ti,lm3533-backlight";
ti,max-current-microamp = <23400>;
ti,linear-mapping-mode;
ti,hardware-controlled;
};
};
muic@44 {
@ -969,18 +984,46 @@
compatible = "solomon,ssd2825";
reg = <2>;
#address-cells = <1>;
#size-cells = <0>;
spi-cpol;
spi-cpha;
spi-max-frequency = <1000000>;
power-gpios = <&gpio TEGRA_GPIO(B, 1) GPIO_ACTIVE_HIGH>;
reset-gpios = <&gpio TEGRA_GPIO(O, 2) GPIO_ACTIVE_HIGH>;
reset-gpios = <&gpio TEGRA_GPIO(O, 2) GPIO_ACTIVE_LOW>;
dvdd-supply = <&vdd_1v2_rgb>;
avdd-supply = <&vdd_1v2_rgb>;
vddio-supply = <&vdd_1v8_vio>;
solomon,hs-zero-delay-ns = <300>;
solomon,hs-prep-delay-ns = <65>;
clocks = <&ssd2825_refclk>;
clock-names = "tx_clk";
panel = <&panel>;
ports {
#address-cells = <1>;
#size-cells = <0>;
port@0 {
reg = <0>;
bridge_input: endpoint {
remote-endpoint = <&dpi_output>;
bus-width = <24>;
};
};
port@1 {
reg = <1>;
bridge_output: endpoint {
remote-endpoint = <&panel_input>;
};
};
};
};
};
@ -1036,4 +1079,29 @@
linux,code = <KEY_DOWN>;
};
};
vdd_1v2_rgb: regulator-rgb1v2 {
compatible = "regulator-fixed";
regulator-name = "vdd_1v2_rgb";
regulator-min-microvolt = <1200000>;
regulator-max-microvolt = <1200000>;
gpio = <&gpio TEGRA_GPIO(B, 1) GPIO_ACTIVE_HIGH>;
enable-active-high;
};
vcc_3v0_lcd: regulator-lcd3v {
compatible = "regulator-fixed";
regulator-name = "vcc_3v0_lcd";
regulator-min-microvolt = <3000000>;
regulator-max-microvolt = <3000000>;
};
iovcc_1v8_lcd: regulator-lcd1v8 {
compatible = "regulator-fixed";
regulator-name = "iovcc_1v8_lcd";
regulator-min-microvolt = <1800000>;
regulator-max-microvolt = <1800000>;
gpio = <&gpio TEGRA_GPIO(Y, 0) GPIO_ACTIVE_HIGH>;
enable-active-high;
};
};

View file

@ -103,8 +103,8 @@
nvidia,pull = <TEGRA_PIN_PULL_NONE>;
nvidia,tristate = <TEGRA_PIN_DISABLE>;
nvidia,enable-input = <TEGRA_PIN_ENABLE>;
nvidia,lock = <1>;
nvidia,io-reset = <1>;
nvidia,lock = <TEGRA_PIN_DISABLE>;
nvidia,io-reset = <TEGRA_PIN_DISABLE>;
};
sdmmc4-cmd {
nvidia,pins = "sdmmc4_cmd_pt7",
@ -121,8 +121,8 @@
nvidia,pull = <TEGRA_PIN_PULL_UP>;
nvidia,tristate = <TEGRA_PIN_DISABLE>;
nvidia,enable-input = <TEGRA_PIN_ENABLE>;
nvidia,lock = <1>;
nvidia,io-reset = <1>;
nvidia,lock = <TEGRA_PIN_DISABLE>;
nvidia,io-reset = <TEGRA_PIN_DISABLE>;
};
cam-mclk {
nvidia,pins = "cam_mclk_pcc0";
@ -141,7 +141,7 @@
nvidia,tristate = <TEGRA_PIN_DISABLE>;
nvidia,enable-input = <TEGRA_PIN_ENABLE>;
nvidia,open-drain = <TEGRA_PIN_ENABLE>;
nvidia,lock = <0>;
nvidia,lock = <TEGRA_PIN_DISABLE>;
};
gen2-i2c {
nvidia,pins = "gen2_i2c_scl_pt5",
@ -151,7 +151,7 @@
nvidia,tristate = <TEGRA_PIN_DISABLE>;
nvidia,enable-input = <TEGRA_PIN_ENABLE>;
nvidia,open-drain = <TEGRA_PIN_ENABLE>;
nvidia,lock = <0>;
nvidia,lock = <TEGRA_PIN_DISABLE>;
};
cam-i2c {
nvidia,pins = "cam_i2c_scl_pbb1",
@ -161,7 +161,7 @@
nvidia,tristate = <TEGRA_PIN_DISABLE>;
nvidia,enable-input = <TEGRA_PIN_ENABLE>;
nvidia,open-drain = <TEGRA_PIN_ENABLE>;
nvidia,lock = <0>;
nvidia,lock = <TEGRA_PIN_DISABLE>;
};
ddc-i2c {
nvidia,pins = "ddc_scl_pv4",
@ -170,7 +170,7 @@
nvidia,pull = <TEGRA_PIN_PULL_NONE>;
nvidia,tristate = <TEGRA_PIN_DISABLE>;
nvidia,enable-input = <TEGRA_PIN_ENABLE>;
nvidia,lock = <0>;
nvidia,lock = <TEGRA_PIN_DISABLE>;
};
pwr-i2c {
nvidia,pins = "pwr_i2c_scl_pz6",
@ -180,7 +180,7 @@
nvidia,tristate = <TEGRA_PIN_DISABLE>;
nvidia,enable-input = <TEGRA_PIN_ENABLE>;
nvidia,open-drain = <TEGRA_PIN_ENABLE>;
nvidia,lock = <0>;
nvidia,lock = <TEGRA_PIN_DISABLE>;
};
/* HDMI pinmux */
@ -703,8 +703,8 @@
nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
nvidia,tristate = <TEGRA_PIN_ENABLE>;
nvidia,enable-input = <TEGRA_PIN_ENABLE>;
nvidia,lock = <1>;
nvidia,io-reset = <1>;
nvidia,lock = <TEGRA_PIN_DISABLE>;
nvidia,io-reset = <TEGRA_PIN_DISABLE>;
};
vi-d3-pl1 {
nvidia,pins = "vi_d3_pl1";
@ -712,8 +712,8 @@
nvidia,pull = <TEGRA_PIN_PULL_NONE>;
nvidia,tristate = <TEGRA_PIN_ENABLE>;
nvidia,enable-input = <TEGRA_PIN_ENABLE>;
nvidia,lock = <1>;
nvidia,io-reset = <1>;
nvidia,lock = <TEGRA_PIN_DISABLE>;
nvidia,io-reset = <TEGRA_PIN_DISABLE>;
};
vi-hsync-pd7 {
nvidia,pins = "vi_hsync_pd7",
@ -724,8 +724,8 @@
nvidia,pull = <TEGRA_PIN_PULL_NONE>;
nvidia,tristate = <TEGRA_PIN_DISABLE>;
nvidia,enable-input = <TEGRA_PIN_DISABLE>;
nvidia,lock = <1>;
nvidia,io-reset = <1>;
nvidia,lock = <TEGRA_PIN_DISABLE>;
nvidia,io-reset = <TEGRA_PIN_DISABLE>;
};
vi-mclk-pt1 {
nvidia,pins = "vi_mclk_pt1";
@ -733,8 +733,8 @@
nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
nvidia,tristate = <TEGRA_PIN_ENABLE>;
nvidia,enable-input = <TEGRA_PIN_ENABLE>;
nvidia,lock = <1>;
nvidia,io-reset = <1>;
nvidia,lock = <TEGRA_PIN_DISABLE>;
nvidia,io-reset = <TEGRA_PIN_DISABLE>;
};
vi-d11-pt3 {
nvidia,pins = "vi_d11_pt3";
@ -742,8 +742,8 @@
nvidia,pull = <TEGRA_PIN_PULL_NONE>;
nvidia,tristate = <TEGRA_PIN_DISABLE>;
nvidia,enable-input = <TEGRA_PIN_DISABLE>;
nvidia,lock = <1>;
nvidia,io-reset = <1>;
nvidia,lock = <TEGRA_PIN_DISABLE>;
nvidia,io-reset = <TEGRA_PIN_DISABLE>;
};
/* PORT U */

File diff suppressed because it is too large Load diff

View file

@ -157,7 +157,7 @@
nvidia,tristate = <TEGRA_PIN_DISABLE>;
nvidia,enable-input = <TEGRA_PIN_ENABLE>;
nvidia,open-drain = <TEGRA_PIN_ENABLE>;
nvidia,lock = <0>;
nvidia,lock = <TEGRA_PIN_DISABLE>;
};
gen2-i2c {
nvidia,pins = "gen2_i2c_scl_pt5",
@ -167,7 +167,7 @@
nvidia,tristate = <TEGRA_PIN_DISABLE>;
nvidia,enable-input = <TEGRA_PIN_ENABLE>;
nvidia,open-drain = <TEGRA_PIN_ENABLE>;
nvidia,lock = <0>;
nvidia,lock = <TEGRA_PIN_DISABLE>;
};
cam-i2c {
nvidia,pins = "cam_i2c_scl_pbb1",
@ -177,7 +177,7 @@
nvidia,tristate = <TEGRA_PIN_DISABLE>;
nvidia,enable-input = <TEGRA_PIN_ENABLE>;
nvidia,open-drain = <TEGRA_PIN_ENABLE>;
nvidia,lock = <0>;
nvidia,lock = <TEGRA_PIN_DISABLE>;
};
ddc-i2c {
nvidia,pins = "ddc_scl_pv4",
@ -186,7 +186,7 @@
nvidia,pull = <TEGRA_PIN_PULL_NONE>;
nvidia,tristate = <TEGRA_PIN_DISABLE>;
nvidia,enable-input = <TEGRA_PIN_ENABLE>;
nvidia,lock = <0>;
nvidia,lock = <TEGRA_PIN_DISABLE>;
};
pwr-i2c {
nvidia,pins = "pwr_i2c_scl_pz6",
@ -196,7 +196,7 @@
nvidia,tristate = <TEGRA_PIN_DISABLE>;
nvidia,enable-input = <TEGRA_PIN_ENABLE>;
nvidia,open-drain = <TEGRA_PIN_ENABLE>;
nvidia,lock = <0>;
nvidia,lock = <TEGRA_PIN_DISABLE>;
};
/* HDMI pinmux */

View file

@ -448,6 +448,11 @@ enum win_color_depth_id {
#define LVS_OUTPUT_POLARITY_LOW BIT(28)
#define LSC0_OUTPUT_POLARITY_LOW BIT(24)
/* DC_DISP_DISP_SIGNAL_OPTIONS0 0x400 */
#define H_PULSE0_ENABLE BIT(8)
#define H_PULSE1_ENABLE BIT(10)
#define H_PULSE2_ENABLE BIT(12)
/* DC_DISP_DISP_WIN_OPTIONS 0x402 */
#define CURSOR_ENABLE BIT(16)
#define SOR_ENABLE BIT(25)
@ -504,6 +509,22 @@ enum {
DATA_ORDER_BLUE_RED,
};
/* DC_DISP_DISP_COLOR_CONTROL 0x430 */
#define DITHER_CONTROL_DISABLE (0 << 8)
#define DITHER_CONTROL_ORDERED (2 << 8)
#define DITHER_CONTROL_ERRDIFF (3 << 8)
enum {
BASE_COLOR_SIZE_666,
BASE_COLOR_SIZE_111,
BASE_COLOR_SIZE_222,
BASE_COLOR_SIZE_333,
BASE_COLOR_SIZE_444,
BASE_COLOR_SIZE_555,
BASE_COLOR_SIZE_565,
BASE_COLOR_SIZE_332,
BASE_COLOR_SIZE_888,
};
/* DC_DISP_DATA_ENABLE_OPTIONS 0x432 */
#define DE_SELECT_SHIFT 0
#define DE_SELECT_MASK (0x3 << DE_SELECT_SHIFT)
@ -570,8 +591,27 @@ enum {
#define V_DDA_INC_SHIFT 16
#define V_DDA_INC_MASK (0xFFFF << V_DDA_INC_SHIFT)
#define DC_POLL_TIMEOUT_MS 50
#define DC_N_WINDOWS 5
#define DC_REG_SAVE_SPACE (DC_N_WINDOWS + 5)
#define DC_POLL_TIMEOUT_MS 50
#define DC_N_WINDOWS 5
#define DC_REG_SAVE_SPACE (DC_N_WINDOWS + 5)
#define PULSE_MODE_NORMAL (0 << 3)
#define PULSE_MODE_ONE_CLOCK (1 << 3)
#define PULSE_POLARITY_HIGH (0 << 4)
#define PULSE_POLARITY_LOW (1 << 4)
#define PULSE_QUAL_ALWAYS (0 << 6)
#define PULSE_QUAL_VACTIVE (2 << 6)
#define PULSE_QUAL_VACTIVE1 (3 << 6)
#define PULSE_LAST_START_A (0 << 8)
#define PULSE_LAST_END_A (1 << 8)
#define PULSE_LAST_START_B (2 << 8)
#define PULSE_LAST_END_B (3 << 8)
#define PULSE_LAST_START_C (4 << 8)
#define PULSE_LAST_END_C (5 << 8)
#define PULSE_LAST_START_D (6 << 8)
#define PULSE_LAST_END_D (7 << 8)
#define PULSE_START(x) (((x) & 0xfff) << 0)
#define PULSE_END(x) (((x) & 0xfff) << 16)
#endif /* __ASM_ARCH_TEGRA_DC_H */

View file

@ -34,41 +34,41 @@ enum pmux_pin_io {
#ifdef TEGRA_PMX_PINS_HAVE_LOCK
enum pmux_pin_lock {
PMUX_PIN_LOCK_DEFAULT = 0,
PMUX_PIN_LOCK_DISABLE,
PMUX_PIN_LOCK_DISABLE = 0,
PMUX_PIN_LOCK_ENABLE,
PMUX_PIN_LOCK_DEFAULT,
};
#endif
#ifdef TEGRA_PMX_PINS_HAVE_OD
enum pmux_pin_od {
PMUX_PIN_OD_DEFAULT = 0,
PMUX_PIN_OD_DISABLE,
PMUX_PIN_OD_DISABLE = 0,
PMUX_PIN_OD_ENABLE,
PMUX_PIN_OD_DEFAULT,
};
#endif
#ifdef TEGRA_PMX_PINS_HAVE_IO_RESET
enum pmux_pin_ioreset {
PMUX_PIN_IO_RESET_DEFAULT = 0,
PMUX_PIN_IO_RESET_DISABLE,
PMUX_PIN_IO_RESET_DISABLE = 0,
PMUX_PIN_IO_RESET_ENABLE,
PMUX_PIN_IO_RESET_DEFAULT,
};
#endif
#ifdef TEGRA_PMX_PINS_HAVE_RCV_SEL
enum pmux_pin_rcv_sel {
PMUX_PIN_RCV_SEL_DEFAULT = 0,
PMUX_PIN_RCV_SEL_NORMAL,
PMUX_PIN_RCV_SEL_NORMAL = 0,
PMUX_PIN_RCV_SEL_HIGH,
PMUX_PIN_RCV_SEL_DEFAULT,
};
#endif
#ifdef TEGRA_PMX_PINS_HAVE_E_IO_HV
enum pmux_pin_e_io_hv {
PMUX_PIN_E_IO_HV_DEFAULT = 0,
PMUX_PIN_E_IO_HV_NORMAL,
PMUX_PIN_E_IO_HV_NORMAL = 0,
PMUX_PIN_E_IO_HV_HIGH,
PMUX_PIN_E_IO_HV_DEFAULT,
};
#endif

View file

@ -467,14 +467,14 @@ static const char * const tegra_pinctrl_to_func[] = {
[PMUX_FUNC_DAP3] = "dap3",
[PMUX_FUNC_DAP4] = "dap4",
[PMUX_FUNC_DAP5] = "dap5",
[PMUX_FUNC_DISPA] = "dispa",
[PMUX_FUNC_DISPB] = "dispb",
[PMUX_FUNC_DISPA] = "displaya",
[PMUX_FUNC_DISPB] = "displayb",
[PMUX_FUNC_EMC_TEST0_DLL] = "emc_test0_dll",
[PMUX_FUNC_EMC_TEST1_DLL] = "emc_test1_dll",
[PMUX_FUNC_GMI] = "gmi",
[PMUX_FUNC_GMI_INT] = "gmi_int",
[PMUX_FUNC_HDMI] = "hdmi",
[PMUX_FUNC_I2C] = "i2c",
[PMUX_FUNC_I2C] = "i2c1",
[PMUX_FUNC_I2C2] = "i2c2",
[PMUX_FUNC_I2C3] = "i2c3",
[PMUX_FUNC_IDE] = "ide",

View file

@ -32,6 +32,10 @@ config TARGET_IDEAPAD_YOGA_11
bool "Lenovo Ideapad Yoga 11 board"
select BOARD_LATE_INIT
config TARGET_OUYA
bool "Ouya Game Console board"
select BOARD_LATE_INIT
config TARGET_QC750
bool "Wexler QC750 board"
select BOARD_LATE_INIT
@ -64,6 +68,7 @@ source "board/toradex/colibri_t30/Kconfig"
source "board/htc/endeavoru/Kconfig"
source "board/asus/grouper/Kconfig"
source "board/lenovo/ideapad-yoga-11/Kconfig"
source "board/ouya/ouya/Kconfig"
source "board/wexler/qc750/Kconfig"
source "board/microsoft/surface-rt/Kconfig"
source "board/avionic-design/tec-ng/Kconfig"

12
board/ouya/ouya/Kconfig Normal file
View file

@ -0,0 +1,12 @@
if TARGET_OUYA
config SYS_BOARD
default "ouya"
config SYS_VENDOR
default "ouya"
config SYS_CONFIG_NAME
default "ouya"
endif

View file

@ -0,0 +1,8 @@
OUYA BOARD
M: Svyatoslav Ryhel <clamor95@gmail.com>
M: Peter Geis <pgwipeout@gmail.com>
S: Maintained
F: board/ouya/ouya/
F: configs/ouya_defconfig
F: doc/board/ouya/ouya.rst
F: include/configs/ouya.h

11
board/ouya/ouya/Makefile Normal file
View file

@ -0,0 +1,11 @@
# SPDX-License-Identifier: GPL-2.0+
#
# (C) Copyright 2010-2012
# NVIDIA Corporation <www.nvidia.com>
#
# (C) Copyright 2021
# Svyatoslav Ryhel <clamor95@gmail.com>
obj-$(CONFIG_XPL_BUILD) += ouya-spl.o
obj-y += ouya.o

View file

@ -0,0 +1,41 @@
// SPDX-License-Identifier: GPL-2.0+
/*
* T30 Ouya SPL stage configuration
*
* (C) Copyright 2010-2013
* NVIDIA Corporation <www.nvidia.com>
*
* (C) Copyright 2025
* Svyatoslav Ryhel <clamor95@gmail.com>
*/
#include <asm/arch/tegra.h>
#include <asm/arch-tegra/tegra_i2c.h>
#include <linux/delay.h>
#define TPS65911_I2C_ADDR (0x2D << 1)
#define TPS65911_VDDCTRL_OP_REG 0x28
#define TPS65911_VDDCTRL_SR_REG 0x27
#define TPS65911_VDDCTRL_OP_DATA (0x2400 | TPS65911_VDDCTRL_OP_REG)
#define TPS65911_VDDCTRL_SR_DATA (0x0100 | TPS65911_VDDCTRL_SR_REG)
#define TPS62361B_I2C_ADDR (0x60 << 1)
#define TPS62361B_SET3_REG 0x03
#define TPS62361B_SET3_DATA (0x4600 | TPS62361B_SET3_REG)
void pmic_enable_cpu_vdd(void)
{
/* Set VDD_CORE to 1.200V. */
tegra_i2c_ll_write(TPS62361B_I2C_ADDR, TPS62361B_SET3_DATA);
udelay(1000);
/*
* Bring up CPU VDD via the TPS65911x PMIC on the DVC I2C bus.
* First set VDD to 1.0125V, then enable the VDD regulator.
*/
tegra_i2c_ll_write(TPS65911_I2C_ADDR, TPS65911_VDDCTRL_OP_DATA);
udelay(1000);
tegra_i2c_ll_write(TPS65911_I2C_ADDR, TPS65911_VDDCTRL_SR_DATA);
udelay(10 * 1000);
}

21
board/ouya/ouya/ouya.c Normal file
View file

@ -0,0 +1,21 @@
// SPDX-License-Identifier: GPL-2.0+
/*
* (C) Copyright 2010-2013
* NVIDIA Corporation <www.nvidia.com>
*
* (C) Copyright 2025
* Svyatoslav Ryhel <clamor95@gmail.com>
*/
#include <fdt_support.h>
#if defined(CONFIG_OF_LIBFDT) && defined(CONFIG_OF_BOARD_SETUP)
int ft_board_setup(void *blob, struct bd_info *bd)
{
/* Remove TrustZone nodes */
fdt_del_node_and_alias(blob, "/firmware");
fdt_del_node_and_alias(blob, "/reserved-memory/trustzone@bfe00000");
return 0;
}
#endif

12
board/ouya/ouya/ouya.env Normal file
View file

@ -0,0 +1,12 @@
#include <env/nvidia/prod_upd.env>
partitions=name=emmc,start=0,size=-,uuid=${uuid_gpt_rootfs}
boot_interface=usb
bootmenu_0=mount internal storage=usb start && ums 0 mmc 0; bootmenu
bootmenu_1=fastboot=echo Starting Fastboot protocol ...; fastboot usb 0; bootmenu
bootmenu_2=update bootloader=run flash_uboot
bootmenu_3=reboot RCM=enterrcm
bootmenu_4=reboot=reset
bootmenu_5=power off=poweroff
bootmenu_delay=-1

View file

@ -16,6 +16,7 @@
#include <linux/ctype.h>
#include <linux/string.h>
#if CONFIG_IS_ENABLED(I2C_EDID_STANDARD)
#define TIMING(c, ha, hfp, hbp, hsl, va, vfp, vbp, vsl, f) \
.pixelclock = { (c), (c), (c) }, \
.hactive = { (ha), (ha), (ha) }, \
@ -206,6 +207,7 @@ static const struct display_timing dmt_timings[] = {
{ TIMING(556188000, 4096, 8, 32, 40, 2160, 48, 8, 6,
DISPLAY_FLAGS_HSYNC_HIGH | DISPLAY_FLAGS_VSYNC_LOW) },
};
#endif
int edid_check_info(struct edid1_info *edid_info)
{
@ -417,6 +419,7 @@ static bool edid_get_standard_timing(struct edid1_info *edid, int i, unsigned in
return false;
}
#if CONFIG_IS_ENABLED(I2C_EDID_STANDARD)
static bool edid_find_valid_standard_timing(struct edid1_info *buf,
struct display_timing *timing,
bool (*mode_valid)(void *priv,
@ -446,6 +449,7 @@ static bool edid_find_valid_standard_timing(struct edid1_info *buf,
return found;
}
#endif
int edid_get_timing_validate(u8 *buf, int buf_size,
struct display_timing *timing,
@ -493,10 +497,12 @@ int edid_get_timing_validate(u8 *buf, int buf_size,
}
}
#if CONFIG_IS_ENABLED(I2C_EDID_STANDARD)
/* Look for timing in Standard Timings */
if (!found)
found = edid_find_valid_standard_timing(edid, timing, mode_valid,
mode_valid_priv);
#endif
if (!found)
return -EINVAL;

View file

@ -80,6 +80,7 @@ CONFIG_USB_GADGET_VENDOR_NUM=0x0bb4
CONFIG_USB_GADGET_PRODUCT_NUM=0x0c02
CONFIG_CI_UDC=y
CONFIG_VIDEO=y
CONFIG_VIDEO_BRIDGE=y
# CONFIG_VIDEO_LOGO is not set
CONFIG_VIDEO_LCD_ENDEAVORU=y
CONFIG_VIDEO_DSI_TEGRA30=y

86
configs/ouya_defconfig Normal file
View file

@ -0,0 +1,86 @@
CONFIG_ARM=y
CONFIG_ARCH_TEGRA=y
CONFIG_SUPPORT_PASSING_ATAGS=y
CONFIG_CMDLINE_TAG=y
CONFIG_INITRD_TAG=y
CONFIG_TEXT_BASE=0x80110000
CONFIG_NR_DRAM_BANKS=2
CONFIG_ENV_SOURCE_FILE="ouya"
CONFIG_ENV_SIZE=0x3000
CONFIG_ENV_OFFSET=0xFFFFD000
CONFIG_DEFAULT_DEVICE_TREE="tegra30-ouya"
CONFIG_SPL_STACK=0x800ffffc
CONFIG_SPL_TEXT_BASE=0x80108000
CONFIG_SYS_LOAD_ADDR=0x82000000
CONFIG_TEGRA30=y
CONFIG_TARGET_OUYA=y
CONFIG_TEGRA_ENABLE_UARTD=y
CONFIG_CMD_EBTUPDATE=y
CONFIG_BUTTON_CMD=y
CONFIG_BOOTDELAY=3
CONFIG_OF_BOARD_SETUP=y
CONFIG_OF_SYSTEM_SETUP=y
CONFIG_BOOTCOMMAND="bootflow scan; echo 'Boot configuration not found... Power off in 3 sec'; sleep 3; poweroff"
CONFIG_USE_PREBOOT=y
CONFIG_SYS_PBSIZE=2084
CONFIG_SPL_FOOTPRINT_LIMIT=y
CONFIG_SPL_MAX_FOOTPRINT=0x8000
# CONFIG_SPL_SHARES_INIT_SP_ADDR is not set
CONFIG_SPL_SYS_MALLOC=y
CONFIG_SPL_HAS_CUSTOM_MALLOC_START=y
CONFIG_SPL_CUSTOM_SYS_MALLOC_ADDR=0x80090000
CONFIG_SPL_SYS_MALLOC_SIZE=0x10000
CONFIG_SYS_PROMPT="Tegra30 (Ouya) # "
# CONFIG_CMD_BOOTEFI_BOOTMGR is not set
CONFIG_CMD_BOOTMENU=y
# CONFIG_CMD_IMI is not set
CONFIG_CMD_GPIO=y
CONFIG_CMD_GPT=y
CONFIG_CMD_GPT_RENAME=y
CONFIG_CMD_I2C=y
CONFIG_CMD_MMC=y
CONFIG_CMD_POWEROFF=y
CONFIG_CMD_USB=y
CONFIG_CMD_USB_MASS_STORAGE=y
CONFIG_CMD_UMS_ABORT_KEYED=y
# CONFIG_CMD_SETEXPR is not set
CONFIG_CMD_PAUSE=y
CONFIG_CMD_REGULATOR=y
CONFIG_CMD_EXT4_WRITE=y
# CONFIG_SPL_DOS_PARTITION is not set
# CONFIG_SPL_EFI_PARTITION is not set
CONFIG_ENV_OVERWRITE=y
CONFIG_SYS_RELOC_GD_ENV_ADDR=y
CONFIG_SYS_MMC_ENV_PART=2
CONFIG_BUTTON=y
CONFIG_USB_FUNCTION_FASTBOOT=y
CONFIG_FASTBOOT_BUF_ADDR=0x91000000
CONFIG_FASTBOOT_BUF_SIZE=0x10000000
CONFIG_FASTBOOT_FLASH=y
CONFIG_FASTBOOT_FLASH_MMC_DEV=0
CONFIG_FASTBOOT_CMD_OEM_FORMAT=y
CONFIG_GPIO_HOG=y
CONFIG_SYS_I2C_TEGRA=y
CONFIG_BUTTON_KEYBOARD=y
CONFIG_LED=y
CONFIG_LED_BLINK=y
CONFIG_LED_GPIO=y
CONFIG_DM_PMIC=y
CONFIG_DM_PMIC_TPS65910=y
CONFIG_DM_REGULATOR=y
CONFIG_DM_REGULATOR_FIXED=y
CONFIG_DM_REGULATOR_TPS65911=y
CONFIG_PWM_TEGRA=y
CONFIG_SYS_NS16550=y
CONFIG_SYSRESET_TPS65910=y
CONFIG_USB=y
CONFIG_USB_EHCI_HCD=y
CONFIG_USB_EHCI_TEGRA=y
CONFIG_USB_KEYBOARD=y
CONFIG_USB_GADGET=y
CONFIG_CI_UDC=y
CONFIG_VIDEO=y
# CONFIG_VIDEO_LOGO is not set
CONFIG_I2C_EDID_STANDARD=y
CONFIG_VIDEO_BRIDGE=y
CONFIG_VIDEO_HDMI_TEGRA=y

View file

@ -90,6 +90,8 @@ CONFIG_USB_GADGET_VENDOR_NUM=0x0b05
CONFIG_USB_GADGET_PRODUCT_NUM=0x4daf
CONFIG_CI_UDC=y
CONFIG_VIDEO=y
CONFIG_VIDEO_BRIDGE=y
# CONFIG_VIDEO_LOGO is not set
CONFIG_VIDEO_BRIDGE_TOSHIBA_TC358768=y
CONFIG_VIDEO_TEGRA20=y
CONFIG_VIDEO_HDMI_TEGRA=y

View file

@ -83,6 +83,7 @@ CONFIG_USB_GADGET_VENDOR_NUM=0x1004
CONFIG_USB_GADGET_PRODUCT_NUM=0x7100
CONFIG_CI_UDC=y
CONFIG_VIDEO=y
CONFIG_VIDEO_BRIDGE=y
# CONFIG_VIDEO_LOGO is not set
CONFIG_BACKLIGHT_LM3533=y
CONFIG_VIDEO_BRIDGE_SOLOMON_SSD2825=y

View file

@ -43,6 +43,7 @@ Board-specific doc
microsoft/index
nxp/index
openpiton/index
ouya/index
phytec/index
purism/index
qualcomm/index

9
doc/board/ouya/index.rst Normal file
View file

@ -0,0 +1,9 @@
.. SPDX-License-Identifier: GPL-2.0+
OUYA
====
.. toctree::
:maxdepth: 2
ouya

124
doc/board/ouya/ouya.rst Normal file
View file

@ -0,0 +1,124 @@
.. SPDX-License-Identifier: GPL-2.0+
U-Boot for the Ouya Game Console (ouya)
=======================================
``DISCLAMER!`` Moving your Ouya to use U-Boot assumes replacement of the
vendor bootloader. Vendor android firmwares will no longer be able to run on the
device. This replacement IS reversible.
Quick Start
-----------
- Build U-Boot
- Process U-Boot
- Flashing U-Boot into the eMMC
- Boot
- Self Upgrading
Build U-Boot
------------
.. code-block:: bash
$ export CROSS_COMPILE=arm-none-eabi-
$ make ouya_defconfig
$ make
After the build succeeds, you will obtain the final ``u-boot-dtb-tegra.bin``
image, ready for further processing.
Process U-Boot
--------------
``DISCLAMER!`` All questions related to the re-crypt work should be asked
in re-crypt repo issues. NOT HERE!
re-crypt is a tool that processes the ``u-boot-dtb-tegra.bin`` binary into form
usable by device. This process is required only on the first installation or
to recover the device in case of a failed update.
Permanent installation can be performed either by using the nv3p protocol or by
pre-loading just built U-Boot into RAM.
Processing for the NV3P protocol
********************************
.. code-block:: bash
$ git clone https://gitlab.com/grate-driver/re-crypt.git
$ cd re-crypt # place your u-boot-dtb-tegra.bin here
$ ./re-crypt.py --dev ouya
The script will produce a ``repart-block.bin`` ready to flash.
Processing for pre-loaded U-Boot
********************************
The procedure is the same, but the ``--split`` argument is used with the
``re-crypt.py``. The script will produce ``bct.img`` and ``ebt.img`` ready
to flash.
Flashing U-Boot into the eMMC
-----------------------------
Permanent installation can be performed either by using the nv3p protocol or by
pre-loading just built U-Boot into RAM. Regardless of the method bct and bootloader
will end up in boot0 and boot1 partitions of eMMC.
Flashing with the NV3P protocol
*******************************
``DISCLAMER!`` All questions related to NvFlash should be asked in the proper
place. NOT HERE! Flashing U-Boot will erase all eMMC, so make a backup before!
Nv3p is a custom Nvidia protocol used to recover bricked devices. Devices can
enter it by pre-loading vendor bootloader with the Fusée Gelée.
With nv3p, ``repart-block.bin`` is used. It contains BCT and a bootloader in
encrypted state in form, which can just be written RAW at the start of eMMC.
.. code-block:: bash
$ ./run_bootloader.sh -s T30 -t ./bct/ouya.bct -b android_bootloader.bin
$ ./utiils/nvflash_v1.13.87205 --resume --rawdevicewrite 0 1024 repart-block.bin
When flashing is done, reboot the device.
Flashing with a pre-loaded U-Boot
*********************************
U-Boot pre-loaded into RAM acts the same as when it was booted "cold". Currently
U-Boot supports bootmenu entry fastboot, which allows to write a processed copy
of U-Boot permanently into eMMC.
While pre-loading U-Boot, interrupt bootflow by pressing ``CTRL + C`` (USB keyboard
must be plugged in before U-Boot is preloaded, else it will not work), input
``bootmenu`` from the keyboard and hit enter. The bootmenu will appear. There, select
``fastboot`` using the up and down arrows and enter key. After, on host PC, do:
.. code-block:: bash
$ fastboot flash 0.1 bct.img
$ fastboot flash 0.2 ebt.img
$ fastboot reboot
Device will reboot.
Boot
----
To boot Linux, U-Boot will look for an ``extlinux.conf`` on eMMC. Additionally,
bootmenu provides entries to mount eMMC as mass storage, fastboot, reboot,
reboot RCM, poweroff, enter U-Boot console and update bootloader (check
the next chapter).
Flashing ``repart-block.bin`` eliminates vendor restrictions on eMMC and allows
the user to use/partition it in any way the user desires.
Self Upgrading
--------------
Place your ``u-boot-dtb-tegra.bin`` on the first partition of the USB. Enter
bootmenu, choose update bootloader option with Enter and U-Boot should update
itself. Once the process is completed, U-Boot will ask to press any button to reboot.

View file

@ -23,18 +23,18 @@ static void tegra_pinctrl_set_drive(struct udevice *config, int drvcnt)
return;
}
drive_group[0].slwf = dev_read_u32_default(config, "nvidia,slew-rate-falling", 0);
drive_group[0].slwr = dev_read_u32_default(config, "nvidia,slew-rate-rising", 0);
drive_group[0].drvup = dev_read_u32_default(config, "nvidia,pull-up-strength", 0);
drive_group[0].drvdn = dev_read_u32_default(config, "nvidia,pull-down-strength", 0);
drive_group[0].slwf = dev_read_u32_default(config, "nvidia,slew-rate-falling", PMUX_SLWF_NONE);
drive_group[0].slwr = dev_read_u32_default(config, "nvidia,slew-rate-rising", PMUX_SLWR_NONE);
drive_group[0].drvup = dev_read_u32_default(config, "nvidia,pull-up-strength", PMUX_DRVUP_NONE);
drive_group[0].drvdn = dev_read_u32_default(config, "nvidia,pull-down-strength", PMUX_DRVDN_NONE);
#ifdef TEGRA_PMX_GRPS_HAVE_LPMD
drive_group[0].lpmd = dev_read_u32_default(config, "nvidia,low-power-mode", 0);
drive_group[0].lpmd = dev_read_u32_default(config, "nvidia,low-power-mode", PMUX_LPMD_NONE);
#endif
#ifdef TEGRA_PMX_GRPS_HAVE_SCHMT
drive_group[0].schmt = dev_read_u32_default(config, "nvidia,schmitt", 0);
drive_group[0].schmt = dev_read_u32_default(config, "nvidia,schmitt", PMUX_SCHMT_NONE);
#endif
#ifdef TEGRA_PMX_GRPS_HAVE_HSM
drive_group[0].hsm = dev_read_u32_default(config, "nvidia,high-speed-mode", 0);
drive_group[0].hsm = dev_read_u32_default(config, "nvidia,high-speed-mode", PMUX_HSM_NONE);
#endif
for (i = 1; i < drvcnt; i++)
@ -142,31 +142,31 @@ static void tegra_pinctrl_set_pin(struct udevice *config, int pincnt)
pinmux_group[0].func = i;
pinmux_group[0].pull = dev_read_u32_default(config, "nvidia,pull", 0);
pinmux_group[0].tristate = dev_read_u32_default(config, "nvidia,tristate", 0);
pinmux_group[0].pull = dev_read_u32_default(config, "nvidia,pull", PMUX_PULL_NORMAL);
pinmux_group[0].tristate = dev_read_u32_default(config, "nvidia,tristate", PMUX_TRI_TRISTATE);
#ifdef TEGRA_PMX_PINS_HAVE_E_INPUT
pinmux_group[0].io = dev_read_u32_default(config, "nvidia,enable-input", 0);
pinmux_group[0].io = dev_read_u32_default(config, "nvidia,enable-input", PMUX_PIN_NONE);
#endif
#ifdef TEGRA_PMX_PINS_HAVE_LOCK
pinmux_group[0].lock = dev_read_u32_default(config, "nvidia,lock", 0);
pinmux_group[0].lock = dev_read_u32_default(config, "nvidia,lock", PMUX_PIN_LOCK_DEFAULT);
#endif
#ifdef TEGRA_PMX_PINS_HAVE_OD
pinmux_group[0].od = dev_read_u32_default(config, "nvidia,open-drain", 0);
pinmux_group[0].od = dev_read_u32_default(config, "nvidia,open-drain", PMUX_PIN_OD_DEFAULT);
#endif
#ifdef TEGRA_PMX_PINS_HAVE_IO_RESET
pinmux_group[0].ioreset = dev_read_u32_default(config, "nvidia,io-reset", 0);
pinmux_group[0].ioreset = dev_read_u32_default(config, "nvidia,io-reset", PMUX_PIN_IO_RESET_DEFAULT);
#endif
#ifdef TEGRA_PMX_PINS_HAVE_RCV_SEL
pinmux_group[0].rcv_sel = dev_read_u32_default(config, "nvidia,rcv-sel", 0);
pinmux_group[0].rcv_sel = dev_read_u32_default(config, "nvidia,rcv-sel", PMUX_PIN_RCV_SEL_DEFAULT);
#endif
#ifdef TEGRA_PMX_PINS_HAVE_E_IO_HV
pinmux_group[0].e_io_hv = dev_read_u32_default(config, "nvidia,io-hv", 0);
pinmux_group[0].e_io_hv = dev_read_u32_default(config, "nvidia,io-hv", PMUX_PIN_E_IO_HV_DEFAULT);
#endif
#ifdef TEGRA_PMX_PINS_HAVE_SCHMT
pinmux_group[0].schmt = dev_read_u32_default(config, "nvidia,schmitt", 0);
pinmux_group[0].schmt = dev_read_u32_default(config, "nvidia,schmitt", PMUX_SCHMT_NONE);
#endif
#ifdef TEGRA_PMX_PINS_HAVE_HSM
pinmux_group[0].hsm = dev_read_u32_default(config, "nvidia,high-speed-mode", 0);
pinmux_group[0].hsm = dev_read_u32_default(config, "nvidia,high-speed-mode", PMUX_HSM_NONE);
#endif
for (i = 1; i < pincnt; i++)

View file

@ -700,6 +700,12 @@ config I2C_EDID
help
This enables library for accessing EDID data from an LCD panel.
config I2C_EDID_STANDARD
bool "Enable standard timings EDID library expansion"
depends on I2C_EDID
help
This enables standard timings expansion for EDID data from an LCD panel.
config DISPLAY
bool "Enable Display support"
depends on DM

View file

@ -9,7 +9,7 @@ config VIDEO_BRIDGE
config VIDEO_BRIDGE_PARADE_DP501
bool "Support Parade DP501 DP & DVI/HDMI dual mode transmitter"
depends on PANEL && DM_GPIO
depends on VIDEO_BRIDGE && PANEL && DM_GPIO
select DM_I2C
help
The Parade DP501 is a DP & DVI/HDMI dual-mode transmitter. It
@ -46,14 +46,14 @@ config VIDEO_BRIDGE_ANALOGIX_ANX6345
config VIDEO_BRIDGE_SOLOMON_SSD2825
bool "Solomon SSD2825 bridge driver"
depends on PANEL && DM_GPIO
depends on VIDEO_BRIDGE && PANEL && DM_GPIO
select VIDEO_MIPI_DSI
help
Solomon SSD2824 SPI RGB-DSI bridge driver wrapped into panel uClass.
Solomon SSD2824 SPI RGB-DSI bridge driver.
config VIDEO_BRIDGE_TOSHIBA_TC358768
bool "Support Toshiba TC358768 MIPI DSI bridge"
depends on PANEL && DM_GPIO
depends on VIDEO_BRIDGE && PANEL && DM_GPIO
select VIDEO_MIPI_DSI
select DM_I2C
help

View file

@ -9,6 +9,7 @@
#include <log.h>
#include <backlight.h>
#include <panel.h>
#include <video_bridge.h>
#include <linux/delay.h>
#include <linux/err.h>
#include <power/regulator.h>
@ -206,7 +207,6 @@ struct dp501_priv {
struct udevice *chip2;
struct udevice *vdd;
struct gpio_desc reset_gpio;
struct gpio_desc enable_gpio;
};
@ -484,16 +484,19 @@ static int dp501_panel_timings(struct udevice *dev,
return 0;
}
static void dp501_hw_init(struct dp501_priv *priv)
static void dp501_hw_init(struct udevice *dev)
{
dm_gpio_set_value(&priv->reset_gpio, 1);
struct dp501_priv *priv = dev_get_priv(dev);
struct video_bridge_priv *uc_priv = dev_get_uclass_priv(dev);
dm_gpio_set_value(&uc_priv->reset, 1);
regulator_set_enable_if_allowed(priv->vdd, 1);
dm_gpio_set_value(&priv->enable_gpio, 1);
udelay(100);
dm_gpio_set_value(&priv->reset_gpio, 0);
dm_gpio_set_value(&uc_priv->reset, 0);
mdelay(80);
}
@ -521,14 +524,6 @@ static int dp501_setup(struct udevice *dev)
}
/* get gpios */
ret = gpio_request_by_name(dev, "reset-gpios", 0,
&priv->reset_gpio, GPIOD_IS_OUT);
if (ret) {
log_debug("%s: Could not decode reset-gpios (%d)\n",
__func__, ret);
return ret;
}
ret = gpio_request_by_name(dev, "enable-gpios", 0,
&priv->enable_gpio, GPIOD_IS_OUT);
if (ret) {
@ -544,7 +539,7 @@ static int dp501_setup(struct udevice *dev)
return ret;
}
dp501_hw_init(priv);
dp501_hw_init(dev);
/* get EDID */
return panel_get_display_timing(priv->panel, &priv->timing);
@ -558,8 +553,8 @@ static int dp501_probe(struct udevice *dev)
return dp501_setup(dev);
}
struct panel_ops dp501_ops = {
.enable_backlight = dp501_attach,
static const struct video_bridge_ops dp501_ops = {
.attach = dp501_attach,
.set_backlight = dp501_set_backlight,
.get_display_timing = dp501_panel_timings,
};
@ -571,7 +566,7 @@ static const struct udevice_id dp501_ids[] = {
U_BOOT_DRIVER(dp501) = {
.name = "dp501",
.id = UCLASS_PANEL,
.id = UCLASS_VIDEO_BRIDGE,
.of_match = dp501_ids,
.ops = &dp501_ops,
.probe = dp501_probe,

View file

@ -5,12 +5,15 @@
#include <clk.h>
#include <dm.h>
#include <dm/ofnode_graph.h>
#include <log.h>
#include <misc.h>
#include <mipi_display.h>
#include <mipi_dsi.h>
#include <backlight.h>
#include <video_bridge.h>
#include <panel.h>
#include <power/regulator.h>
#include <spi.h>
#include <linux/delay.h>
#include <linux/err.h>
@ -106,6 +109,10 @@
#define SSD2825_LP_MIN_CLK 5000 /* KHz */
#define SSD2825_REF_MIN_CLK 2000 /* KHz */
static const char * const ssd2825_supplies[] = {
"dvdd-supply", "avdd-supply", "vddio-supply"
};
struct ssd2825_bridge_priv {
struct mipi_dsi_host host;
struct mipi_dsi_device device;
@ -113,12 +120,16 @@ struct ssd2825_bridge_priv {
struct udevice *panel;
struct display_timing timing;
struct udevice *supplies[ARRAY_SIZE(ssd2825_supplies)];
struct gpio_desc power_gpio;
struct gpio_desc reset_gpio;
struct clk *tx_clk;
u32 pll_freq_kbps; /* PLL in kbps */
u32 hzd; /* HS Zero Delay in ns */
u32 hpd; /* HS Prepare Delay is ns */
};
static int ssd2825_spi_write(struct udevice *dev, int reg,
@ -231,7 +242,6 @@ static ssize_t ssd2825_bridge_transfer(struct mipi_dsi_host *host,
const struct mipi_dsi_msg *msg)
{
struct udevice *dev = (struct udevice *)host->dev;
u8 buf = *(u8 *)msg->tx_buf;
u16 config;
int ret;
@ -260,15 +270,6 @@ static ssize_t ssd2825_bridge_transfer(struct mipi_dsi_host *host,
ssd2825_write_register(dev, SSD2825_VC_CTRL_REG, 0x0000);
ssd2825_write_dsi(dev, msg->tx_buf, msg->tx_len);
if (buf == MIPI_DCS_SET_DISPLAY_ON) {
ssd2825_write_register(dev, SSD2825_CONFIGURATION_REG,
SSD2825_CONF_REG_HS | SSD2825_CONF_REG_VEN |
SSD2825_CONF_REG_DCS | SSD2825_CONF_REG_ECD |
SSD2825_CONF_REG_EOT);
ssd2825_write_register(dev, SSD2825_PLL_CTRL_REG, 0x0001);
ssd2825_write_register(dev, SSD2825_VC_CTRL_REG, 0x0000);
}
return 0;
}
@ -312,9 +313,14 @@ static void ssd2825_setup_pll(struct udevice *dev)
struct mipi_dsi_device *device = &priv->device;
struct display_timing *dt = &priv->timing;
u16 pll_config, lp_div;
u32 nibble_delay, nibble_freq_khz;
u32 pclk_mult, tx_freq_khz, pd_lines;
u8 hzd, hpd;
tx_freq_khz = clk_get_rate(priv->tx_clk) / 1000;
if (!tx_freq_khz || tx_freq_khz < 0)
tx_freq_khz = SSD2825_REF_MIN_CLK;
pd_lines = mipi_dsi_pixel_format_to_bpp(device->format);
pclk_mult = pd_lines / device->lanes + 1;
@ -324,12 +330,19 @@ static void ssd2825_setup_pll(struct udevice *dev)
lp_div = priv->pll_freq_kbps / (SSD2825_LP_MIN_CLK * 8);
/* nibble_delay in nanoseconds */
nibble_freq_khz = priv->pll_freq_kbps / 4;
nibble_delay = 1000 * 1000 / nibble_freq_khz;
hzd = priv->hzd / nibble_delay;
hpd = (priv->hpd - 4 * nibble_delay) / nibble_delay;
/* Disable PLL */
ssd2825_write_register(dev, SSD2825_PLL_CTRL_REG, 0x0000);
ssd2825_write_register(dev, SSD2825_LINE_CTRL_REG, 0x0001);
/* Set delays */
ssd2825_write_register(dev, SSD2825_DELAY_ADJ_REG_1, 0x2103);
ssd2825_write_register(dev, SSD2825_DELAY_ADJ_REG_1, (hzd << 8) | hpd);
/* Set PLL coeficients */
ssd2825_write_register(dev, SSD2825_PLL_CONFIGURATION_REG, pll_config);
@ -343,11 +356,30 @@ static void ssd2825_setup_pll(struct udevice *dev)
ssd2825_write_register(dev, SSD2825_VC_CTRL_REG, 0x0000);
}
static int ssd2825_bridge_enable_panel(struct udevice *dev)
static int ssd2825_bridge_attach(struct udevice *dev)
{
struct ssd2825_bridge_priv *priv = dev_get_priv(dev);
struct mipi_dsi_device *device = &priv->device;
struct display_timing *dt = &priv->timing;
u8 pixel_format;
int ret;
/* Set pixel format */
switch (device->format) {
case MIPI_DSI_FMT_RGB565:
pixel_format = 0x00;
break;
case MIPI_DSI_FMT_RGB666_PACKED:
pixel_format = 0x01;
break;
case MIPI_DSI_FMT_RGB666:
pixel_format = 0x02;
break;
case MIPI_DSI_FMT_RGB888:
default:
pixel_format = 0x03;
break;
}
/* Perform SW reset */
ssd2825_write_register(dev, SSD2825_OPERATION_CTRL_REG, 0x0100);
@ -367,7 +399,7 @@ static int ssd2825_bridge_enable_panel(struct udevice *dev)
ssd2825_write_register(dev, SSD2825_RGB_INTERFACE_CTRL_REG_6,
SSD2825_HSYNC_HIGH | SSD2825_VSYNC_HIGH |
SSD2825_PCKL_HIGH | SSD2825_NON_BURST |
(3 - device->format));
pixel_format);
ssd2825_write_register(dev, SSD2825_LANE_CONFIGURATION_REG,
device->lanes - 1);
ssd2825_write_register(dev, SSD2825_TEST_REG, 0x0004);
@ -384,7 +416,18 @@ static int ssd2825_bridge_enable_panel(struct udevice *dev)
ssd2825_write_register(dev, SSD2825_VC_CTRL_REG, 0x0000);
/* Perform panel setup */
return panel_enable_backlight(priv->panel);
ret = panel_enable_backlight(priv->panel);
if (ret)
return ret;
ssd2825_write_register(dev, SSD2825_CONFIGURATION_REG,
SSD2825_CONF_REG_HS | SSD2825_CONF_REG_VEN |
SSD2825_CONF_REG_DCS | SSD2825_CONF_REG_ECD |
SSD2825_CONF_REG_EOT);
ssd2825_write_register(dev, SSD2825_PLL_CTRL_REG, 0x0001);
ssd2825_write_register(dev, SSD2825_VC_CTRL_REG, 0x0000);
return 0;
}
static int ssd2825_bridge_set_panel(struct udevice *dev, int percent)
@ -407,7 +450,8 @@ static int ssd2825_bridge_panel_timings(struct udevice *dev,
static int ssd2825_bridge_hw_init(struct udevice *dev)
{
struct ssd2825_bridge_priv *priv = dev_get_priv(dev);
int ret;
struct video_bridge_priv *uc_priv = dev_get_uclass_priv(dev);
int i, ret;
ret = clk_prepare_enable(priv->tx_clk);
if (ret) {
@ -416,25 +460,28 @@ static int ssd2825_bridge_hw_init(struct udevice *dev)
return ret;
}
ret = dm_gpio_set_value(&priv->power_gpio, 1);
/* enable supplies */
for (i = 0; i < ARRAY_SIZE(ssd2825_supplies); i++) {
ret = regulator_set_enable_if_allowed(priv->supplies[i], 1);
if (ret) {
log_debug("%s: cannot enable %s %d\n", __func__,
ssd2825_supplies[i], ret);
return ret;
}
}
mdelay(10);
ret = dm_gpio_set_value(&uc_priv->reset, 1);
if (ret) {
log_debug("%s: error changing power-gpios (%d)\n",
log_debug("%s: error entering reset (%d)\n",
__func__, ret);
return ret;
}
mdelay(10);
ret = dm_gpio_set_value(&priv->reset_gpio, 0);
ret = dm_gpio_set_value(&uc_priv->reset, 0);
if (ret) {
log_debug("%s: error changing reset-gpios (%d)\n",
__func__, ret);
return ret;
}
mdelay(10);
ret = dm_gpio_set_value(&priv->reset_gpio, 1);
if (ret) {
log_debug("%s: error changing reset-gpios (%d)\n",
log_debug("%s: error exiting reset (%d)\n",
__func__, ret);
return ret;
}
@ -443,13 +490,33 @@ static int ssd2825_bridge_hw_init(struct udevice *dev)
return 0;
}
static int ssd2825_bridge_get_panel(struct udevice *dev)
{
struct ssd2825_bridge_priv *priv = dev_get_priv(dev);
int i, ret;
u32 num = ofnode_graph_get_port_count(dev_ofnode(dev));
for (i = 0; i < num; i++) {
ofnode remote = ofnode_graph_get_remote_node(dev_ofnode(dev), i, -1);
ret = uclass_get_device_by_ofnode(UCLASS_PANEL, remote,
&priv->panel);
if (!ret)
return 0;
}
/* If this point is reached, no panels were found */
return -ENODEV;
}
static int ssd2825_bridge_probe(struct udevice *dev)
{
struct ssd2825_bridge_priv *priv = dev_get_priv(dev);
struct spi_slave *slave = dev_get_parent_priv(dev);
struct mipi_dsi_device *device = &priv->device;
struct mipi_dsi_panel_plat *mipi_plat;
int ret;
int i, ret;
ret = spi_claim_bus(slave);
if (ret) {
@ -457,10 +524,9 @@ static int ssd2825_bridge_probe(struct udevice *dev)
return ret;
}
ret = uclass_get_device_by_phandle(UCLASS_PANEL, dev,
"panel", &priv->panel);
ret = ssd2825_bridge_get_panel(dev);
if (ret) {
log_err("cannot get panel: ret=%d\n", ret);
log_debug("%s: panel not found, ret %d\n", __func__, ret);
return ret;
}
@ -477,33 +543,33 @@ static int ssd2825_bridge_probe(struct udevice *dev)
device->format = mipi_plat->format;
device->mode_flags = mipi_plat->mode_flags;
/* get panel gpios */
ret = gpio_request_by_name(dev, "power-gpios", 0,
&priv->power_gpio, GPIOD_IS_OUT);
if (ret) {
log_err("could not decode power-gpios (%d)\n", ret);
return ret;
}
ret = gpio_request_by_name(dev, "reset-gpios", 0,
&priv->reset_gpio, GPIOD_IS_OUT);
if (ret) {
log_err("could not decode reset-gpios (%d)\n", ret);
return ret;
/* get supplies */
for (i = 0; i < ARRAY_SIZE(ssd2825_supplies); i++) {
ret = device_get_supply_regulator(dev, ssd2825_supplies[i],
&priv->supplies[i]);
if (ret) {
log_debug("%s: cannot get %s %d\n", __func__,
ssd2825_supplies[i], ret);
if (ret != -ENOENT)
return log_ret(ret);
}
}
/* get clk */
priv->tx_clk = devm_clk_get(dev, "tx_clk");
priv->tx_clk = devm_clk_get_optional(dev, NULL);
if (IS_ERR(priv->tx_clk)) {
log_err("cannot get tx_clk: %ld\n", PTR_ERR(priv->tx_clk));
return PTR_ERR(priv->tx_clk);
}
priv->hzd = dev_read_u32_default(dev, "solomon,hs-zero-delay-ns", 133);
priv->hpd = dev_read_u32_default(dev, "solomon,hs-prep-delay-ns", 40);
return ssd2825_bridge_hw_init(dev);
}
static const struct panel_ops ssd2825_bridge_ops = {
.enable_backlight = ssd2825_bridge_enable_panel,
static const struct video_bridge_ops ssd2825_bridge_ops = {
.attach = ssd2825_bridge_attach,
.set_backlight = ssd2825_bridge_set_panel,
.get_display_timing = ssd2825_bridge_panel_timings,
};
@ -515,9 +581,10 @@ static const struct udevice_id ssd2825_bridge_ids[] = {
U_BOOT_DRIVER(ssd2825) = {
.name = "ssd2825",
.id = UCLASS_PANEL,
.id = UCLASS_VIDEO_BRIDGE,
.of_match = ssd2825_bridge_ids,
.ops = &ssd2825_bridge_ops,
.bind = dm_scan_fdt_dev,
.probe = ssd2825_bridge_probe,
.priv_auto = sizeof(struct ssd2825_bridge_priv),
};

View file

@ -6,12 +6,14 @@
#include <clk.h>
#include <dm.h>
#include <dm/ofnode_graph.h>
#include <i2c.h>
#include <log.h>
#include <mipi_display.h>
#include <mipi_dsi.h>
#include <backlight.h>
#include <panel.h>
#include <video_bridge.h>
#include <linux/delay.h>
#include <linux/err.h>
#include <linux/kernel.h>
@ -122,6 +124,10 @@
#define NANO 1000000000UL
#define PICO 1000000000000ULL
static const char * const tc358768_supplies[] = {
"vddc-supply", "vddmipi-supply", "vddio-supply"
};
struct tc358768_priv {
struct mipi_dsi_host host;
struct mipi_dsi_device device;
@ -129,9 +135,7 @@ struct tc358768_priv {
struct udevice *panel;
struct display_timing timing;
struct udevice *vddc;
struct udevice *vddmipi;
struct udevice *vddio;
struct udevice *supplies[ARRAY_SIZE(tc358768_supplies)];
struct clk *refclk;
@ -265,25 +269,27 @@ static void tc358768_sw_reset(struct udevice *dev)
tc358768_write(dev, TC358768_SYSCTL, 0);
}
static void tc358768_hw_enable(struct tc358768_priv *priv)
static void tc358768_hw_enable(struct udevice *dev)
{
struct tc358768_priv *priv = dev_get_priv(dev);
struct video_bridge_priv *uc_priv = dev_get_uclass_priv(dev);
int ret;
ret = clk_prepare_enable(priv->refclk);
if (ret)
log_debug("%s: error enabling refclk (%d)\n", __func__, ret);
ret = regulator_set_enable_if_allowed(priv->vddc, true);
ret = regulator_set_enable_if_allowed(priv->supplies[0], true);
if (ret)
log_debug("%s: error enabling vddc (%d)\n", __func__, ret);
ret = regulator_set_enable_if_allowed(priv->vddmipi, true);
ret = regulator_set_enable_if_allowed(priv->supplies[1], true);
if (ret)
log_debug("%s: error enabling vddmipi (%d)\n", __func__, ret);
mdelay(10);
ret = regulator_set_enable_if_allowed(priv->vddio, true);
ret = regulator_set_enable_if_allowed(priv->supplies[2], true);
if (ret)
log_debug("%s: error enabling vddio (%d)\n", __func__, ret);
@ -293,7 +299,7 @@ static void tc358768_hw_enable(struct tc358768_priv *priv)
* The RESX is active low (GPIO_ACTIVE_LOW).
* DEASSERT (value = 0) the reset_gpio to enable the chip
*/
ret = dm_gpio_set_value(&priv->reset_gpio, 0);
ret = dm_gpio_set_value(&uc_priv->reset, 0);
if (ret)
log_debug("%s: error changing reset-gpio (%d)\n", __func__, ret);
@ -477,7 +483,7 @@ static int tc358768_attach(struct udevice *dev)
device->mode_flags &= ~MIPI_DSI_CLOCK_NON_CONTINUOUS;
}
tc358768_hw_enable(priv);
tc358768_hw_enable(dev);
tc358768_sw_reset(dev);
tc358768_setup_pll(dev);
@ -874,12 +880,33 @@ static int tc358768_panel_timings(struct udevice *dev,
return 0;
}
static int tc358768_get_panel(struct udevice *dev)
{
struct tc358768_priv *priv = dev_get_priv(dev);
int i, ret;
u32 num = ofnode_graph_get_port_count(dev_ofnode(dev));
for (i = 0; i < num; i++) {
ofnode remote = ofnode_graph_get_remote_node(dev_ofnode(dev), i, -1);
ret = uclass_get_device_by_ofnode(UCLASS_PANEL, remote,
&priv->panel);
if (!ret)
return 0;
}
/* If this point is reached, no panels were found */
return -ENODEV;
}
static int tc358768_setup(struct udevice *dev)
{
struct tc358768_priv *priv = dev_get_priv(dev);
struct video_bridge_priv *uc_priv = dev_get_uclass_priv(dev);
struct mipi_dsi_device *device = &priv->device;
struct mipi_dsi_panel_plat *mipi_plat;
int ret;
int i, ret;
/* The bridge uses 16 bit registers */
ret = i2c_set_chip_offset_len(dev, 2);
@ -889,11 +916,10 @@ static int tc358768_setup(struct udevice *dev)
return ret;
}
ret = uclass_get_device_by_phandle(UCLASS_PANEL, dev,
"panel", &priv->panel);
ret = tc358768_get_panel(dev);
if (ret) {
log_debug("%s: Cannot get panel: ret=%d\n", __func__, ret);
return log_ret(ret);
log_debug("%s: panel not found, ret %d\n", __func__, ret);
return ret;
}
panel_get_display_timing(priv->panel, &priv->timing);
@ -913,44 +939,26 @@ static int tc358768_setup(struct udevice *dev)
priv->dsi_lanes = device->lanes;
/* get regulators */
ret = device_get_supply_regulator(dev, "vddc-supply", &priv->vddc);
if (ret) {
log_debug("%s: vddc regulator error: %d\n", __func__, ret);
if (ret != -ENOENT)
return log_ret(ret);
}
ret = device_get_supply_regulator(dev, "vddmipi-supply", &priv->vddmipi);
if (ret) {
log_debug("%s: vddmipi regulator error: %d\n", __func__, ret);
if (ret != -ENOENT)
return log_ret(ret);
}
ret = device_get_supply_regulator(dev, "vddio-supply", &priv->vddio);
if (ret) {
log_debug("%s: vddio regulator error: %d\n", __func__, ret);
if (ret != -ENOENT)
return log_ret(ret);
for (i = 0; i < ARRAY_SIZE(tc358768_supplies); i++) {
ret = device_get_supply_regulator(dev, tc358768_supplies[i],
&priv->supplies[i]);
if (ret) {
log_debug("%s: cannot get %s %d\n", __func__,
tc358768_supplies[i], ret);
if (ret != -ENOENT)
return log_ret(ret);
}
}
/* get clk */
priv->refclk = devm_clk_get(dev, "refclk");
priv->refclk = devm_clk_get(dev, NULL);
if (IS_ERR(priv->refclk)) {
log_debug("%s: Could not get refclk: %ld\n",
__func__, PTR_ERR(priv->refclk));
return PTR_ERR(priv->refclk);
}
/* get gpios */
ret = gpio_request_by_name(dev, "reset-gpios", 0,
&priv->reset_gpio, GPIOD_IS_OUT);
if (ret) {
log_debug("%s: Could not decode reset-gpios (%d)\n", __func__, ret);
return ret;
}
dm_gpio_set_value(&priv->reset_gpio, 1);
dm_gpio_set_value(&uc_priv->reset, 1);
return 0;
}
@ -963,8 +971,8 @@ static int tc358768_probe(struct udevice *dev)
return tc358768_setup(dev);
}
struct panel_ops tc358768_ops = {
.enable_backlight = tc358768_attach,
static const struct video_bridge_ops tc358768_ops = {
.attach = tc358768_attach,
.set_backlight = tc358768_set_backlight,
.get_display_timing = tc358768_panel_timings,
};
@ -977,9 +985,10 @@ static const struct udevice_id tc358768_ids[] = {
U_BOOT_DRIVER(tc358768) = {
.name = "tc358768",
.id = UCLASS_PANEL,
.id = UCLASS_VIDEO_BRIDGE,
.of_match = tc358768_ids,
.ops = &tc358768_ops,
.bind = dm_scan_fdt_dev,
.probe = tc358768_probe,
.priv_auto = sizeof(struct tc358768_priv),
};

View file

@ -117,6 +117,18 @@ static int endeavoru_panel_set_backlight(struct udevice *dev, int percent)
struct endeavoru_panel_priv *priv = dev_get_priv(dev);
int ret;
/*
* Due to the use of the Tegra DC backlight feature, backlight
* requests MUST NOT be made during probe or earlier. This is
* because it creates a loop, as the backlight is a DC child.
*/
ret = uclass_get_device_by_phandle(UCLASS_PANEL_BACKLIGHT, dev,
"backlight", &priv->backlight);
if (ret) {
log_err("cannot get backlight: ret = %d\n", ret);
return ret;
}
ret = backlight_enable(priv->backlight);
if (ret)
return ret;
@ -136,13 +148,6 @@ static int endeavoru_panel_of_to_plat(struct udevice *dev)
struct endeavoru_panel_priv *priv = dev_get_priv(dev);
int ret;
ret = uclass_get_device_by_phandle(UCLASS_PANEL_BACKLIGHT, dev,
"backlight", &priv->backlight);
if (ret) {
log_err("cannot get backlight: ret = %d\n", ret);
return ret;
}
ret = uclass_get_device_by_phandle(UCLASS_REGULATOR, dev,
"vdd-supply", &priv->vdd);
if (ret) {
@ -231,7 +236,7 @@ static int endeavoru_panel_probe(struct udevice *dev)
/* fill characteristics of DSI data link */
plat->lanes = 2;
plat->format = MIPI_DSI_FMT_RGB888;
plat->mode_flags = MIPI_DSI_MODE_VIDEO;
plat->mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_LPM;
return endeavoru_panel_hw_init(dev);
}

View file

@ -158,7 +158,7 @@ static int lg_ld070wx3_probe(struct udevice *dev)
/* fill characteristics of DSI data link */
plat->lanes = 4;
plat->format = MIPI_DSI_FMT_RGB888;
plat->mode_flags = MIPI_DSI_MODE_VIDEO;
plat->mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_LPM;
return lg_ld070wx3_hw_init(dev);
}

View file

@ -7,6 +7,7 @@
#include <backlight.h>
#include <dm.h>
#include <dm/ofnode.h>
#include <i2c.h>
#include <log.h>
#include <linux/delay.h>
@ -17,56 +18,79 @@
#define LM3533_BL_MAX_BRIGHTNESS 0xFF
#define LM3533_SINK_OUTPUT_CONFIG_1 0x10
#define LM3533_CONTROL_BANK_A_PWM 0x14
#define LM3533_CONTROL_PWM_BASE 0x14
#define PWM_MAX GENMASK(5, 0)
#define LM3533_CONTROL_BANK_AB_BRIGHTNESS 0x1A
#define LM3533_CONTROL_BANK_A_FULLSCALE_CURRENT 0x1F
#define LM3533_CONTROL_FULLSCALE_CURRENT_BASE 0x1F
#define MAX_CURRENT_MIN 5000
#define MAX_CURRENT_MAX 29800
#define MAX_CURRENT_STEP 800
#define LM3533_CONTROL_BANK_ENABLE 0x27
#define LM3533_OVP_FREQUENCY_PWM_POLARITY 0x2C
#define BOOST_OVP_MASK GENMASK(2, 1)
#define BOOST_OVP_SHIFT 1
#define BOOST_FREQ_MASK BIT(0)
#define BOOST_FREQ_SHIFT 0
#define LM3533_BRIGHTNESS_REGISTER_A 0x40
#define LM3533_BOOST_OVP_16V 16000000UL
#define LM3533_BOOST_FREQ_500KHZ 500000UL
struct lm3533_backlight_priv {
struct gpio_desc enable_gpio;
u32 def_bl_lvl;
/* Core */
u32 boost_ovp;
u32 boost_freq;
/* Backlight */
u32 reg;
u16 max_current; /* 5000 - 29800 uA (800 uA step) */
u8 pwm; /* 0 - 0x3f */
bool linear;
bool hvled;
};
static int lm3533_backlight_enable(struct udevice *dev)
{
struct lm3533_backlight_priv *priv = dev_get_priv(dev);
u8 val, id = priv->reg;
int ret;
dm_gpio_set_value(&priv->enable_gpio, 1);
mdelay(5);
if (priv->linear) {
ret = dm_i2c_reg_clrset(dev, LM3533_CONTROL_BANK_AB_BRIGHTNESS,
BIT(2 * id + 1), BIT(2 * id + 1));
if (ret)
return ret;
}
/* HVLED 1 & 2 are controlled by Bank A */
ret = dm_i2c_reg_write(dev, LM3533_SINK_OUTPUT_CONFIG_1, 0x00);
if (priv->hvled) {
ret = dm_i2c_reg_clrset(dev, LM3533_SINK_OUTPUT_CONFIG_1,
BIT(0) | BIT(1), id | id << 1);
if (ret)
return ret;
}
/* Set current */
if (priv->max_current < MAX_CURRENT_MIN || priv->max_current > MAX_CURRENT_MAX)
return -EINVAL;
val = (priv->max_current - MAX_CURRENT_MIN) / MAX_CURRENT_STEP;
ret = dm_i2c_reg_write(dev, LM3533_CONTROL_FULLSCALE_CURRENT_BASE + id, val);
if (ret)
return ret;
/* PWM input is disabled for CABC */
ret = dm_i2c_reg_write(dev, LM3533_CONTROL_BANK_A_PWM, 0x00);
/* Set PWM mask */
if (priv->pwm > PWM_MAX)
return -EINVAL;
ret = dm_i2c_reg_write(dev, LM3533_CONTROL_PWM_BASE + id, priv->pwm);
if (ret)
return ret;
/* Linear & Control Bank A is configured for register Current control */
ret = dm_i2c_reg_write(dev, LM3533_CONTROL_BANK_AB_BRIGHTNESS, 0x02);
if (ret)
return ret;
/* Full-Scale Current (20.2mA) */
ret = dm_i2c_reg_write(dev, LM3533_CONTROL_BANK_A_FULLSCALE_CURRENT, 0x13);
if (ret)
return ret;
/* Control Bank A is enable */
ret = dm_i2c_reg_write(dev, LM3533_CONTROL_BANK_ENABLE, 0x01);
if (ret)
return ret;
ret = dm_i2c_reg_write(dev, LM3533_OVP_FREQUENCY_PWM_POLARITY, 0x0A);
if (ret)
return ret;
return 0;
/* Enable Control Bank */
return dm_i2c_reg_clrset(dev, LM3533_CONTROL_BANK_ENABLE, BIT(id), BIT(id));
}
static int lm3533_backlight_set_brightness(struct udevice *dev, int percent)
@ -92,14 +116,12 @@ static int lm3533_backlight_set_brightness(struct udevice *dev, int percent)
return 0;
}
static int lm3533_backlight_probe(struct udevice *dev)
static int lm3533_backlight_of_to_plat(struct udevice *dev)
{
struct lm3533_backlight_priv *priv = dev_get_priv(dev);
ofnode child;
int ret;
if (device_get_uclass_id(dev->parent) != UCLASS_I2C)
return -EPROTONOSUPPORT;
ret = gpio_request_by_name(dev, "enable-gpios", 0,
&priv->enable_gpio, GPIOD_IS_OUT);
if (ret) {
@ -107,8 +129,67 @@ static int lm3533_backlight_probe(struct udevice *dev)
return ret;
}
priv->def_bl_lvl = dev_read_u32_default(dev, "default-brightness-level",
LM3533_BL_MAX_BRIGHTNESS);
priv->boost_ovp = dev_read_u32_default(dev, "ti,boost-ovp-microvolt",
LM3533_BOOST_OVP_16V);
/* boost_ovp is defined in microvolts, convert to enum value */
priv->boost_ovp = priv->boost_ovp / (8 * 1000 * 1000) - 2;
priv->boost_freq = dev_read_u32_default(dev, "ti,boost-freq-hz",
LM3533_BOOST_FREQ_500KHZ);
/* boost_freq is defined in Hz, convert to enum value */
priv->boost_freq = priv->boost_freq / (500 * 1000) - 1;
/* Backlight is one of children but has no dedicated driver */
ofnode_for_each_subnode(child, dev_ofnode(dev)) {
if (ofnode_device_is_compatible(child, "ti,lm3533-backlight")) {
const char *node_name = ofnode_get_name(child);
if (!strcmp(&node_name[10], "1"))
priv->reg = 1;
else
priv->reg = 0;
priv->max_current = ofnode_read_u32_default(child, "ti,max-current-microamp",
5000);
priv->pwm = ofnode_read_u32_default(child, "ti,pwm-config-mask", 0);
priv->def_bl_lvl = ofnode_read_u32_default(child, "default-brightness",
LM3533_BL_MAX_BRIGHTNESS);
priv->linear = ofnode_read_bool(child, "ti,linear-mapping-mode");
priv->hvled = ofnode_read_bool(child, "ti,hardware-controlled");
}
}
return 0;
}
static int lm3533_backlight_probe(struct udevice *dev)
{
struct lm3533_backlight_priv *priv = dev_get_priv(dev);
int ret;
if (device_get_uclass_id(dev->parent) != UCLASS_I2C)
return -EPROTONOSUPPORT;
dm_gpio_set_value(&priv->enable_gpio, 1);
mdelay(5);
ret = dm_i2c_reg_clrset(dev, LM3533_OVP_FREQUENCY_PWM_POLARITY,
BOOST_FREQ_MASK, priv->boost_freq << BOOST_FREQ_SHIFT);
if (ret) {
log_debug("%s: freq config failed %d\n", __func__, ret);
return ret;
}
ret = dm_i2c_reg_clrset(dev, LM3533_OVP_FREQUENCY_PWM_POLARITY,
BOOST_OVP_MASK, priv->boost_ovp << BOOST_OVP_SHIFT);
if (ret) {
log_debug("%s: ovp config failed %d\n", __func__, ret);
return ret;
}
return 0;
}
@ -127,6 +208,7 @@ U_BOOT_DRIVER(lm3533_backlight) = {
.name = "lm3533_backlight",
.id = UCLASS_PANEL_BACKLIGHT,
.of_match = lm3533_backlight_ids,
.of_to_plat = lm3533_backlight_of_to_plat,
.probe = lm3533_backlight_probe,
.ops = &lm3533_backlight_ops,
.priv_auto = sizeof(struct lm3533_backlight_priv),

View file

@ -254,17 +254,17 @@ static int renesas_r61307_hw_init(struct udevice *dev)
return ret;
}
ret = dm_gpio_set_value(&priv->reset_gpio, 0);
ret = dm_gpio_set_value(&priv->reset_gpio, 1);
if (ret) {
log_debug("%s: changing reset-gpio failed (%d)\n",
log_debug("%s: entering reset failed (%d)\n",
__func__, ret);
return ret;
}
mdelay(5);
ret = dm_gpio_set_value(&priv->reset_gpio, 1);
ret = dm_gpio_set_value(&priv->reset_gpio, 0);
if (ret) {
log_debug("%s: changing reset-gpio failed (%d)\n",
log_debug("%s: exiting reset failed (%d)\n",
__func__, ret);
return ret;
}
@ -281,7 +281,8 @@ static int renesas_r61307_probe(struct udevice *dev)
/* fill characteristics of DSI data link */
plat->lanes = 4;
plat->format = MIPI_DSI_FMT_RGB888;
plat->mode_flags = MIPI_DSI_MODE_VIDEO;
plat->mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_SYNC_PULSE |
MIPI_DSI_CLOCK_NON_CONTINUOUS | MIPI_DSI_MODE_LPM;
return renesas_r61307_hw_init(dev);
}
@ -294,7 +295,7 @@ static const struct panel_ops renesas_r61307_ops = {
static const struct udevice_id renesas_r61307_ids[] = {
{ .compatible = "koe,tx13d100vm0eaa" },
{ .compatible = "hitachi,tx13d100vm0eaa" },
{ .compatible = "hit,tx13d100vm0eaa" },
{ }
};

View file

@ -32,9 +32,11 @@
#define R69328_POWER_SET 0xD1
struct renesas_r69328_priv {
struct udevice *vdd;
struct udevice *vddio;
struct udevice *backlight;
struct gpio_desc enable_gpio;
struct gpio_desc reset_gpio;
};
@ -159,10 +161,15 @@ static int renesas_r69328_of_to_plat(struct udevice *dev)
return ret;
}
ret = gpio_request_by_name(dev, "enable-gpios", 0,
&priv->enable_gpio, GPIOD_IS_OUT);
ret = device_get_supply_regulator(dev, "vdd-supply", &priv->vdd);
if (ret) {
log_err("could not decode enable-gpios (%d)\n", ret);
log_err("Cannot get vdd-supply: ret = %d\n", ret);
return ret;
}
ret = device_get_supply_regulator(dev, "vddio-supply", &priv->vddio);
if (ret) {
log_err("Cannot get vddio-supply: ret = %d\n", ret);
return ret;
}
@ -181,9 +188,24 @@ static int renesas_r69328_hw_init(struct udevice *dev)
struct renesas_r69328_priv *priv = dev_get_priv(dev);
int ret;
ret = dm_gpio_set_value(&priv->enable_gpio, 1);
ret = regulator_set_enable_if_allowed(priv->vddio, 1);
if (ret) {
log_debug("%s: error changing enable-gpios (%d)\n",
log_debug("%s: enabling vddio-supply failed (%d)\n",
__func__, ret);
return ret;
}
mdelay(5);
ret = regulator_set_enable_if_allowed(priv->vdd, 1);
if (ret) {
log_debug("%s: enabling vdd-supply failed (%d)\n",
__func__, ret);
return ret;
}
ret = dm_gpio_set_value(&priv->reset_gpio, 1);
if (ret) {
log_debug("%s: error entering reset (%d)\n",
__func__, ret);
return ret;
}
@ -191,15 +213,7 @@ static int renesas_r69328_hw_init(struct udevice *dev)
ret = dm_gpio_set_value(&priv->reset_gpio, 0);
if (ret) {
log_debug("%s: error changing reset-gpios (%d)\n",
__func__, ret);
return ret;
}
mdelay(5);
ret = dm_gpio_set_value(&priv->reset_gpio, 1);
if (ret) {
log_debug("%s: error changing reset-gpios (%d)\n",
log_debug("%s: error exiting reset (%d)\n",
__func__, ret);
return ret;
}
@ -216,7 +230,8 @@ static int renesas_r69328_probe(struct udevice *dev)
/* fill characteristics of DSI data link */
plat->lanes = 4;
plat->format = MIPI_DSI_FMT_RGB888;
plat->mode_flags = MIPI_DSI_MODE_VIDEO;
plat->mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_SYNC_PULSE |
MIPI_DSI_CLOCK_NON_CONTINUOUS | MIPI_DSI_MODE_LPM;
return renesas_r69328_hw_init(dev);
}

View file

@ -129,7 +129,7 @@ static int samsung_ltl106hl02_probe(struct udevice *dev)
/* fill characteristics of DSI data link */
plat->lanes = 4;
plat->format = MIPI_DSI_FMT_RGB888;
plat->mode_flags = MIPI_DSI_MODE_VIDEO;
plat->mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_LPM;
return samsung_ltl106hl02_hw_init(dev);
}

View file

@ -255,6 +255,7 @@ static int sharp_lq101r1sx01_probe(struct udevice *dev)
/* fill characteristics of DSI data link */
plat->lanes = 4;
plat->format = MIPI_DSI_FMT_RGB888;
plat->mode_flags = MIPI_DSI_MODE_LPM;
return sharp_lq101r1sx01_hw_init(dev);
}

View file

@ -1,6 +1,11 @@
config HOST1X_TEGRA
bool "NVIDIA Tegra host1x BUS support"
depends on SIMPLE_BUS
config VIDEO_TEGRA20
bool "Enable Display Controller support on Tegra20 and Tegra 30"
depends on OF_CONTROL
select HOST1X_TEGRA
help
T20/T30 support video output to an attached LCD panel as well as
other options such as HDMI. Only the LCD is supported in U-Boot.
@ -9,13 +14,22 @@ config VIDEO_TEGRA20
config VIDEO_DSI_TEGRA30
bool "Enable Tegra 30 DSI support"
depends on PANEL && DM_GPIO
depends on VIDEO_BRIDGE && PANEL && DM_GPIO
select VIDEO_TEGRA20
select VIDEO_MIPI_DSI
help
T30 has native support for DSI panels. This option enables support
for such panels which can be used on endeavoru and tf600t.
config VIDEO_HDMI_TEGRA
bool "Enable Tegra HDMI support"
depends on VIDEO_BRIDGE && DM_I2C
select I2C_EDID
select VIDEO_TEGRA20
help
Tegra has native support for HDMI. This option enables support
for such connection and can be used for any supported device.
config TEGRA_BACKLIGHT_PWM
bool "Enable Tegra DC PWM backlight support"
depends on BACKLIGHT

View file

@ -1,5 +1,7 @@
# SPDX-License-Identifier: GPL-2.0+
obj-$(CONFIG_HOST1X_TEGRA) += tegra-host1x.o
obj-$(CONFIG_VIDEO_TEGRA20) += tegra-dc.o
obj-$(CONFIG_VIDEO_DSI_TEGRA30) += tegra-dsi.o tegra-mipi.o mipi-phy.o
obj-$(CONFIG_VIDEO_HDMI_TEGRA) += tegra-hdmi.o
obj-$(CONFIG_TEGRA_BACKLIGHT_PWM) += tegra-pwm-backlight.o

View file

@ -1,16 +1,19 @@
// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright (c) 2011 The Chromium OS Authors.
* Copyright (c) 2024 Svyatoslav Ryhel <clamor95@gmail.com>
*/
#include <backlight.h>
#include <cpu_func.h>
#include <clk.h>
#include <dm.h>
#include <dm/ofnode_graph.h>
#include <fdtdec.h>
#include <log.h>
#include <panel.h>
#include <video.h>
#include <video_bridge.h>
#include <asm/system.h>
#include <asm/io.h>
#include <asm/arch/clock.h>
@ -31,7 +34,8 @@ struct tegra_lcd_priv {
int height; /* height in pixels */
enum video_log2_bpp log2_bpp; /* colour depth */
struct display_timing timing;
struct udevice *panel;
struct udevice *panel; /* Panels attached to RGB */
struct udevice *bridge; /* Bridge linked with DC */
struct dc_ctlr *dc; /* Display controller regmap */
const struct tegra_dc_soc_info *soc;
fdt_addr_t frame_buffer; /* Address of frame buffer */
@ -319,11 +323,6 @@ static int tegra_display_probe(struct tegra_lcd_priv *priv,
/ priv->pixel_clock) - 2;
log_debug("Display clock %lu, divider %lu\n", rate, priv->scdiv);
/*
* HOST1X is init by default at 150MHz with PLLC as parent
*/
clock_start_periph_pll(PERIPH_ID_HOST1X, CLOCK_ID_CGENERAL,
150 * 1000000);
clock_start_periph_pll(priv->clk->id, priv->clk_parent->id,
rate);
@ -378,11 +377,12 @@ static int tegra_lcd_probe(struct udevice *dev)
}
/* Get shift clock divider from Tegra DSI if used */
if (!strcmp(priv->panel->name, TEGRA_DSI_A) ||
!strcmp(priv->panel->name, TEGRA_DSI_B)) {
struct tegra_dc_plat *dc_plat = dev_get_plat(priv->panel);
if (priv->bridge) {
if (!strcmp(priv->bridge->driver->name, "tegra_dsi")) {
struct tegra_dc_plat *dc_plat = dev_get_plat(priv->bridge);
priv->scdiv = dc_plat->scdiv;
priv->scdiv = dc_plat->scdiv;
}
}
/* Clean the framebuffer area */
@ -395,10 +395,20 @@ static int tegra_lcd_probe(struct udevice *dev)
return ret;
}
ret = panel_enable_backlight(priv->panel);
if (ret) {
log_debug("%s: Cannot enable backlight, ret=%d\n", __func__, ret);
return ret;
if (priv->panel) {
ret = panel_enable_backlight(priv->panel);
if (ret) {
log_debug("%s: Cannot enable backlight, ret=%d\n", __func__, ret);
return ret;
}
}
if (priv->bridge) {
ret = video_bridge_attach(priv->bridge);
if (ret) {
log_debug("%s: Cannot attach bridge, ret=%d\n", __func__, ret);
return ret;
}
}
mmu_set_region_dcache_behaviour(priv->frame_buffer, plat->size,
@ -413,17 +423,129 @@ static int tegra_lcd_probe(struct udevice *dev)
log_debug("LCD frame buffer at %08x, size %x\n", priv->frame_buffer,
plat->size);
return panel_set_backlight(priv->panel, BACKLIGHT_DEFAULT);
if (priv->panel) {
ret = panel_set_backlight(priv->panel, BACKLIGHT_DEFAULT);
if (ret)
return ret;
}
if (priv->bridge) {
ret = video_bridge_set_backlight(priv->bridge, BACKLIGHT_DEFAULT);
if (ret)
return ret;
}
return 0;
}
static int tegra_lcd_configure_rgb(struct udevice *dev, ofnode rgb)
{
struct tegra_lcd_priv *priv = dev_get_priv(dev);
ofnode remote;
int ret;
/* DC can have only 1 port */
remote = ofnode_graph_get_remote_node(rgb, -1, -1);
ret = uclass_get_device_by_ofnode(UCLASS_PANEL, remote, &priv->panel);
if (!ret)
return 0;
ret = uclass_get_device_by_ofnode(UCLASS_VIDEO_BRIDGE, remote, &priv->bridge);
if (!ret)
return 0;
/* Try legacy method if graph did not work */
remote = ofnode_parse_phandle(rgb, "nvidia,panel", 0);
if (!ofnode_valid(remote))
return -EINVAL;
ret = uclass_get_device_by_ofnode(UCLASS_PANEL, remote, &priv->panel);
if (ret) {
log_debug("%s: Cannot find panel for '%s' (ret=%d)\n",
__func__, dev->name, ret);
ret = uclass_get_device_by_ofnode(UCLASS_VIDEO_BRIDGE, remote,
&priv->bridge);
if (ret) {
log_err("%s: Cannot find panel or bridge for '%s' (ret=%d)\n",
__func__, dev->name, ret);
return ret;
}
}
return 0;
}
static int tegra_lcd_configure_internal(struct udevice *dev)
{
struct tegra_lcd_priv *priv = dev_get_priv(dev);
struct tegra_dc_plat *dc_plat;
ofnode host1x = ofnode_get_parent(dev_ofnode(dev));
ofnode node;
int ret;
switch (priv->pipe) {
case 0: /* DC0 is usually used for DSI */
/* Check for ganged DSI configuration */
ofnode_for_each_subnode(node, host1x)
if (ofnode_name_eq(node, "dsi") && ofnode_is_enabled(node) &&
ofnode_read_bool(node, "nvidia,ganged-mode"))
goto exit;
/* If no master DSI found loop for any active DSI */
ofnode_for_each_subnode(node, host1x)
if (ofnode_name_eq(node, "dsi") && ofnode_is_enabled(node))
goto exit;
log_err("%s: failed to find DSI device for '%s'\n",
__func__, dev->name);
return -ENODEV;
case 1: /* DC1 is usually used for HDMI */
ofnode_for_each_subnode(node, host1x)
if (ofnode_name_eq(node, "hdmi"))
goto exit;
log_err("%s: failed to find HDMI device for '%s'\n",
__func__, dev->name);
return -ENODEV;
default:
log_debug("Unsupported DC selection\n");
return -EINVAL;
}
exit:
ret = uclass_get_device_by_ofnode(UCLASS_VIDEO_BRIDGE, node, &priv->bridge);
if (ret) {
log_err("%s: failed to get DSI/HDMI device for '%s' (ret %d)\n",
__func__, dev->name, ret);
return ret;
}
priv->clk_parent = devm_clk_get(priv->bridge, "parent");
if (IS_ERR(priv->clk_parent)) {
log_debug("%s: Could not get DC clock parent from DSI/HDMI: %ld\n",
__func__, PTR_ERR(priv->clk_parent));
return PTR_ERR(priv->clk_parent);
}
dc_plat = dev_get_plat(priv->bridge);
/* Fill the platform data for internal devices */
dc_plat->dev = dev;
dc_plat->dc = priv->dc;
dc_plat->pipe = priv->pipe;
return 0;
}
static int tegra_lcd_of_to_plat(struct udevice *dev)
{
struct tegra_lcd_priv *priv = dev_get_priv(dev);
const void *blob = gd->fdt_blob;
struct display_timing *timing;
int node = dev_of_offset(dev);
int panel_node;
int rgb;
ofnode rgb;
int ret;
priv->dc = (struct dc_ctlr *)dev_read_addr_ptr(dev);
@ -451,44 +573,42 @@ static int tegra_lcd_of_to_plat(struct udevice *dev)
priv->rotation = dev_read_bool(dev, "nvidia,180-rotation");
priv->pipe = dev_read_u32_default(dev, "nvidia,head", 0);
rgb = fdt_subnode_offset(blob, node, "rgb");
if (rgb < 0) {
log_debug("%s: Cannot find rgb subnode for '%s' (ret=%d)\n",
__func__, dev->name, rgb);
return -EINVAL;
}
/*
* Sadly the panel phandle is in an rgb subnode so we cannot use
* uclass_get_device_by_phandle().
* Usual logic of Tegra video routing should be next:
* 1. Check rgb subnode for RGB/LVDS panels or bridges
* 2. If none found, then iterate through bridges bound,
* looking for DSIA or DSIB for DC0 and HDMI for DC1.
* If none of above is valid, then configuration is not
* valid.
*/
panel_node = fdtdec_lookup_phandle(blob, rgb, "nvidia,panel");
if (panel_node < 0) {
log_debug("%s: Cannot find panel information\n", __func__);
return -EINVAL;
rgb = dev_read_subnode(dev, "rgb");
if (ofnode_valid(rgb) && ofnode_is_enabled(rgb)) {
/* RGB is available, use it */
ret = tegra_lcd_configure_rgb(dev, rgb);
if (ret)
return ret;
} else {
/* RGB is not available, check for internal devices */
ret = tegra_lcd_configure_internal(dev);
if (ret)
return ret;
}
ret = uclass_get_device_by_of_offset(UCLASS_PANEL, panel_node,
&priv->panel);
if (ret) {
log_debug("%s: Cannot find panel for '%s' (ret=%d)\n", __func__,
dev->name, ret);
return ret;
if (priv->panel) {
ret = panel_get_display_timing(priv->panel, &priv->timing);
if (ret) {
ret = ofnode_decode_display_timing(rgb, 0, &priv->timing);
if (ret) {
log_debug("%s: Cannot read display timing for '%s' (ret=%d)\n",
__func__, dev->name, ret);
return -EINVAL;
}
}
}
/* Fill the platform data for internal devices */
if (!strcmp(priv->panel->name, TEGRA_DSI_A) ||
!strcmp(priv->panel->name, TEGRA_DSI_B)) {
struct tegra_dc_plat *dc_plat = dev_get_plat(priv->panel);
dc_plat->dev = dev;
dc_plat->dc = priv->dc;
dc_plat->pipe = priv->pipe;
}
ret = panel_get_display_timing(priv->panel, &priv->timing);
if (ret) {
ret = fdtdec_decode_display_timing(blob, rgb, 0, &priv->timing);
if (priv->bridge) {
ret = video_bridge_get_display_timing(priv->bridge, &priv->timing);
if (ret) {
log_debug("%s: Cannot read display timing for '%s' (ret=%d)\n",
__func__, dev->name, ret);
@ -508,23 +628,13 @@ static int tegra_lcd_of_to_plat(struct udevice *dev)
static int tegra_lcd_bind(struct udevice *dev)
{
struct video_uc_plat *plat = dev_get_uclass_plat(dev);
const void *blob = gd->fdt_blob;
int node = dev_of_offset(dev);
int rgb;
rgb = fdt_subnode_offset(blob, node, "rgb");
if ((rgb < 0) || !fdtdec_get_is_enabled(blob, rgb))
return -ENODEV;
plat->size = LCD_MAX_WIDTH * LCD_MAX_HEIGHT *
(1 << LCD_MAX_LOG2_BPP) / 8;
return 0;
return dm_scan_fdt_dev(dev);
}
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,
@ -565,7 +675,6 @@ U_BOOT_DRIVER(tegra_lcd) = {
.name = "tegra_lcd",
.id = UCLASS_VIDEO,
.of_match = tegra_lcd_ids,
.ops = &tegra_lcd_ops,
.bind = tegra_lcd_bind,
.probe = tegra_lcd_probe,
.of_to_plat = tegra_lcd_of_to_plat,

View file

@ -14,9 +14,6 @@
/* arch-tegra/dc exists only because T124 uses it */
#include <asm/arch-tegra/dc.h>
#define TEGRA_DSI_A "dsi@54300000"
#define TEGRA_DSI_B "dsi@54400000"
struct tegra_dc_plat {
struct udevice *dev; /* Display controller device */
struct dc_ctlr *dc; /* Display controller regmap */

View file

@ -11,6 +11,7 @@
#include <mipi_display.h>
#include <mipi_dsi.h>
#include <backlight.h>
#include <video_bridge.h>
#include <panel.h>
#include <reset.h>
#include <linux/delay.h>
@ -250,6 +251,9 @@ static ssize_t tegra_dsi_host_transfer(struct mipi_dsi_host *host,
value = DSI_HOST_CONTROL_CRC_RESET | DSI_HOST_CONTROL_TX_TRIG_HOST |
DSI_HOST_CONTROL_CS | DSI_HOST_CONTROL_ECC;
if ((msg->flags & MIPI_DSI_MSG_USE_LPM) == 0)
value |= DSI_HOST_CONTROL_HS;
/*
* The host FIFO has a maximum of 64 words, so larger transmissions
* need to use the video FIFO.
@ -991,7 +995,7 @@ static int tegra_dsi_ganged_probe(struct udevice *dev)
struct tegra_dsi_priv *mpriv = dev_get_priv(dev);
struct udevice *gangster;
uclass_get_device_by_phandle(UCLASS_PANEL, dev,
uclass_get_device_by_phandle(UCLASS_VIDEO_BRIDGE, dev,
"nvidia,ganged-mode", &gangster);
if (gangster) {
/* Ganged mode is set */
@ -1118,8 +1122,8 @@ static int tegra_dsi_bridge_probe(struct udevice *dev)
return 0;
}
static const struct panel_ops tegra_dsi_bridge_ops = {
.enable_backlight = tegra_dsi_encoder_enable,
static const struct video_bridge_ops tegra_dsi_bridge_ops = {
.attach = tegra_dsi_encoder_enable,
.set_backlight = tegra_dsi_bridge_set_panel,
.get_display_timing = tegra_dsi_panel_timings,
};
@ -1133,7 +1137,7 @@ static const struct udevice_id tegra_dsi_bridge_ids[] = {
U_BOOT_DRIVER(tegra_dsi) = {
.name = "tegra_dsi",
.id = UCLASS_PANEL,
.id = UCLASS_VIDEO_BRIDGE,
.of_match = tegra_dsi_bridge_ids,
.ops = &tegra_dsi_bridge_ops,
.bind = dm_scan_fdt_dev,

View file

@ -0,0 +1,623 @@
// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright (C) 2013 NVIDIA Corporation
* Copyright (c) 2023 Svyatoslav Ryhel <clamor95@gmail.com>
*/
#include <clk.h>
#include <dm.h>
#include <edid.h>
#include <i2c.h>
#include <log.h>
#include <misc.h>
#include <panel.h>
#include <reset.h>
#include <linux/delay.h>
#include <linux/err.h>
#include <linux/time.h>
#include <power/regulator.h>
#include <video_bridge.h>
#include <asm/gpio.h>
#include <asm/io.h>
#include <asm/arch/clock.h>
#include "tegra-dc.h"
#include "tegra-hdmi.h"
#define DDCCI_ENTRY_ADDR 0x37
#define DDCCI_SOURSE_ADDR 0x51
#define DDCCI_COMMAND_WRITE 0x03
#define DDCCI_CTRL_BRIGHTNESS 0x10
#define HDMI_EDID_I2C_ADDR 0x50
#define HDMI_REKEY_DEFAULT 56
static const char * const hdmi_supplies[] = {
"hdmi-supply", "pll-supply", "vdd-supply"
};
struct tmds_config {
unsigned int pclk;
u32 pll0;
u32 pll1;
u32 pe_current;
u32 drive_current;
u32 peak_current;
};
struct tegra_hdmi_config {
const struct tmds_config *tmds;
unsigned int num_tmds;
unsigned int max_pclk;
/* to be filled */
};
struct tegra_hdmi_priv {
struct hdmi_ctlr *hdmi_regmap;
struct udevice *supplies[ARRAY_SIZE(hdmi_supplies)];
struct udevice *hdmi_ddc;
struct gpio_desc hpd; /* hotplug detection gpio */
struct display_timing timing;
struct clk *clk;
struct clk *clk_parent;
int panel_bits_per_colourp;
const struct tegra_hdmi_config *config;
};
/* 1280x720p 60hz: EIA/CEA-861-B Format 4 */
static struct display_timing default_720p_timing = {
.pixelclock.typ = 74250000,
.hactive.typ = 1280,
.hfront_porch.typ = 110,
.hback_porch.typ = 220,
.hsync_len.typ = 40,
.vactive.typ = 720,
.vfront_porch.typ = 5,
.vback_porch.typ = 20,
.vsync_len.typ = 5,
.flags = DISPLAY_FLAGS_HSYNC_HIGH |
DISPLAY_FLAGS_VSYNC_HIGH,
};
static const struct tmds_config tegra20_tmds_config[] = {
{ /* slow pixel clock modes */
.pclk = 27000000,
.pll0 = SOR_PLL_BG_V17_S(3) | SOR_PLL_ICHPMP(1) |
SOR_PLL_RESISTORSEL | SOR_PLL_VCOCAP(0) |
SOR_PLL_TX_REG_LOAD(3),
.pll1 = SOR_PLL_TMDS_TERM_ENABLE,
.pe_current = PE_CURRENT0(PE_CURRENT_0_0_mA) |
PE_CURRENT1(PE_CURRENT_0_0_mA) |
PE_CURRENT2(PE_CURRENT_0_0_mA) |
PE_CURRENT3(PE_CURRENT_0_0_mA),
.drive_current = DRIVE_CURRENT_LANE0(DRIVE_CURRENT_7_125_mA) |
DRIVE_CURRENT_LANE1(DRIVE_CURRENT_7_125_mA) |
DRIVE_CURRENT_LANE2(DRIVE_CURRENT_7_125_mA) |
DRIVE_CURRENT_LANE3(DRIVE_CURRENT_7_125_mA),
},
{ /* high pixel clock modes */
.pclk = UINT_MAX,
.pll0 = SOR_PLL_BG_V17_S(3) | SOR_PLL_ICHPMP(1) |
SOR_PLL_RESISTORSEL | SOR_PLL_VCOCAP(1) |
SOR_PLL_TX_REG_LOAD(3),
.pll1 = SOR_PLL_TMDS_TERM_ENABLE | SOR_PLL_PE_EN,
.pe_current = PE_CURRENT0(PE_CURRENT_6_0_mA) |
PE_CURRENT1(PE_CURRENT_6_0_mA) |
PE_CURRENT2(PE_CURRENT_6_0_mA) |
PE_CURRENT3(PE_CURRENT_6_0_mA),
.drive_current = DRIVE_CURRENT_LANE0(DRIVE_CURRENT_7_125_mA) |
DRIVE_CURRENT_LANE1(DRIVE_CURRENT_7_125_mA) |
DRIVE_CURRENT_LANE2(DRIVE_CURRENT_7_125_mA) |
DRIVE_CURRENT_LANE3(DRIVE_CURRENT_7_125_mA),
},
};
static const struct tmds_config tegra30_tmds_config[] = {
{ /* 480p modes */
.pclk = 27000000,
.pll0 = SOR_PLL_BG_V17_S(3) | SOR_PLL_ICHPMP(1) |
SOR_PLL_RESISTORSEL | SOR_PLL_VCOCAP(0) |
SOR_PLL_TX_REG_LOAD(0),
.pll1 = SOR_PLL_TMDS_TERM_ENABLE,
.pe_current = PE_CURRENT0(PE_CURRENT_0_0_mA) |
PE_CURRENT1(PE_CURRENT_0_0_mA) |
PE_CURRENT2(PE_CURRENT_0_0_mA) |
PE_CURRENT3(PE_CURRENT_0_0_mA),
.drive_current = DRIVE_CURRENT_LANE0(DRIVE_CURRENT_5_250_mA) |
DRIVE_CURRENT_LANE1(DRIVE_CURRENT_5_250_mA) |
DRIVE_CURRENT_LANE2(DRIVE_CURRENT_5_250_mA) |
DRIVE_CURRENT_LANE3(DRIVE_CURRENT_5_250_mA),
}, { /* 720p modes */
.pclk = 74250000,
.pll0 = SOR_PLL_BG_V17_S(3) | SOR_PLL_ICHPMP(1) |
SOR_PLL_RESISTORSEL | SOR_PLL_VCOCAP(1) |
SOR_PLL_TX_REG_LOAD(0),
.pll1 = SOR_PLL_TMDS_TERM_ENABLE | SOR_PLL_PE_EN,
.pe_current = PE_CURRENT0(PE_CURRENT_5_0_mA) |
PE_CURRENT1(PE_CURRENT_5_0_mA) |
PE_CURRENT2(PE_CURRENT_5_0_mA) |
PE_CURRENT3(PE_CURRENT_5_0_mA),
.drive_current = DRIVE_CURRENT_LANE0(DRIVE_CURRENT_5_250_mA) |
DRIVE_CURRENT_LANE1(DRIVE_CURRENT_5_250_mA) |
DRIVE_CURRENT_LANE2(DRIVE_CURRENT_5_250_mA) |
DRIVE_CURRENT_LANE3(DRIVE_CURRENT_5_250_mA),
}, { /* 1080p modes */
.pclk = UINT_MAX,
.pll0 = SOR_PLL_BG_V17_S(3) | SOR_PLL_ICHPMP(1) |
SOR_PLL_RESISTORSEL | SOR_PLL_VCOCAP(3) |
SOR_PLL_TX_REG_LOAD(0),
.pll1 = SOR_PLL_TMDS_TERM_ENABLE | SOR_PLL_PE_EN,
.pe_current = PE_CURRENT0(PE_CURRENT_5_0_mA) |
PE_CURRENT1(PE_CURRENT_5_0_mA) |
PE_CURRENT2(PE_CURRENT_5_0_mA) |
PE_CURRENT3(PE_CURRENT_5_0_mA),
.drive_current = DRIVE_CURRENT_LANE0(DRIVE_CURRENT_5_250_mA) |
DRIVE_CURRENT_LANE1(DRIVE_CURRENT_5_250_mA) |
DRIVE_CURRENT_LANE2(DRIVE_CURRENT_5_250_mA) |
DRIVE_CURRENT_LANE3(DRIVE_CURRENT_5_250_mA),
},
};
static void tegra_dc_enable_controller(struct udevice *dev)
{
struct tegra_dc_plat *dc_plat = dev_get_plat(dev);
struct dc_ctlr *dc = dc_plat->dc;
u32 value;
value = readl(&dc->disp.disp_win_opt);
value |= HDMI_ENABLE;
writel(value, &dc->disp.disp_win_opt);
writel(GENERAL_UPDATE, &dc->cmd.state_ctrl);
writel(GENERAL_ACT_REQ, &dc->cmd.state_ctrl);
}
static void tegra_hdmi_setup_tmds(struct tegra_hdmi_priv *priv,
const struct tmds_config *tmds)
{
struct hdmi_ctlr *hdmi = priv->hdmi_regmap;
u32 value;
writel(tmds->pll0, &hdmi->nv_pdisp_sor_pll0);
writel(tmds->pll1, &hdmi->nv_pdisp_sor_pll1);
writel(tmds->pe_current, &hdmi->nv_pdisp_pe_current);
writel(tmds->drive_current, &hdmi->nv_pdisp_sor_lane_drive_current);
value = readl(&hdmi->nv_pdisp_sor_lane_drive_current);
value |= BIT(31);
writel(value, &hdmi->nv_pdisp_sor_lane_drive_current);
}
static int tegra_hdmi_encoder_enable(struct udevice *dev)
{
struct tegra_dc_plat *dc_plat = dev_get_plat(dev);
struct tegra_hdmi_priv *priv = dev_get_priv(dev);
struct dc_ctlr *dc = dc_plat->dc;
struct display_timing *dt = &priv->timing;
struct hdmi_ctlr *hdmi = priv->hdmi_regmap;
unsigned long rate, div82;
unsigned int pulse_start, rekey;
int retries = 1000;
u32 value;
int i;
/* power up sequence */
value = readl(&hdmi->nv_pdisp_sor_pll0);
value &= ~SOR_PLL_PDBG;
writel(value, &hdmi->nv_pdisp_sor_pll0);
udelay(20);
value = readl(&hdmi->nv_pdisp_sor_pll0);
value &= ~SOR_PLL_PWR;
writel(value, &hdmi->nv_pdisp_sor_pll0);
writel(VSYNC_H_POSITION(1), &dc->disp.disp_timing_opt);
writel(DITHER_CONTROL_DISABLE | BASE_COLOR_SIZE_888,
&dc->disp.disp_color_ctrl);
/* video_preamble uses h_pulse2 */
pulse_start = 1 + dt->hsync_len.typ + dt->hback_porch.typ - 10;
writel(H_PULSE2_ENABLE, &dc->disp.disp_signal_opt0);
value = PULSE_MODE_NORMAL | PULSE_POLARITY_HIGH |
PULSE_QUAL_VACTIVE | PULSE_LAST_END_A;
writel(value, &dc->disp.h_pulse[H_PULSE2].h_pulse_ctrl);
value = PULSE_START(pulse_start) | PULSE_END(pulse_start + 8);
writel(value, &dc->disp.h_pulse[H_PULSE2].h_pulse_pos[H_PULSE0_POSITION_A]);
value = VSYNC_WINDOW_END(0x210) | VSYNC_WINDOW_START(0x200) |
VSYNC_WINDOW_ENABLE;
writel(value, &hdmi->nv_pdisp_hdmi_vsync_window);
if (dc_plat->pipe)
value = HDMI_SRC_DISPLAYB;
else
value = HDMI_SRC_DISPLAYA;
if (dt->hactive.typ == 720 && (dt->vactive.typ == 480 ||
dt->vactive.typ == 576))
writel(value | ARM_VIDEO_RANGE_FULL,
&hdmi->nv_pdisp_input_control);
else
writel(value | ARM_VIDEO_RANGE_LIMITED,
&hdmi->nv_pdisp_input_control);
rate = clock_get_periph_rate(priv->clk->id, priv->clk_parent->id);
div82 = rate / USEC_PER_SEC * 4;
value = SOR_REFCLK_DIV_INT(div82 >> 2) | SOR_REFCLK_DIV_FRAC(div82);
writel(value, &hdmi->nv_pdisp_sor_refclk);
rekey = HDMI_REKEY_DEFAULT;
value = HDMI_CTRL_REKEY(rekey);
value |= HDMI_CTRL_MAX_AC_PACKET((dt->hsync_len.typ + dt->hback_porch.typ +
dt->hfront_porch.typ - rekey - 18) / 32);
writel(value, &hdmi->nv_pdisp_hdmi_ctrl);
/* TMDS CONFIG */
for (i = 0; i < priv->config->num_tmds; i++) {
if (dt->pixelclock.typ <= priv->config->tmds[i].pclk) {
tegra_hdmi_setup_tmds(priv, &priv->config->tmds[i]);
break;
}
}
writel(SOR_SEQ_PU_PC(0) | SOR_SEQ_PU_PC_ALT(0) | SOR_SEQ_PD_PC(8) |
SOR_SEQ_PD_PC_ALT(8), &hdmi->nv_pdisp_sor_seq_ctl);
value = SOR_SEQ_INST_WAIT_TIME(1) | SOR_SEQ_INST_WAIT_UNITS_VSYNC |
SOR_SEQ_INST_HALT | SOR_SEQ_INST_PIN_A_LOW |
SOR_SEQ_INST_PIN_B_LOW | SOR_SEQ_INST_DRIVE_PWM_OUT_LO;
writel(value, &hdmi->nv_pdisp_sor_seq_inst0);
writel(value, &hdmi->nv_pdisp_sor_seq_inst8);
value = readl(&hdmi->nv_pdisp_sor_cstm);
value &= ~SOR_CSTM_ROTCLK(~0);
value |= SOR_CSTM_ROTCLK(2);
value |= SOR_CSTM_PLLDIV;
value &= ~SOR_CSTM_LVDS_ENABLE;
value &= ~SOR_CSTM_MODE_MASK;
value |= SOR_CSTM_MODE_TMDS;
writel(value, &hdmi->nv_pdisp_sor_cstm);
/* start SOR */
writel(SOR_PWR_NORMAL_STATE_PU | SOR_PWR_NORMAL_START_NORMAL |
SOR_PWR_SAFE_STATE_PD | SOR_PWR_SETTING_NEW_TRIGGER,
&hdmi->nv_pdisp_sor_pwr);
writel(SOR_PWR_NORMAL_STATE_PU | SOR_PWR_NORMAL_START_NORMAL |
SOR_PWR_SAFE_STATE_PD | SOR_PWR_SETTING_NEW_DONE,
&hdmi->nv_pdisp_sor_pwr);
do {
if (--retries < 0)
return -ETIME;
value = readl(&hdmi->nv_pdisp_sor_pwr);
} while (value & SOR_PWR_SETTING_NEW_PENDING);
value = SOR_STATE_ASY_CRCMODE_COMPLETE |
SOR_STATE_ASY_OWNER_HEAD0 |
SOR_STATE_ASY_SUBOWNER_BOTH |
SOR_STATE_ASY_PROTOCOL_SINGLE_TMDS_A |
SOR_STATE_ASY_DEPOL_POS;
/* setup sync polarities */
if (dt->flags & DISPLAY_FLAGS_HSYNC_HIGH)
value |= SOR_STATE_ASY_HSYNCPOL_POS;
if (dt->flags & DISPLAY_FLAGS_HSYNC_LOW)
value |= SOR_STATE_ASY_HSYNCPOL_NEG;
if (dt->flags & DISPLAY_FLAGS_VSYNC_HIGH)
value |= SOR_STATE_ASY_VSYNCPOL_POS;
if (dt->flags & DISPLAY_FLAGS_VSYNC_LOW)
value |= SOR_STATE_ASY_VSYNCPOL_NEG;
writel(value, &hdmi->nv_pdisp_sor_state2);
value = SOR_STATE_ASY_HEAD_OPMODE_AWAKE | SOR_STATE_ASY_ORMODE_NORMAL;
writel(value, &hdmi->nv_pdisp_sor_state1);
writel(0, &hdmi->nv_pdisp_sor_state0);
writel(SOR_STATE_UPDATE, &hdmi->nv_pdisp_sor_state0);
writel(value | SOR_STATE_ATTACHED,
&hdmi->nv_pdisp_sor_state1);
writel(0, &hdmi->nv_pdisp_sor_state0);
tegra_dc_enable_controller(dev);
return 0;
}
/* DDC/CI backlight control */
static int tegra_hdmi_set_connector(struct udevice *dev, int percent)
{
struct tegra_hdmi_priv *priv = dev_get_priv(dev);
struct udevice *ddc_entry;
struct i2c_msg msg[1];
u8 checksum = DDCCI_ENTRY_ADDR << 1;
int i, ret;
ret = dm_i2c_probe(priv->hdmi_ddc, DDCCI_ENTRY_ADDR, 0, &ddc_entry);
if (ret) {
log_debug("%s: cannot probe DDC/CI entry: error %d\n",
__func__, ret);
return 0;
}
/*
* payload[1] is length: hithest bit OR last 4 bits indicate
* the number of following bytes (excluding checksum)
*/
u8 payload[7] = { DDCCI_SOURSE_ADDR, BIT(7) | (sizeof(payload) - 3),
DDCCI_COMMAND_WRITE, DDCCI_CTRL_BRIGHTNESS,
(u8)(percent & 0xff), (u8)(percent & 0xff), 0 };
/* DDC/CI checksum is a simple XOR of all preceding bytes */
for (i = 0; i < (sizeof(payload) - 1); i++)
checksum ^= payload[i];
payload[6] = checksum;
msg->addr = DDCCI_ENTRY_ADDR;
msg->flags = 0;
msg->len = sizeof(payload);
msg->buf = payload;
dm_i2c_xfer(ddc_entry, msg, 1);
return 0;
}
static int tegra_hdmi_timings(struct udevice *dev,
struct display_timing *timing)
{
struct tegra_hdmi_priv *priv = dev_get_priv(dev);
memcpy(timing, &priv->timing, sizeof(*timing));
return 0;
}
static void tegra_hdmi_init_clocks(struct udevice *dev)
{
struct tegra_hdmi_priv *priv = dev_get_priv(dev);
u32 n = priv->timing.pixelclock.typ * 2 / USEC_PER_SEC;
switch (clock_get_osc_freq()) {
case CLOCK_OSC_FREQ_12_0: /* OSC is 12Mhz */
case CLOCK_OSC_FREQ_48_0: /* OSC is 48Mhz */
clock_set_rate(priv->clk_parent->id, n, 12, 0, 8);
break;
case CLOCK_OSC_FREQ_26_0: /* OSC is 26Mhz */
clock_set_rate(priv->clk_parent->id, n, 26, 0, 8);
break;
case CLOCK_OSC_FREQ_13_0: /* OSC is 13Mhz */
case CLOCK_OSC_FREQ_16_8: /* OSC is 16.8Mhz */
clock_set_rate(priv->clk_parent->id, n, 13, 0, 8);
break;
case CLOCK_OSC_FREQ_19_2:
case CLOCK_OSC_FREQ_38_4:
default:
/*
* These are not supported.
*/
break;
}
clock_start_periph_pll(priv->clk->id, priv->clk_parent->id,
priv->timing.pixelclock.typ);
}
static bool tegra_hdmi_mode_valid(void *hdmi_priv, const struct display_timing *timing)
{
struct tegra_hdmi_priv *priv = hdmi_priv;
if (timing->pixelclock.typ > priv->config->max_pclk)
return false;
return true;
}
static int tegra_hdmi_decode_edid(struct udevice *dev)
{
struct tegra_hdmi_priv *priv = dev_get_priv(dev);
struct udevice *hdmi_edid;
uchar edid_buf[EDID_SIZE] = { 0 };
int i, ret;
/* Poll for 1 sec in case EDID is not ready right after hpd */
for (i = 0; i < 10; i++) {
ret = dm_i2c_probe(priv->hdmi_ddc, HDMI_EDID_I2C_ADDR, 0,
&hdmi_edid);
if (!ret)
break;
mdelay(100);
}
if (ret) {
log_debug("%s: cannot probe EDID: error %d\n",
__func__, ret);
return ret;
}
ret = dm_i2c_read(hdmi_edid, 0, edid_buf, sizeof(edid_buf));
if (ret) {
log_debug("%s: cannot dump EDID buffer: error %d\n",
__func__, ret);
return ret;
}
ret = edid_get_timing_validate(edid_buf, sizeof(edid_buf), &priv->timing,
&priv->panel_bits_per_colourp,
tegra_hdmi_mode_valid, priv);
if (ret) {
log_debug("%s: cannot decode EDID info: error %d\n",
__func__, ret);
return ret;
}
return 0;
}
static int tegra_hdmi_wait_hpd(struct tegra_hdmi_priv *priv)
{
int i;
/* Poll 1 second for HPD signal */
for (i = 0; i < 10; i++) {
if (dm_gpio_get_value(&priv->hpd))
return 0;
mdelay(100);
}
return -ETIMEDOUT;
}
static int tegra_hdmi_probe(struct udevice *dev)
{
struct tegra_hdmi_priv *priv = dev_get_priv(dev);
struct reset_ctl reset_ctl;
int i, ret;
priv->hdmi_regmap = (struct hdmi_ctlr *)dev_read_addr_ptr(dev);
if (!priv->hdmi_regmap) {
log_debug("%s: no display controller address\n", __func__);
return -EINVAL;
}
priv->config = (struct tegra_hdmi_config *)dev_get_driver_data(dev);
priv->clk = devm_clk_get(dev, NULL);
if (IS_ERR(priv->clk)) {
log_debug("%s: Could not get HDMI clock: %ld\n",
__func__, PTR_ERR(priv->clk));
return PTR_ERR(priv->clk);
}
priv->clk_parent = devm_clk_get(dev, "parent");
if (IS_ERR(priv->clk_parent)) {
log_debug("%s: Could not get HDMI clock parent: %ld\n",
__func__, PTR_ERR(priv->clk_parent));
return PTR_ERR(priv->clk_parent);
}
for (i = 0; i < ARRAY_SIZE(hdmi_supplies); i++) {
ret = device_get_supply_regulator(dev, hdmi_supplies[i],
&priv->supplies[i]);
if (ret) {
log_debug("%s: cannot get %s %d\n", __func__,
hdmi_supplies[i], ret);
if (ret != -ENOENT)
return log_ret(ret);
}
ret = regulator_set_enable_if_allowed(priv->supplies[i], true);
if (ret && ret != -ENOSYS) {
log_debug("%s: cannot enable %s: error %d\n",
__func__, hdmi_supplies[i], ret);
return ret;
}
}
ret = reset_get_by_name(dev, "hdmi", &reset_ctl);
if (ret) {
log_debug("%s: reset_get_by_name() failed: %d\n",
__func__, ret);
return ret;
}
ret = uclass_get_device_by_phandle(UCLASS_I2C, dev,
"nvidia,ddc-i2c-bus",
&priv->hdmi_ddc);
if (ret) {
log_debug("%s: cannot get hdmi ddc i2c bus: error %d\n",
__func__, ret);
return ret;
}
ret = gpio_request_by_name(dev, "nvidia,hpd-gpio", 0,
&priv->hpd, GPIOD_IS_IN);
if (ret) {
log_debug("%s: Could not decode hpd-gpios (%d)\n",
__func__, ret);
return ret;
}
/* wait for connector */
ret = tegra_hdmi_wait_hpd(priv);
if (ret) {
/* HPD failed, use default timings */
memcpy(&priv->timing, &default_720p_timing,
sizeof(default_720p_timing));
} else {
ret = tegra_hdmi_decode_edid(dev);
if (ret)
memcpy(&priv->timing, &default_720p_timing,
sizeof(default_720p_timing));
}
reset_assert(&reset_ctl);
tegra_hdmi_init_clocks(dev);
mdelay(2);
reset_deassert(&reset_ctl);
return 0;
}
static const struct tegra_hdmi_config tegra20_hdmi_config = {
.tmds = tegra20_tmds_config,
.num_tmds = ARRAY_SIZE(tegra20_tmds_config),
.max_pclk = 148500000, /* 1080p */
};
static const struct tegra_hdmi_config tegra30_hdmi_config = {
.tmds = tegra30_tmds_config,
.num_tmds = ARRAY_SIZE(tegra30_tmds_config),
.max_pclk = 148500000, /* 1080p */
};
static const struct video_bridge_ops tegra_hdmi_ops = {
.attach = tegra_hdmi_encoder_enable,
.set_backlight = tegra_hdmi_set_connector,
.get_display_timing = tegra_hdmi_timings,
};
static const struct udevice_id tegra_hdmi_ids[] = {
{
.compatible = "nvidia,tegra20-hdmi",
.data = (ulong)&tegra20_hdmi_config
}, {
.compatible = "nvidia,tegra30-hdmi",
.data = (ulong)&tegra30_hdmi_config
}, {
/* sentinel */
}
};
U_BOOT_DRIVER(tegra_hdmi) = {
.name = "tegra_hdmi",
.id = UCLASS_VIDEO_BRIDGE,
.of_match = tegra_hdmi_ids,
.ops = &tegra_hdmi_ops,
.probe = tegra_hdmi_probe,
.plat_auto = sizeof(struct tegra_dc_plat),
.priv_auto = sizeof(struct tegra_hdmi_priv),
};

View file

@ -0,0 +1,648 @@
/* SPDX-License-Identifier: GPL-2.0+ */
/*
* (C) Copyright 2010
* NVIDIA Corporation <www.nvidia.com>
*/
#ifndef _TEGRA_HDMI_H
#define _TEGRA_HDMI_H
#ifndef __ASSEMBLY__
#include <linux/bitops.h>
#endif
/* Register definitions for the Tegra high-definition multimedia interface */
/* High-Definition Multimedia Interface (HDMI_) regs */
struct hdmi_ctlr {
/* Address 0x000 ~ 0x0d2 */
uint ctxsw; /* _CTXSW */ /* 0x00 */
uint nv_pdisp_sor_state0; /* _NV_PDISP_SOR_STATE0 */
uint nv_pdisp_sor_state1; /* _NV_PDISP_SOR_STATE1 */
uint nv_pdisp_sor_state2; /* _NV_PDISP_SOR_STATE2 */
uint nv_pdisp_rg_hdcp_an_msb; /* _NV_PDISP_RG_HDCP_AN_MSB */
uint nv_pdisp_rg_hdcp_an_lsb; /* _NV_PDISP_RG_HDCP_AN_LSB */
uint nv_pdisp_rg_hdcp_cn_msb; /* _NV_PDISP_RG_HDCP_CN_MSB */
uint nv_pdisp_rg_hdcp_cn_lsb; /* _NV_PDISP_RG_HDCP_CN_LSB */
uint nv_pdisp_rg_hdcp_aksv_msb; /* _NV_PDISP_RG_HDCP_AKSV_MSB */
uint nv_pdisp_rg_hdcp_aksv_lsb; /* _NV_PDISP_RG_HDCP_AKSV_LSB */
uint nv_pdisp_rg_hdcp_bksv_msb; /* _NV_PDISP_RG_HDCP_BKSV_MSB */
uint nv_pdisp_rg_hdcp_bksv_lsb; /* _NV_PDISP_RG_HDCP_BKSV_LSB */
uint nv_pdisp_rg_hdcp_cksv_msb; /* _NV_PDISP_RG_HDCP_CKSV_MSB */
uint nv_pdisp_rg_hdcp_cksv_lsb; /* _NV_PDISP_RG_HDCP_CKSV_LSB */
uint nv_pdisp_rg_hdcp_dksv_msb; /* _NV_PDISP_RG_HDCP_DKSV_MSB */
uint nv_pdisp_rg_hdcp_dksv_lsb; /* _NV_PDISP_RG_HDCP_DKSV_LSB */
uint nv_pdisp_rg_hdcp_ctrl; /* _NV_PDISP_RG_HDCP_CTRL */ /* 0x10 */
uint nv_pdisp_rg_hdcp_cmode; /* _NV_PDISP_RG_HDCP_CMODE */
uint nv_pdisp_rg_hdcp_mprime_msb; /* _NV_PDISP_RG_HDCP_MPRIME_MSB */
uint nv_pdisp_rg_hdcp_mprime_lsb; /* _NV_PDISP_RG_HDCP_MPRIME_LSB */
uint nv_pdisp_rg_hdcp_sprime_msb; /* _NV_PDISP_RG_HDCP_SPRIME_MSB */
uint nv_pdisp_rg_hdcp_sprime_lsb2; /* _NV_PDISP_RG_HDCP_SPRIME_LSB2 */
uint nv_pdisp_rg_hdcp_sprime_lsb1; /* _NV_PDISP_RG_HDCP_SPRIME_LSB1 */
uint nv_pdisp_rg_hdcp_ri; /* _NV_PDISP_RG_HDCP_RI */
uint nv_pdisp_rg_hdcp_cs_msb; /* _NV_PDISP_RG_HDCP_CS_MSB */
uint nv_pdisp_rg_hdcp_cs_lsb; /* _NV_PDISP_RG_HDCP_CS_LSB */
uint nv_pdisp_hdmi_audio_emu0; /* _NV_PDISP_HDMI_AUDIO_EMU0 */
uint nv_pdisp_hdmi_audio_emu_rdata0; /* _NV_PDISP_HDMI_AUDIO_EMU_RDATA0 */
uint nv_pdisp_hdmi_audio_emu1; /* _NV_PDISP_HDMI_AUDIO_EMU1 */
uint nv_pdisp_hdmi_audio_emu2; /* _NV_PDISP_HDMI_AUDIO_EMU2 */
uint nv_pdisp_hdmi_audio_infoframe_ctrl; /* _NV_PDISP_HDMI_AUDIO_INFOFRAME_CTRL */
uint nv_pdisp_hdmi_audio_infoframe_status; /* _NV_PDISP_HDMI_AUDIO_INFOFRAME_STATUS */
uint nv_pdisp_hdmi_audio_infoframe_header; /* _NV_PDISP_HDMI_AUDIO_INFOFRAME_HEADER */ /* 0x20 */
uint nv_pdisp_hdmi_audio_infoframe_subpack0_low; /* _NV_PDISP_HDMI_AUDIO_INFOFRAME_SUBPACK0_LOW */
uint nv_pdisp_hdmi_audio_infoframe_subpack0_high; /* _NV_PDISP_HDMI_AUDIO_INFOFRAME_SUBPACK0_HIGH */
uint nv_pdisp_hdmi_avi_infoframe_ctrl; /* _NV_PDISP_HDMI_AVI_INFOFRAME_CTRL */
uint nv_pdisp_hdmi_avi_infoframe_status; /* _NV_PDISP_HDMI_AVI_INFOFRAME_STATUS */
uint nv_pdisp_hdmi_avi_infoframe_header; /* _NV_PDISP_HDMI_AVI_INFOFRAME_HEADER */
uint nv_pdisp_hdmi_avi_infoframe_subpack0_low; /* _NV_PDISP_HDMI_AVI_INFOFRAME_SUBPACK0_LOW */
uint nv_pdisp_hdmi_avi_infoframe_subpack0_high; /* _NV_PDISP_HDMI_AVI_INFOFRAME_SUBPACK0_HIGH */
uint nv_pdisp_hdmi_avi_infoframe_subpack1_low; /* _NV_PDISP_HDMI_AVI_INFOFRAME_SUBPACK1_LOW */
uint nv_pdisp_hdmi_avi_infoframe_subpack1_high; /* _NV_PDISP_HDMI_AVI_INFOFRAME_SUBPACK1_HIGH */
uint nv_pdisp_hdmi_generic_ctrl; /* _NV_PDISP_HDMI_GENERIC_CTRL */
uint nv_pdisp_hdmi_generic_status; /* _NV_PDISP_HDMI_GENERIC_STATUS */
uint nv_pdisp_hdmi_generic_header; /* _NV_PDISP_HDMI_GENERIC_HEADER */
uint nv_pdisp_hdmi_generic_subpack0_low; /* _NV_PDISP_HDMI_GENERIC_SUBPACK0_LOW */
uint nv_pdisp_hdmi_generic_subpack0_high; /* _NV_PDISP_HDMI_GENERIC_SUBPACK0_HIGH */
uint nv_pdisp_hdmi_generic_subpack1_low; /* _NV_PDISP_HDMI_GENERIC_SUBPACK1_LOW */
uint nv_pdisp_hdmi_generic_subpack1_high; /* _NV_PDISP_HDMI_GENERIC_SUBPACK1_HIGH */
uint nv_pdisp_hdmi_generic_subpack2_low; /* _NV_PDISP_HDMI_GENERIC_SUBPACK2_LOW */
uint nv_pdisp_hdmi_generic_subpack2_high; /* _NV_PDISP_HDMI_GENERIC_SUBPACK2_HIGH */
uint nv_pdisp_hdmi_generic_subpack3_low; /* _NV_PDISP_HDMI_GENERIC_SUBPACK3_LOW */
uint nv_pdisp_hdmi_generic_subpack3_high; /* _NV_PDISP_HDMI_GENERIC_SUBPACK3_HIGH */
uint nv_pdisp_hdmi_acr_ctrl; /* _NV_PDISP_HDMI_ACR_CTRL */
uint nv_pdisp_hdmi_acr_0320_subpack_low; /* _NV_PDISP_HDMI_ACR_0320_SUBPACK_LOW */
uint nv_pdisp_hdmi_acr_0320_subpack_high; /* _NV_PDISP_HDMI_ACR_0320_SUBPACK_HIGH */
uint nv_pdisp_hdmi_acr_0441_subpack_low; /* _NV_PDISP_HDMI_ACR_0441_SUBPACK_LOW */
uint nv_pdisp_hdmi_acr_0441_subpack_high; /* _NV_PDISP_HDMI_ACR_0441_SUBPACK_HIGH */
uint nv_pdisp_hdmi_acr_0882_subpack_low; /* _NV_PDISP_HDMI_ACR_0882_SUBPACK_LOW */
uint nv_pdisp_hdmi_acr_0882_subpack_high; /* _NV_PDISP_HDMI_ACR_0882_SUBPACK_HIGH */
uint nv_pdisp_hdmi_acr_1764_subpack_low; /* _NV_PDISP_HDMI_ACR_1764_SUBPACK_LOW */
uint nv_pdisp_hdmi_acr_1764_subpack_high; /* _NV_PDISP_HDMI_ACR_1764_SUBPACK_HIGH */
uint nv_pdisp_hdmi_acr_0480_subpack_low; /* _NV_PDISP_HDMI_ACR_0480_SUBPACK_LOW */
uint nv_pdisp_hdmi_acr_0480_subpack_high; /* _NV_PDISP_HDMI_ACR_0480_SUBPACK_HIGH */
uint nv_pdisp_hdmi_acr_0960_subpack_low; /* _NV_PDISP_HDMI_ACR_0960_SUBPACK_LOW */
uint nv_pdisp_hdmi_acr_0960_subpack_high; /* _NV_PDISP_HDMI_ACR_0960_SUBPACK_HIGH */
uint nv_pdisp_hdmi_acr_1920_subpack_low; /* _NV_PDISP_HDMI_ACR_1920_SUBPACK_LOW */
uint nv_pdisp_hdmi_acr_1920_subpack_high; /* _NV_PDISP_HDMI_ACR_1920_SUBPACK_HIGH */
uint nv_pdisp_hdmi_ctrl; /* _NV_PDISP_HDMI_CTRL */
uint nv_pdisp_hdmi_vsync_keepout; /* _NV_PDISP_HDMI_VSYNC_KEEPOUT */
uint nv_pdisp_hdmi_vsync_window; /* _NV_PDISP_HDMI_VSYNC_WINDOW */
uint nv_pdisp_hdmi_gcp_ctrl; /* _NV_PDISP_HDMI_GCP_CTRL */
uint nv_pdisp_hdmi_gcp_status; /* _NV_PDISP_HDMI_GCP_STATUS */
uint nv_pdisp_hdmi_gcp_subpack; /* _NV_PDISP_HDMI_GCP_SUBPACK */
uint nv_pdisp_hdmi_channel_status1; /* _NV_PDISP_HDMI_CHANNEL_STATUS1 */
uint nv_pdisp_hdmi_channel_status2; /* _NV_PDISP_HDMI_CHANNEL_STATUS2 */
uint nv_pdisp_hdmi_emu0; /* _NV_PDISP_HDMI_EMU0 */
uint nv_pdisp_hdmi_emu1; /* _NV_PDISP_HDMI_EMU1 */
uint nv_pdisp_hdmi_emu1_rdata; /* _NV_PDISP_HDMI_EMU1_RDATA */
uint nv_pdisp_hdmi_spare; /* _NV_PDISP_HDMI_SPARE */
uint nv_pdisp_hdmi_spdif_chn_status1; /* _NV_PDISP_HDMI_SPDIF_CHN_STATUS1 */
uint nv_pdisp_hdmi_spdif_chn_status2; /* _NV_PDISP_HDMI_SPDIF_CHN_STATUS2 */
uint nv_pdisp_hdcprif_rom_ctrl; /* _NV_PDISP_HDCPRIF_ROM_CTRL */
uint unused;
uint nv_pdisp_sor_cap; /* _NV_PDISP_SOR_CAP */
uint nv_pdisp_sor_pwr; /* _NV_PDISP_SOR_PWR */
uint nv_pdisp_sor_test; /* _NV_PDISP_SOR_TEST */
uint nv_pdisp_sor_pll0; /* _NV_PDISP_SOR_PLL0 */
uint nv_pdisp_sor_pll1; /* _NV_PDISP_SOR_PLL1 */
uint nv_pdisp_sor_pll2; /* _NV_PDISP_SOR_PLL2 */
uint nv_pdisp_sor_cstm; /* _NV_PDISP_SOR_CSTM */
uint nv_pdisp_sor_lvds; /* _NV_PDISP_SOR_LVDS */
uint nv_pdisp_sor_crca; /* _NV_PDISP_SOR_CRCA */
uint nv_pdisp_sor_crcb; /* _NV_PDISP_SOR_CRCB */
uint nv_pdisp_sor_blank; /* _NV_PDISP_SOR_BLANK */
uint nv_pdisp_sor_seq_ctl; /* _NV_PDISP_SOR_SEQ_CTL */
uint nv_pdisp_sor_seq_inst0; /* _NV_PDISP_SOR_SEQ_INST0 */
uint nv_pdisp_sor_seq_inst1; /* _NV_PDISP_SOR_SEQ_INST1 */
uint nv_pdisp_sor_seq_inst2; /* _NV_PDISP_SOR_SEQ_INST2 */
uint nv_pdisp_sor_seq_inst3; /* _NV_PDISP_SOR_SEQ_INST3 */
uint nv_pdisp_sor_seq_inst4; /* _NV_PDISP_SOR_SEQ_INST4 */
uint nv_pdisp_sor_seq_inst5; /* _NV_PDISP_SOR_SEQ_INST5 */
uint nv_pdisp_sor_seq_inst6; /* _NV_PDISP_SOR_SEQ_INST6 */
uint nv_pdisp_sor_seq_inst7; /* _NV_PDISP_SOR_SEQ_INST7 */
uint nv_pdisp_sor_seq_inst8; /* _NV_PDISP_SOR_SEQ_INST8 */
uint nv_pdisp_sor_seq_inst9; /* _NV_PDISP_SOR_SEQ_INST9 */
uint nv_pdisp_sor_seq_insta; /* _NV_PDISP_SOR_SEQ_INSTA */
uint nv_pdisp_sor_seq_instb; /* _NV_PDISP_SOR_SEQ_INSTB */
uint nv_pdisp_sor_seq_instc; /* _NV_PDISP_SOR_SEQ_INSTC */
uint nv_pdisp_sor_seq_instd; /* _NV_PDISP_SOR_SEQ_INSTD */
uint nv_pdisp_sor_seq_inste; /* _NV_PDISP_SOR_SEQ_INSTE */
uint nv_pdisp_sor_seq_instf; /* _NV_PDISP_SOR_SEQ_INSTF */
uint unused1[2];
uint nv_pdisp_sor_vcrca0; /* _NV_PDISP_SOR_VCRCA0 */
uint nv_pdisp_sor_vcrca1; /* _NV_PDISP_SOR_VCRCA1 */
uint nv_pdisp_sor_ccrca0; /* _NV_PDISP_SOR_CCRCA0 */
uint nv_pdisp_sor_ccrca1; /* _NV_PDISP_SOR_CCRCA1 */
uint nv_pdisp_sor_edataa0; /* _NV_PDISP_SOR_EDATAA0 */
uint nv_pdisp_sor_edataa1; /* _NV_PDISP_SOR_EDATAA1 */
uint nv_pdisp_sor_counta0; /* _NV_PDISP_SOR_COUNTA0 */
uint nv_pdisp_sor_counta1; /* _NV_PDISP_SOR_COUNTA1 */
uint nv_pdisp_sor_debuga0; /* _NV_PDISP_SOR_DEBUGA0 */
uint nv_pdisp_sor_debuga1; /* _NV_PDISP_SOR_DEBUGA1 */
uint nv_pdisp_sor_trig; /* _NV_PDISP_SOR_TRIG */
uint nv_pdisp_sor_mscheck; /* _NV_PDISP_SOR_MSCHECK */
uint nv_pdisp_sor_lane_drive_current; /* _NV_PDISP_SOR_LANE_DRIVE_CURRENT */
uint nv_pdisp_audio_debug0; /* _NV_PDISP_AUDIO_DEBUG0 0x7f */
uint nv_pdisp_audio_debug1; /* _NV_PDISP_AUDIO_DEBUG1 0x80 */
uint nv_pdisp_audio_debug2; /* _NV_PDISP_AUDIO_DEBUG2 0x81 */
uint nv_pdisp_audio_fs1; /* _NV_PDISP_AUDIO_FS1 0x82 */
uint nv_pdisp_audio_fs2; /* _NV_PDISP_AUDIO_FS2 */
uint nv_pdisp_audio_fs3; /* _NV_PDISP_AUDIO_FS3 */
uint nv_pdisp_audio_fs4; /* _NV_PDISP_AUDIO_FS4 */
uint nv_pdisp_audio_fs5; /* _NV_PDISP_AUDIO_FS5 */
uint nv_pdisp_audio_fs6; /* _NV_PDISP_AUDIO_FS6 */
uint nv_pdisp_audio_fs7; /* _NV_PDISP_AUDIO_FS7 0x88 */
uint nv_pdisp_audio_pulse_width; /* _NV_PDISP_AUDIO_PULSE_WIDTH */
uint nv_pdisp_audio_threshold; /* _NV_PDISP_AUDIO_THRESHOLD */
uint nv_pdisp_audio_cntrl0; /* _NV_PDISP_AUDIO_CNTRL0 */
uint nv_pdisp_audio_n; /* _NV_PDISP_AUDIO_N */
uint nv_pdisp_audio_nval[7]; /* _NV_PDISP_AUDIO_NVAL */
uint nv_pdisp_hdcprif_rom_timing; /* _NV_PDISP_HDCPRIF_ROM_TIMING */
uint nv_pdisp_sor_refclk; /* _NV_PDISP_SOR_REFCLK */
uint nv_pdisp_crc_control; /* _NV_PDISP_CRC_CONTROL */
uint nv_pdisp_input_control; /* _NV_PDISP_INPUT_CONTROL */
uint nv_pdisp_scratch; /* _NV_PDISP_SCRATCH */
uint nv_pdisp_pe_current; /* _NV_PDISP_PE_CURRENT */
uint nv_pdisp_key_ctrl; /* _NV_PDISP_KEY_CTRL */
uint nv_pdisp_key_debug0; /* _NV_PDISP_KEY_DEBUG0 */
uint nv_pdisp_key_debug1; /* _NV_PDISP_KEY_DEBUG1 */
uint nv_pdisp_key_debug2; /* _NV_PDISP_KEY_DEBUG2 */
uint nv_pdisp_key_hdcp_key_0; /* _NV_PDISP_KEY_HDCP_KEY_0 */
uint nv_pdisp_key_hdcp_key_1; /* _NV_PDISP_KEY_HDCP_KEY_1 */
uint nv_pdisp_key_hdcp_key_2; /* _NV_PDISP_KEY_HDCP_KEY_2 */
uint nv_pdisp_key_hdcp_key_3; /* _NV_PDISP_KEY_HDCP_KEY_3 */
uint nv_pdisp_key_hdcp_key_trig; /* _NV_PDISP_KEY_HDCP_KEY_3 */
uint nv_pdisp_key_skey_index; /* _NV_PDISP_KEY_HDCP_KEY_3 */ /* 0xa3 */
uint unused2[8];
uint nv_pdisp_sor_audio_cntrl0; /* _NV_PDISP_SOR_AUDIO_CNTRL0 */ /* 0xac */
uint nv_pdisp_sor_audio_debug; /* _NV_PDISP_SOR_AUDIO_DEBUG */
uint nv_pdisp_sor_audio_spare0; /* _NV_PDISP_SOR_AUDIO_SPARE0 */
uint nv_pdisp_sor_audio_nval[7]; /* _NV_PDISP_SOR_AUDIO_NVAL 0xaf ~ 0xb5 */
uint nv_pdisp_sor_audio_hda_scratch[4]; /* _NV_PDISP_SOR_AUDIO_HDA_SCRATCH 0xb6 ~ 0xb9 */
uint nv_pdisp_sor_audio_hda_codec_scratch[2]; /* _NV_PDISP_SOR_AUDIO_HDA_CODEC_SCRATCH 0xba ~ 0xbb */
uint nv_pdisp_sor_audio_hda_eld_bufwr; /* _NV_PDISP_SOR_AUDIO_HDA_ELD_BUFWR */
uint nv_pdisp_sor_audio_hda_presense; /* _NV_PDISP_SOR_AUDIO_HDA_PRESENSE */
uint nv_pdisp_sor_audio_hda_cp; /* _NV_PDISP_SOR_AUDIO_HDA_CP */
uint nv_pdisp_sor_audio_aval[8]; /* _NV_PDISP_SOR_AUDIO_AVAL */
uint nv_pdisp_sor_audio_gen_ctrl; /* _NV_PDISP_SOR_AUDIO_GEN_CTRL */
uint unused3[4];
uint nv_pdisp_int_status; /* _NV_PDISP_INT_STATUS */
uint nv_pdisp_int_mask; /* _NV_PDISP_INT_MASK */
uint nv_pdisp_int_enable; /* _NV_PDISP_INT_ENABLE */
uint unused4[2];
uint nv_pdisp_sor_io_peak_current; /* _NV_PDISP_SOR_IO_PEAK_CURRENT */
uint nv_pdisp_sor_pad_ctls0; /* _NV_PDISP_SOR_PAD_CTLS0 */
};
/* HDMI_NV_PDISP_SOR_STATE0 0x01 */
#define SOR_STATE_UPDATE BIT(0)
/* HDMI_NV_PDISP_SOR_STATE1 0x02 */
#define SOR_STATE_ASY_HEAD_OPMODE_AWAKE BIT(1)
#define SOR_STATE_ASY_ORMODE_NORMAL BIT(2)
#define SOR_STATE_ATTACHED BIT(3)
/* HDMI_NV_PDISP_SOR_STATE2 0x03 */
#define SOR_STATE_ASY_OWNER_NONE (0 << 0)
#define SOR_STATE_ASY_OWNER_HEAD0 (1 << 0)
#define SOR_STATE_ASY_SUBOWNER_NONE (0 << 4)
#define SOR_STATE_ASY_SUBOWNER_SUBHEAD0 (1 << 4)
#define SOR_STATE_ASY_SUBOWNER_SUBHEAD1 (2 << 4)
#define SOR_STATE_ASY_SUBOWNER_BOTH (3 << 4)
#define SOR_STATE_ASY_CRCMODE_ACTIVE (0 << 6)
#define SOR_STATE_ASY_CRCMODE_COMPLETE (1 << 6)
#define SOR_STATE_ASY_CRCMODE_NON_ACTIVE (2 << 6)
#define SOR_STATE_ASY_PROTOCOL_SINGLE_TMDS_A (1 << 8)
#define SOR_STATE_ASY_PROTOCOL_CUSTOM (15 << 8)
#define SOR_STATE_ASY_HSYNCPOL_POS (0 << 12)
#define SOR_STATE_ASY_HSYNCPOL_NEG (1 << 12)
#define SOR_STATE_ASY_VSYNCPOL_POS (0 << 13)
#define SOR_STATE_ASY_VSYNCPOL_NEG (1 << 13)
#define SOR_STATE_ASY_DEPOL_POS (0 << 14)
#define SOR_STATE_ASY_DEPOL_NEG (1 << 14)
#define INFOFRAME_CTRL_ENABLE BIT(0)
#define INFOFRAME_HEADER_TYPE(x) (((x) & 0xff) << 0)
#define INFOFRAME_HEADER_VERSION(x) (((x) & 0xff) << 8)
#define INFOFRAME_HEADER_LEN(x) (((x) & 0x0f) << 16)
/* HDMI_NV_PDISP_HDMI_GENERIC_CTRL 0x2a */
#define GENERIC_CTRL_ENABLE BIT(0)
#define GENERIC_CTRL_OTHER BIT(4)
#define GENERIC_CTRL_SINGLE BIT(8)
#define GENERIC_CTRL_HBLANK BIT(12)
#define GENERIC_CTRL_AUDIO BIT(16)
/* HDMI_NV_PDISP_HDMI_ACR_* */
#define ACR_SUBPACK_CTS(x) (((x) & 0xffffff) << 8)
#define ACR_SUBPACK_N(x) (((x) & 0xffffff) << 0)
#define ACR_ENABLE BIT(31)
/* HDMI_NV_PDISP_HDMI_CTRL 0x44 */
#define HDMI_CTRL_REKEY(x) (((x) & 0x7f) << 0)
#define HDMI_CTRL_MAX_AC_PACKET(x) (((x) & 0x1f) << 16)
#define HDMI_CTRL_ENABLE BIT(30)
/* HDMI_NV_PDISP_HDMI_VSYNC_* */
#define VSYNC_WINDOW_END(x) (((x) & 0x3ff) << 0)
#define VSYNC_WINDOW_START(x) (((x) & 0x3ff) << 16)
#define VSYNC_WINDOW_ENABLE BIT(31)
/* HDMI_NV_PDISP_HDMI_SPARE 0x4f */
#define SPARE_HW_CTS BIT(0)
#define SPARE_FORCE_SW_CTS BIT(1)
#define SPARE_CTS_RESET_VAL(x) (((x) & 0x7) << 16)
/* HDMI_NV_PDISP_SOR_PWR 0x55 */
#define SOR_PWR_NORMAL_STATE_PD (0 << 0)
#define SOR_PWR_NORMAL_STATE_PU (1 << 0)
#define SOR_PWR_NORMAL_START_NORMAL (0 << 1)
#define SOR_PWR_NORMAL_START_ALT (1 << 1)
#define SOR_PWR_SAFE_STATE_PD (0 << 16)
#define SOR_PWR_SAFE_STATE_PU (1 << 16)
#define SOR_PWR_SETTING_NEW_DONE (0 << 31)
#define SOR_PWR_SETTING_NEW_PENDING (1 << 31)
#define SOR_PWR_SETTING_NEW_TRIGGER (1 << 31)
/* HDMI_NV_PDISP_SOR_PLL0 0x57 */
#define SOR_PLL_PWR BIT(0)
#define SOR_PLL_PDBG BIT(1)
#define SOR_PLL_VCAPD BIT(2)
#define SOR_PLL_PDPORT BIT(3)
#define SOR_PLL_RESISTORSEL BIT(4)
#define SOR_PLL_PULLDOWN BIT(5)
#define SOR_PLL_VCOCAP(x) (((x) & 0xf) << 8)
#define SOR_PLL_BG_V17_S(x) (((x) & 0xf) << 12)
#define SOR_PLL_FILTER(x) (((x) & 0xf) << 16)
#define SOR_PLL_ICHPMP(x) (((x) & 0xf) << 24)
#define SOR_PLL_TX_REG_LOAD(x) (((x) & 0xf) << 28)
/* HDMI_NV_PDISP_SOR_PLL1 0x58 */
#define SOR_PLL_TMDS_TERM_ENABLE BIT(8)
#define SOR_PLL_TMDS_TERMADJ(x) (((x) & 0xf) << 9)
#define SOR_PLL_LOADADJ(x) (((x) & 0xf) << 20)
#define SOR_PLL_PE_EN BIT(28)
#define SOR_PLL_HALF_FULL_PE BIT(29)
#define SOR_PLL_S_D_PIN_PE BIT(30)
/* HDMI_NV_PDISP_SOR_CSTM 0x5a */
#define SOR_CSTM_ROTCLK(x) (((x) & 0xf) << 24)
#define SOR_CSTM_PLLDIV BIT(21)
#define SOR_CSTM_LVDS_ENABLE BIT(16)
#define SOR_CSTM_MODE_LVDS (0 << 12)
#define SOR_CSTM_MODE_TMDS (1 << 12)
#define SOR_CSTM_MODE_MASK (3 << 12)
/* HDMI_NV_PDISP_SOR_SEQ_CTL 0x5f */
#define SOR_SEQ_PU_PC(x) (((x) & 0xf) << 0)
#define SOR_SEQ_PU_PC_ALT(x) (((x) & 0xf) << 4)
#define SOR_SEQ_PD_PC(x) (((x) & 0xf) << 8)
#define SOR_SEQ_PD_PC_ALT(x) (((x) & 0xf) << 12)
#define SOR_SEQ_PC(x) (((x) & 0xf) << 16)
#define SOR_SEQ_STATUS BIT(28)
#define SOR_SEQ_SWITCH BIT(30)
/* HDMI_NV_PDISP_SOR_SEQ_INST(x) (0x60 + (x)) */
#define SOR_SEQ_INST_WAIT_TIME(x) (((x) & 0x3ff) << 0)
#define SOR_SEQ_INST_WAIT_UNITS_VSYNC (2 << 12)
#define SOR_SEQ_INST_HALT (1 << 15)
#define SOR_SEQ_INST_PIN_A_LOW (0 << 21)
#define SOR_SEQ_INST_PIN_A_HIGH (1 << 21)
#define SOR_SEQ_INST_PIN_B_LOW (0 << 22)
#define SOR_SEQ_INST_PIN_B_HIGH (1 << 22)
#define SOR_SEQ_INST_DRIVE_PWM_OUT_LO (1 << 23)
/* HDMI_NV_PDISP_SOR_LANE_DRIVE_CURRENT 0x7e */
#define DRIVE_CURRENT_LANE0(x) (((x) & 0x3f) << 0)
#define DRIVE_CURRENT_LANE1(x) (((x) & 0x3f) << 8)
#define DRIVE_CURRENT_LANE2(x) (((x) & 0x3f) << 16)
#define DRIVE_CURRENT_LANE3(x) (((x) & 0x3f) << 24)
#define DRIVE_CURRENT_LANE0_T114(x) (((x) & 0x7f) << 0)
#define DRIVE_CURRENT_LANE1_T114(x) (((x) & 0x7f) << 8)
#define DRIVE_CURRENT_LANE2_T114(x) (((x) & 0x7f) << 16)
#define DRIVE_CURRENT_LANE3_T114(x) (((x) & 0x7f) << 24)
/* Drive current list */
enum {
DRIVE_CURRENT_1_500_mA,
DRIVE_CURRENT_1_875_mA,
DRIVE_CURRENT_2_250_mA,
DRIVE_CURRENT_2_625_mA,
DRIVE_CURRENT_3_000_mA,
DRIVE_CURRENT_3_375_mA,
DRIVE_CURRENT_3_750_mA,
DRIVE_CURRENT_4_125_mA,
DRIVE_CURRENT_4_500_mA,
DRIVE_CURRENT_4_875_mA,
DRIVE_CURRENT_5_250_mA,
DRIVE_CURRENT_5_625_mA,
DRIVE_CURRENT_6_000_mA,
DRIVE_CURRENT_6_375_mA,
DRIVE_CURRENT_6_750_mA,
DRIVE_CURRENT_7_125_mA,
DRIVE_CURRENT_7_500_mA,
DRIVE_CURRENT_7_875_mA,
DRIVE_CURRENT_8_250_mA,
DRIVE_CURRENT_8_625_mA,
DRIVE_CURRENT_9_000_mA,
DRIVE_CURRENT_9_375_mA,
DRIVE_CURRENT_9_750_mA,
DRIVE_CURRENT_10_125_mA,
DRIVE_CURRENT_10_500_mA,
DRIVE_CURRENT_10_875_mA,
DRIVE_CURRENT_11_250_mA,
DRIVE_CURRENT_11_625_mA,
DRIVE_CURRENT_12_000_mA,
DRIVE_CURRENT_12_375_mA,
DRIVE_CURRENT_12_750_mA,
DRIVE_CURRENT_13_125_mA,
DRIVE_CURRENT_13_500_mA,
DRIVE_CURRENT_13_875_mA,
DRIVE_CURRENT_14_250_mA,
DRIVE_CURRENT_14_625_mA,
DRIVE_CURRENT_15_000_mA,
DRIVE_CURRENT_15_375_mA,
DRIVE_CURRENT_15_750_mA,
DRIVE_CURRENT_16_125_mA,
DRIVE_CURRENT_16_500_mA,
DRIVE_CURRENT_16_875_mA,
DRIVE_CURRENT_17_250_mA,
DRIVE_CURRENT_17_625_mA,
DRIVE_CURRENT_18_000_mA,
DRIVE_CURRENT_18_375_mA,
DRIVE_CURRENT_18_750_mA,
DRIVE_CURRENT_19_125_mA,
DRIVE_CURRENT_19_500_mA,
DRIVE_CURRENT_19_875_mA,
DRIVE_CURRENT_20_250_mA,
DRIVE_CURRENT_20_625_mA,
DRIVE_CURRENT_21_000_mA,
DRIVE_CURRENT_21_375_mA,
DRIVE_CURRENT_21_750_mA,
DRIVE_CURRENT_22_125_mA,
DRIVE_CURRENT_22_500_mA,
DRIVE_CURRENT_22_875_mA,
DRIVE_CURRENT_23_250_mA,
DRIVE_CURRENT_23_625_mA,
DRIVE_CURRENT_24_000_mA,
DRIVE_CURRENT_24_375_mA,
DRIVE_CURRENT_24_750_mA,
};
/* Drive current list for T114 */
enum {
DRIVE_CURRENT_0_000_mA_T114,
DRIVE_CURRENT_0_400_mA_T114,
DRIVE_CURRENT_0_800_mA_T114,
DRIVE_CURRENT_1_200_mA_T114,
DRIVE_CURRENT_1_600_mA_T114,
DRIVE_CURRENT_2_000_mA_T114,
DRIVE_CURRENT_2_400_mA_T114,
DRIVE_CURRENT_2_800_mA_T114,
DRIVE_CURRENT_3_200_mA_T114,
DRIVE_CURRENT_3_600_mA_T114,
DRIVE_CURRENT_4_000_mA_T114,
DRIVE_CURRENT_4_400_mA_T114,
DRIVE_CURRENT_4_800_mA_T114,
DRIVE_CURRENT_5_200_mA_T114,
DRIVE_CURRENT_5_600_mA_T114,
DRIVE_CURRENT_6_000_mA_T114,
DRIVE_CURRENT_6_400_mA_T114,
DRIVE_CURRENT_6_800_mA_T114,
DRIVE_CURRENT_7_200_mA_T114,
DRIVE_CURRENT_7_600_mA_T114,
DRIVE_CURRENT_8_000_mA_T114,
DRIVE_CURRENT_8_400_mA_T114,
DRIVE_CURRENT_8_800_mA_T114,
DRIVE_CURRENT_9_200_mA_T114,
DRIVE_CURRENT_9_600_mA_T114,
DRIVE_CURRENT_10_000_mA_T114,
DRIVE_CURRENT_10_400_mA_T114,
DRIVE_CURRENT_10_800_mA_T114,
DRIVE_CURRENT_11_200_mA_T114,
DRIVE_CURRENT_11_600_mA_T114,
DRIVE_CURRENT_12_000_mA_T114,
DRIVE_CURRENT_12_400_mA_T114,
DRIVE_CURRENT_12_800_mA_T114,
DRIVE_CURRENT_13_200_mA_T114,
DRIVE_CURRENT_13_600_mA_T114,
DRIVE_CURRENT_14_000_mA_T114,
DRIVE_CURRENT_14_400_mA_T114,
DRIVE_CURRENT_14_800_mA_T114,
DRIVE_CURRENT_15_200_mA_T114,
DRIVE_CURRENT_15_600_mA_T114,
DRIVE_CURRENT_16_000_mA_T114,
DRIVE_CURRENT_16_400_mA_T114,
DRIVE_CURRENT_16_800_mA_T114,
DRIVE_CURRENT_17_200_mA_T114,
DRIVE_CURRENT_17_600_mA_T114,
DRIVE_CURRENT_18_000_mA_T114,
DRIVE_CURRENT_18_400_mA_T114,
DRIVE_CURRENT_18_800_mA_T114,
DRIVE_CURRENT_19_200_mA_T114,
DRIVE_CURRENT_19_600_mA_T114,
DRIVE_CURRENT_20_000_mA_T114,
DRIVE_CURRENT_20_400_mA_T114,
DRIVE_CURRENT_20_800_mA_T114,
DRIVE_CURRENT_21_200_mA_T114,
DRIVE_CURRENT_21_600_mA_T114,
DRIVE_CURRENT_22_000_mA_T114,
DRIVE_CURRENT_22_400_mA_T114,
DRIVE_CURRENT_22_800_mA_T114,
DRIVE_CURRENT_23_200_mA_T114,
DRIVE_CURRENT_23_600_mA_T114,
DRIVE_CURRENT_24_000_mA_T114,
DRIVE_CURRENT_24_400_mA_T114,
DRIVE_CURRENT_24_800_mA_T114,
DRIVE_CURRENT_25_200_mA_T114,
DRIVE_CURRENT_25_400_mA_T114,
DRIVE_CURRENT_25_800_mA_T114,
DRIVE_CURRENT_26_200_mA_T114,
DRIVE_CURRENT_26_600_mA_T114,
DRIVE_CURRENT_27_000_mA_T114,
DRIVE_CURRENT_27_400_mA_T114,
DRIVE_CURRENT_27_800_mA_T114,
DRIVE_CURRENT_28_200_mA_T114,
};
/* HDMI_NV_PDISP_AUDIO_FS */
#define AUDIO_FS_LOW(x) (((x) & 0xfff) << 0)
#define AUDIO_FS_HIGH(x) (((x) & 0xfff) << 16)
/* HDMI_NV_PDISP_AUDIO_CNTRL0 0x8b */
#define AUDIO_CNTRL0_ERROR_TOLERANCE(x) (((x) & 0xff) << 0)
#define AUDIO_CNTRL0_SOURCE_SELECT_AUTO (0 << 20)
#define AUDIO_CNTRL0_SOURCE_SELECT_SPDIF (1 << 20)
#define AUDIO_CNTRL0_SOURCE_SELECT_HDAL (2 << 20)
#define AUDIO_CNTRL0_FRAMES_PER_BLOCK(x) (((x) & 0xff) << 24)
/* HDMI_NV_PDISP_AUDIO_N 0x8c */
#define AUDIO_N_VALUE(x) (((x) & 0xfffff) << 0)
#define AUDIO_N_RESETF (1 << 20)
#define AUDIO_N_GENERATE_NORMAL (0 << 24)
#define AUDIO_N_GENERATE_ALTERNATE (1 << 24)
/* HDMI_NV_PDISP_SOR_REFCLK 0x95 */
#define SOR_REFCLK_DIV_INT(x) (((x) & 0xff) << 8)
#define SOR_REFCLK_DIV_FRAC(x) (((x) & 0x03) << 6)
/* HDMI_NV_PDISP_INPUT_CONTROL 0x97 */
#define HDMI_SRC_DISPLAYA (0 << 0)
#define HDMI_SRC_DISPLAYB (1 << 0)
#define ARM_VIDEO_RANGE_FULL (0 << 1)
#define ARM_VIDEO_RANGE_LIMITED (1 << 1)
/* HDMI_NV_PDISP_PE_CURRENT 0x99 */
#define PE_CURRENT0(x) (((x) & 0xf) << 0)
#define PE_CURRENT1(x) (((x) & 0xf) << 8)
#define PE_CURRENT2(x) (((x) & 0xf) << 16)
#define PE_CURRENT3(x) (((x) & 0xf) << 24)
enum {
PE_CURRENT_0_0_mA,
PE_CURRENT_0_5_mA,
PE_CURRENT_1_0_mA,
PE_CURRENT_1_5_mA,
PE_CURRENT_2_0_mA,
PE_CURRENT_2_5_mA,
PE_CURRENT_3_0_mA,
PE_CURRENT_3_5_mA,
PE_CURRENT_4_0_mA,
PE_CURRENT_4_5_mA,
PE_CURRENT_5_0_mA,
PE_CURRENT_5_5_mA,
PE_CURRENT_6_0_mA,
PE_CURRENT_6_5_mA,
PE_CURRENT_7_0_mA,
PE_CURRENT_7_5_mA,
};
enum {
PE_CURRENT_0_mA_T114,
PE_CURRENT_1_mA_T114,
PE_CURRENT_2_mA_T114,
PE_CURRENT_3_mA_T114,
PE_CURRENT_4_mA_T114,
PE_CURRENT_5_mA_T114,
PE_CURRENT_6_mA_T114,
PE_CURRENT_7_mA_T114,
PE_CURRENT_8_mA_T114,
PE_CURRENT_9_mA_T114,
PE_CURRENT_10_mA_T114,
PE_CURRENT_11_mA_T114,
PE_CURRENT_12_mA_T114,
PE_CURRENT_13_mA_T114,
PE_CURRENT_14_mA_T114,
PE_CURRENT_15_mA_T114,
};
/* HDMI_NV_PDISP_SOR_AUDIO_CNTRL0 0xac */
#define SOR_AUDIO_CNTRL0_SOURCE_SELECT_AUTO (0 << 20)
#define SOR_AUDIO_CNTRL0_SOURCE_SELECT_SPDIF (1 << 20)
#define SOR_AUDIO_CNTRL0_SOURCE_SELECT_HDAL (2 << 20)
#define SOR_AUDIO_CNTRL0_INJECT_NULLSMPL (1 << 29)
/* HDMI_NV_PDISP_SOR_AUDIO_SPARE0 0xae */
#define SOR_AUDIO_SPARE0_HBR_ENABLE BIT(27)
/* HDMI_NV_PDISP_SOR_AUDIO_HDA_CODEC_SCRATCH0 0xba */
#define SOR_AUDIO_HDA_CODEC_SCRATCH0_VALID BIT(30)
#define SOR_AUDIO_HDA_CODEC_SCRATCH0_FMT_MASK 0xffff
/* HDMI_NV_PDISP_SOR_AUDIO_HDA_PRESENSE 0xbd */
#define SOR_AUDIO_HDA_PRESENSE_VALID BIT(1)
#define SOR_AUDIO_HDA_PRESENSE_PRESENT BIT(0)
/* HDMI_NV_PDISP_INT_STATUS 0xcc */
#define INT_SCRATCH BIT(3)
#define INT_CP_REQUEST BIT(2)
#define INT_CODEC_SCRATCH1 BIT(1)
#define INT_CODEC_SCRATCH0 BIT(0)
/* HDMI_NV_PDISP_SOR_IO_PEAK_CURRENT 0xd1 */
#define PEAK_CURRENT_LANE0(x) (((x) & 0x7f) << 0)
#define PEAK_CURRENT_LANE1(x) (((x) & 0x7f) << 8)
#define PEAK_CURRENT_LANE2(x) (((x) & 0x7f) << 16)
#define PEAK_CURRENT_LANE3(x) (((x) & 0x7f) << 24)
enum {
PEAK_CURRENT_0_000_mA,
PEAK_CURRENT_0_200_mA,
PEAK_CURRENT_0_400_mA,
PEAK_CURRENT_0_600_mA,
PEAK_CURRENT_0_800_mA,
PEAK_CURRENT_1_000_mA,
PEAK_CURRENT_1_200_mA,
PEAK_CURRENT_1_400_mA,
PEAK_CURRENT_1_600_mA,
PEAK_CURRENT_1_800_mA,
PEAK_CURRENT_2_000_mA,
PEAK_CURRENT_2_200_mA,
PEAK_CURRENT_2_400_mA,
PEAK_CURRENT_2_600_mA,
PEAK_CURRENT_2_800_mA,
PEAK_CURRENT_3_000_mA,
PEAK_CURRENT_3_200_mA,
PEAK_CURRENT_3_400_mA,
PEAK_CURRENT_3_600_mA,
PEAK_CURRENT_3_800_mA,
PEAK_CURRENT_4_000_mA,
PEAK_CURRENT_4_200_mA,
PEAK_CURRENT_4_400_mA,
PEAK_CURRENT_4_600_mA,
PEAK_CURRENT_4_800_mA,
PEAK_CURRENT_5_000_mA,
PEAK_CURRENT_5_200_mA,
PEAK_CURRENT_5_400_mA,
PEAK_CURRENT_5_600_mA,
PEAK_CURRENT_5_800_mA,
PEAK_CURRENT_6_000_mA,
PEAK_CURRENT_6_200_mA,
PEAK_CURRENT_6_400_mA,
PEAK_CURRENT_6_600_mA,
PEAK_CURRENT_6_800_mA,
PEAK_CURRENT_7_000_mA,
PEAK_CURRENT_7_200_mA,
PEAK_CURRENT_7_400_mA,
PEAK_CURRENT_7_600_mA,
PEAK_CURRENT_7_800_mA,
PEAK_CURRENT_8_000_mA,
PEAK_CURRENT_8_200_mA,
PEAK_CURRENT_8_400_mA,
PEAK_CURRENT_8_600_mA,
PEAK_CURRENT_8_800_mA,
PEAK_CURRENT_9_000_mA,
PEAK_CURRENT_9_200_mA,
PEAK_CURRENT_9_400_mA,
};
#endif /* _TEGRA_HDMI_H */

View file

@ -0,0 +1,86 @@
// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright (c) 2025 Svyatoslav Ryhel <clamor95@gmail.com>
*/
#include <dm.h>
#include <clk.h>
#include <log.h>
#include <reset.h>
#include <linux/delay.h>
#include <asm/arch/clock.h>
#include <asm/arch-tegra/clk_rst.h>
struct tegra_host1x_info {
u32 clk_parent;
u32 rate;
};
static int tegra_host1x_probe(struct udevice *dev)
{
struct clk *clk;
struct reset_ctl reset_ctl;
const struct tegra_host1x_info *info;
int ret;
clk = devm_clk_get(dev, NULL);
if (IS_ERR(clk)) {
log_debug("%s: cannot get HOST1X clock: %ld\n",
__func__, PTR_ERR(clk));
return PTR_ERR(clk);
}
ret = reset_get_by_name(dev, "host1x", &reset_ctl);
if (ret) {
log_debug("%s: cannot get HOST1X reset: %d\n",
__func__, ret);
return ret;
}
info = (struct tegra_host1x_info *)dev_get_driver_data(dev);
reset_assert(&reset_ctl);
clock_start_periph_pll(clk->id, info->clk_parent, info->rate);
mdelay(2);
reset_deassert(&reset_ctl);
return 0;
}
static const struct tegra_host1x_info tegra20_host1x_info = {
.clk_parent = CLOCK_ID_CGENERAL,
.rate = 150000000, /* 150 MHz */
};
static const struct tegra_host1x_info tegra114_host1x_info = {
.clk_parent = CLOCK_ID_PERIPH,
.rate = 136000000, /* 136 MHz */
};
static const struct udevice_id tegra_host1x_ids[] = {
{
.compatible = "nvidia,tegra20-host1x",
.data = (ulong)&tegra20_host1x_info
}, {
.compatible = "nvidia,tegra30-host1x",
.data = (ulong)&tegra20_host1x_info
}, {
.compatible = "nvidia,tegra114-host1x",
.data = (ulong)&tegra114_host1x_info
}, {
.compatible = "nvidia,tegra124-host1x",
.data = (ulong)&tegra114_host1x_info
}, {
/* sentinel */
}
};
U_BOOT_DRIVER(tegra_host1x) = {
.name = "tegra_host1x",
.id = UCLASS_SIMPLE_BUS,
.of_match = tegra_host1x_ids,
.probe = tegra_host1x_probe,
.flags = DM_FLAG_PRE_RELOC,
};

View file

@ -17,9 +17,6 @@
#include "tegra-dc.h"
#define TEGRA_DISPLAY_A_BASE 0x54200000
#define TEGRA_DISPLAY_B_BASE 0x54240000
#define TEGRA_PWM_BL_MIN_BRIGHTNESS 0x10
#define TEGRA_PWM_BL_MAX_BRIGHTNESS 0xFF
@ -106,14 +103,11 @@ static int tegra_pwm_backlight_enable(struct udevice *dev)
static int tegra_pwm_backlight_probe(struct udevice *dev)
{
struct tegra_pwm_backlight_priv *priv = dev_get_priv(dev);
ofnode dc = ofnode_get_parent(dev_ofnode(dev));
if (dev_read_bool(dev, "nvidia,display-b-base"))
priv->dc = (struct dc_ctlr *)TEGRA_DISPLAY_B_BASE;
else
priv->dc = (struct dc_ctlr *)TEGRA_DISPLAY_A_BASE;
priv->dc = (struct dc_ctlr *)ofnode_get_addr(dc);
if (!priv->dc) {
log_err("no display controller address\n");
log_err("%s: failed to get DC controller\n", __func__);
return -EINVAL;
}

23
include/configs/ouya.h Normal file
View file

@ -0,0 +1,23 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* (C) Copyright 2010,2012
* NVIDIA Corporation <www.nvidia.com>
*
* (C) Copyright 2025
* Svyatoslav Ryhel <clamor95@gmail.com>
*/
#ifndef __CONFIG_H
#define __CONFIG_H
#include "tegra30-common.h"
/* High-level configuration options */
#define CFG_TEGRA_BOARD_STRING "Ouya Game Console"
/* Board-specific serial config */
#define CFG_SYS_NS16550_COM1 NV_PA_APB_UARTD_BASE
#include "tegra-common-post.h"
#endif /* __CONFIG_H */

View file

@ -3,6 +3,7 @@ boot_block_size=0x1000
bootloader_file=u-boot-dtb-tegra.bin
spi_size=0x400000
boot_dev=0
boot_interface=mmc
flash_uboot=echo Preparing RAM;
mw ${kernel_addr_r} 0 ${boot_block_size_r};
@ -11,9 +12,9 @@ flash_uboot=echo Preparing RAM;
mmc dev 0 1;
mmc read ${kernel_addr_r} 0 ${boot_block_size};
echo Reading bootloader;
if load mmc ${boot_dev}:1 ${ramdisk_addr_r} ${bootloader_file};
if load ${boot_interface} ${boot_dev}:1 ${ramdisk_addr_r} ${bootloader_file};
then echo Calculating bootloader size;
size mmc ${boot_dev}:1 ${bootloader_file};
size ${boot_interface} ${boot_dev}:1 ${bootloader_file};
ebtupdate ${kernel_addr_r} ${ramdisk_addr_r} ${filesize};
echo Writing bootloader to eMMC;
mmc dev 0 1;