diff --git a/arch/arm/dts/tegra20-colibri.dts b/arch/arm/dts/tegra20-colibri.dts index 2bed516f47..2cf24d3ee7 100644 --- a/arch/arm/dts/tegra20-colibri.dts +++ b/arch/arm/dts/tegra20-colibri.dts @@ -104,6 +104,10 @@ }; }; + pwm: pwm@7000a000 { + status = "okay"; + }; + lcd_panel: panel { clock = <25175000>; xres = <640>; diff --git a/arch/arm/dts/tegra20-harmony.dts b/arch/arm/dts/tegra20-harmony.dts index 3eb9aa503e..623eb90a8a 100644 --- a/arch/arm/dts/tegra20-harmony.dts +++ b/arch/arm/dts/tegra20-harmony.dts @@ -84,6 +84,10 @@ }; }; + pwm: pwm@7000a000 { + status = "okay"; + }; + lcd_panel: panel { clock = <42430000>; xres = <1024>; diff --git a/arch/arm/dts/tegra20-medcom-wide.dts b/arch/arm/dts/tegra20-medcom-wide.dts index a4886bf715..3d37257189 100644 --- a/arch/arm/dts/tegra20-medcom-wide.dts +++ b/arch/arm/dts/tegra20-medcom-wide.dts @@ -40,6 +40,10 @@ status = "okay"; }; + pwm: pwm@7000a000 { + status = "okay"; + }; + lcd_panel: panel { clock = <61715000>; xres = <1366>; diff --git a/arch/arm/dts/tegra20-paz00.dts b/arch/arm/dts/tegra20-paz00.dts index f5edff1349..5c7e80558d 100644 --- a/arch/arm/dts/tegra20-paz00.dts +++ b/arch/arm/dts/tegra20-paz00.dts @@ -65,6 +65,10 @@ }; }; + pwm: pwm@7000a000 { + status = "okay"; + }; + lcd_panel: panel { /* PAZ00 has 1024x600 */ clock = <54030000>; diff --git a/arch/arm/dts/tegra20-seaboard.dts b/arch/arm/dts/tegra20-seaboard.dts index 15bd12142b..eada59073e 100644 --- a/arch/arm/dts/tegra20-seaboard.dts +++ b/arch/arm/dts/tegra20-seaboard.dts @@ -200,6 +200,10 @@ }; }; + pwm: pwm@7000a000 { + status = "okay"; + }; + lcd_panel: panel { /* Seaboard has 1366x768 */ clock = <70600000>; diff --git a/arch/arm/dts/tegra20-tec.dts b/arch/arm/dts/tegra20-tec.dts index b16f10d410..4f68077faf 100644 --- a/arch/arm/dts/tegra20-tec.dts +++ b/arch/arm/dts/tegra20-tec.dts @@ -52,6 +52,10 @@ status = "disabled"; }; + pwm: pwm@7000a000 { + status = "okay"; + }; + lcd_panel: panel { clock = <33260000>; xres = <800>; diff --git a/arch/arm/dts/tegra20-ventana.dts b/arch/arm/dts/tegra20-ventana.dts index bbbe8b7a89..851e0ed8d9 100644 --- a/arch/arm/dts/tegra20-ventana.dts +++ b/arch/arm/dts/tegra20-ventana.dts @@ -65,6 +65,10 @@ }; }; + pwm: pwm@7000a000 { + status = "okay"; + }; + lcd_panel: panel { clock = <72072000>; xres = <1366>; diff --git a/arch/arm/mach-tegra/Kconfig b/arch/arm/mach-tegra/Kconfig index 3857243947..3540edab9a 100644 --- a/arch/arm/mach-tegra/Kconfig +++ b/arch/arm/mach-tegra/Kconfig @@ -9,6 +9,7 @@ config TEGRA_COMMON select DM_KEYBOARD select DM_PCI select DM_PCI_COMPAT + select DM_PWM select DM_SERIAL select DM_SPI select DM_SPI_FLASH diff --git a/drivers/pwm/Kconfig b/drivers/pwm/Kconfig index e5880ac84f..6f0d61e7ab 100644 --- a/drivers/pwm/Kconfig +++ b/drivers/pwm/Kconfig @@ -20,6 +20,7 @@ config PWM_ROCKCHIP config PWM_TEGRA bool "Enable support for the Tegra PWM" + depends on DM_PWM help This PWM is found on Tegra 20 and other Nvidia SoCs. It supports four channels with a programmable period and duty cycle. Only a diff --git a/drivers/video/tegra.c b/drivers/video/tegra.c index ccd9c0824e..7fd10e6af3 100644 --- a/drivers/video/tegra.c +++ b/drivers/video/tegra.c @@ -6,6 +6,7 @@ #include #include #include +#include #include #include #include @@ -68,6 +69,7 @@ struct tegra_lcd_priv { unsigned pixel_clock; /* Pixel clock in Hz */ uint horiz_timing[FDT_LCD_TIMING_COUNT]; /* Horizontal timing */ uint vert_timing[FDT_LCD_TIMING_COUNT]; /* Vertical timing */ + struct udevice *pwm; int pwm_channel; /* PWM channel to use for backlight */ enum lcd_cache_t cache_type; @@ -400,7 +402,8 @@ static int handle_stage(const void *blob, struct tegra_lcd_priv *priv) pinmux_set_func(PMUX_PINGRP_GPU, PMUX_FUNC_PWM); pinmux_tristate_disable(PMUX_PINGRP_GPU); - pwm_enable(priv->pwm_channel, 32768, 0xdf, 1); + pwm_set_config(priv->pwm, priv->pwm_channel, 0xdf, 0xff); + pwm_set_enable(priv->pwm, priv->pwm_channel, true); break; case STAGE_BACKLIGHT_EN: if (dm_gpio_is_valid(&priv->backlight_en)) @@ -504,12 +507,14 @@ static int tegra_lcd_probe(struct udevice *dev) static int tegra_lcd_ofdata_to_platdata(struct udevice *dev) { struct tegra_lcd_priv *priv = dev_get_priv(dev); + struct fdtdec_phandle_args args; const void *blob = gd->fdt_blob; int node = dev->of_offset; int front, back, ref; int panel_node; int rgb; int bpp, bit; + int ret; priv->disp = (struct disp_ctlr *)dev_get_addr(dev); if (!priv->disp) { @@ -575,12 +580,19 @@ static int tegra_lcd_ofdata_to_platdata(struct udevice *dev) return -EINVAL; } - priv->pwm_channel = pwm_request(blob, panel_node, "nvidia,pwm"); - if (priv->pwm_channel < 0) { - debug("%s: Unable to request PWM channel\n", __func__); + if (fdtdec_parse_phandle_with_args(blob, panel_node, "nvidia,pwm", + "#pwm-cells", 0, 0, &args)) { + debug("%s: Unable to decode PWM\n", __func__); return -EINVAL; } + ret = uclass_get_device_by_of_offset(UCLASS_PWM, args.node, &priv->pwm); + if (ret) { + debug("%s: Unable to find PWM\n", __func__); + return -EINVAL; + } + priv->pwm_channel = args.args[0]; + priv->cache_type = fdtdec_get_int(blob, panel_node, "nvidia,cache-type", FDT_LCD_CACHE_WRITE_BACK_FLUSH);