]> git.dujemihanovic.xyz Git - u-boot.git/commitdiff
tegra: nyan-big: Move the LCD driver to driver model
authorSimon Glass <sjg@chromium.org>
Sat, 30 Jan 2016 23:37:50 +0000 (16:37 -0700)
committerTom Warren <twarren@nvidia.com>
Tue, 16 Feb 2016 16:17:51 +0000 (09:17 -0700)
Adjust the driver to use driver model. The SOR becomes a bridge device. We
use the normal simple_panel driver to handle the display itself. We also
need to enable some options such as regulators, PWMs and DM_VIDEO itself.

Signed-off-by: Simon Glass <sjg@chromium.org>
Acked-by: Anatolij Gustschin <agust@denx.de>
Signed-off-by: Tom Warren <twarren@nvidia.com>
configs/nyan-big_defconfig
drivers/video/Kconfig
drivers/video/simple_panel.c
drivers/video/tegra124/display.c
drivers/video/tegra124/dp.c
drivers/video/tegra124/sor.c
drivers/video/tegra124/sor.h
include/configs/nyan-big.h
include/fdtdec.h
lib/fdtdec.c

index ca0f9e067bfe853b5072810336bcbdc52cd74489..12377bde09937a280a6dd0c1f12ffc4409a5c696 100644 (file)
@@ -12,6 +12,8 @@ CONFIG_SYS_PROMPT="Tegra124 (Nyan-big) # "
 CONFIG_CMD_GPIO=y
 # CONFIG_CMD_SETEXPR is not set
 # CONFIG_CMD_NFS is not set
+CONFIG_CMD_PMIC=y
+CONFIG_CMD_REGULATOR=y
 CONFIG_CMD_TPM=y
 CONFIG_CMD_TPM_TEST=y
 CONFIG_CROS_EC_KEYB=y
@@ -20,6 +22,10 @@ CONFIG_CROS_EC=y
 CONFIG_CROS_EC_SPI=y
 CONFIG_SPI_FLASH=y
 CONFIG_SPI_FLASH_WINBOND=y
+CONFIG_DM_PMIC=y
+CONFIG_DM_REGULATOR=y
+CONFIG_DM_REGULATOR_FIXED=y
+CONFIG_DM_PWM=y
 CONFIG_SYS_NS16550=y
 CONFIG_TEGRA114_SPI=y
 CONFIG_TPM_TIS_INFINEON=y
@@ -27,6 +33,9 @@ CONFIG_USB=y
 CONFIG_DM_USB=y
 CONFIG_DISPLAY=y
 CONFIG_I2C_EDID=y
+CONFIG_DM_VIDEO=y
 CONFIG_VIDEO_TEGRA124=y
+CONFIG_VIDEO_BRIDGE=y
 CONFIG_USE_PRIVATE_LIBGCC=y
 CONFIG_TPM=y
+CONFIG_ERRNO_STR=y
index 19f9429cce784450d5fbcea2d9d114638ebf3ed9..72afae0d26a81f31508d242d5a9da48a6bb40bac 100644 (file)
@@ -383,6 +383,7 @@ config VIDEO_SANDBOX_SDL
 
 config VIDEO_TEGRA124
        bool "Enable video support on Tegra124"
+       depends on DM_VIDEO
        help
           Tegra124 supports many video output options including eDP and
           HDMI. At present only eDP is supported by U-Boot. This option
index b16151767488fb4ba42143991ef244b0fd786ed9..c73f24295a4057893872321bc6a3fe617d9623ea 100644 (file)
@@ -85,6 +85,7 @@ static const struct panel_ops simple_panel_ops = {
 
 static const struct udevice_id simple_panel_ids[] = {
        { .compatible = "simple-panel" },
+       { .compatible = "auo,b133xtn01" },
        { }
 };
 
index b4c4093694a2d4c444cb38e9c7051854f451f2d9..2f1f0df20eb194e557697a9d70761cfda9f7047f 100644 (file)
 #include <edid.h>
 #include <fdtdec.h>
 #include <lcd.h>
+#include <video.h>
 #include <asm/gpio.h>
 #include <asm/io.h>
 #include <asm/arch/clock.h>
 #include <asm/arch/pwm.h>
 #include <asm/arch-tegra/dc.h>
+#include <dm/uclass-internal.h>
 #include "displayport.h"
 
 DECLARE_GLOBAL_DATA_PTR;
@@ -333,73 +335,46 @@ static int display_update_config_from_edid(struct udevice *dp_dev,
        return 0;
 }
 
-/* Somewhat torturous method */
-static int get_backlight_info(const void *blob, struct gpio_desc *vdd,
-                             struct gpio_desc *enable, int *pwmp)
-{
-       int sor, panel, backlight, power;
-       const u32 *prop;
-       int len;
-       int ret;
-
-       *pwmp = 0;
-       sor = fdtdec_next_compatible(blob, 0, COMPAT_NVIDIA_TEGRA124_SOR);
-       if (sor < 0)
-               return -ENOENT;
-       panel = fdtdec_lookup_phandle(blob, sor, "nvidia,panel");
-       if (panel < 0)
-               return -ENOENT;
-       backlight = fdtdec_lookup_phandle(blob, panel, "backlight");
-       if (backlight < 0)
-               return -ENOENT;
-       ret = gpio_request_by_name_nodev(blob, backlight, "enable-gpios", 0,
-                                        enable, GPIOD_IS_OUT);
-       if (ret)
-               return ret;
-       prop = fdt_getprop(blob, backlight, "pwms", &len);
-       if (!prop || len != 3 * sizeof(u32))
-               return -EINVAL;
-       *pwmp = fdt32_to_cpu(prop[1]);
-
-       power = fdtdec_lookup_phandle(blob, backlight, "power-supply");
-       if (power < 0)
-               return -ENOENT;
-       ret = gpio_request_by_name_nodev(blob, power, "gpio", 0, vdd,
-                                        GPIOD_IS_OUT);
-       if (ret)
-               goto err;
-
-       return 0;
-
-err:
-       dm_gpio_free(NULL, enable);
-       return ret;
-}
-
-static int display_init(void *lcdbase, int fb_bits_per_pixel,
-                       struct display_timing *timing)
+static int display_init(struct udevice *dev, void *lcdbase,
+                       int fb_bits_per_pixel, struct display_timing *timing)
 {
+       struct display_plat *disp_uc_plat;
        struct dc_ctlr *dc_ctlr;
        const void *blob = gd->fdt_blob;
        struct udevice *dp_dev;
        const int href_to_sync = 1, vref_to_sync = 1;
        int panel_bpp = 18;     /* default 18 bits per pixel */
        u32 plld_rate;
-       struct gpio_desc vdd_gpio, enable_gpio;
-       int pwm;
-       int node;
        int ret;
 
+       /*
+        * Before we probe the display device (eDP), tell it that this device
+        * is are the source of the display data.
+        */
+       ret = uclass_find_first_device(UCLASS_DISPLAY, &dp_dev);
+       if (ret) {
+               debug("%s: device '%s' display not found (ret=%d)\n", __func__,
+                     dev->name, ret);
+               return ret;
+       }
+
+       disp_uc_plat = dev_get_uclass_platdata(dp_dev);
+       debug("Found device '%s', disp_uc_priv=%p\n", dp_dev->name,
+             disp_uc_plat);
+       disp_uc_plat->src_dev = dev;
+
        ret = uclass_get_device(UCLASS_DISPLAY, 0, &dp_dev);
-       if (ret)
+       if (ret) {
+               debug("%s: Failed to probe eDP, ret=%d\n", __func__, ret);
                return ret;
+       }
 
-       node = fdtdec_next_compatible(blob, 0, COMPAT_NVIDIA_TEGRA124_DC);
-       if (node < 0)
-               return -ENOENT;
-       dc_ctlr = (struct dc_ctlr *)fdtdec_get_addr(blob, node, "reg");
-       if (fdtdec_decode_display_timing(blob, node, 0, timing))
+       dc_ctlr = (struct dc_ctlr *)fdtdec_get_addr(blob, dev->of_offset,
+                                                   "reg");
+       if (fdtdec_decode_display_timing(blob, dev->of_offset, 0, timing)) {
+               debug("%s: Failed to decode display timing\n", __func__);
                return -EINVAL;
+       }
 
        ret = display_update_config_from_edid(dp_dev, &panel_bpp, timing);
        if (ret) {
@@ -407,12 +382,6 @@ static int display_init(void *lcdbase, int fb_bits_per_pixel,
                dump_config(panel_bpp, timing);
        }
 
-       if (!get_backlight_info(blob, &vdd_gpio, &enable_gpio, &pwm)) {
-               dm_gpio_set_value(&vdd_gpio, 1);
-               debug("%s: backlight vdd setting gpio %08x to %d\n",
-                     __func__, gpio_get_number(&vdd_gpio), 1);
-       }
-
        /*
         * The plld is programmed with the assumption of the SHIFT_CLK_DIVIDER
         * and PIXEL_CLK_DIVIDER are zero (divide by 1). See the
@@ -443,21 +412,15 @@ static int display_init(void *lcdbase, int fb_bits_per_pixel,
 
        /* Enable dp */
        ret = display_enable(dp_dev, panel_bpp, timing);
-       if (ret)
+       if (ret) {
+               debug("dc: failed to enable display: ret=%d\n", ret);
                return ret;
+       }
 
        ret = update_window(dc_ctlr, (ulong)lcdbase, fb_bits_per_pixel, timing);
-       if (ret)
+       if (ret) {
+               debug("dc: failed to update window\n");
                return ret;
-
-       /* Set up Tegra PWM to drive the panel backlight */
-       pwm_enable(pwm, 0, 220, 0x2e);
-       udelay(10 * 1000);
-
-       if (dm_gpio_is_valid(&enable_gpio)) {
-               dm_gpio_set_value(&enable_gpio, 1);
-               debug("%s: backlight enable setting gpio %08x to %d\n",
-                     __func__, gpio_get_number(&enable_gpio), 1);
        }
 
        return 0;
@@ -470,29 +433,10 @@ enum {
        LCD_MAX_LOG2_BPP        = 4,            /* 2^4 = 16 bpp */
 };
 
-vidinfo_t panel_info = {
-       /* Insert a value here so that we don't end up in the BSS */
-       .vl_col = -1,
-};
-
-int tegra_lcd_check_next_stage(const void *blob, int wait)
-{
-       return 0;
-}
-
-void tegra_lcd_early_init(const void *blob)
-{
-       /*
-        * Go with the maximum size for now. We will fix this up after
-        * relocation. These values are only used for memory alocation.
-        */
-       panel_info.vl_col = LCD_MAX_WIDTH;
-       panel_info.vl_row = LCD_MAX_HEIGHT;
-       panel_info.vl_bpix = LCD_MAX_LOG2_BPP;
-}
-
-static int tegra124_lcd_init(void *lcdbase)
+static int tegra124_lcd_init(struct udevice *dev, void *lcdbase,
+                            enum video_log2_bpp l2bpp)
 {
+       struct video_priv *uc_priv = dev_get_uclass_priv(dev);
        struct display_timing timing;
        int ret;
 
@@ -512,30 +456,55 @@ static int tegra124_lcd_init(void *lcdbase)
        reset_set_enable(PERIPH_ID_DPAUX, 0);
        reset_set_enable(PERIPH_ID_SOR0, 0);
 
-       ret = display_init(lcdbase, 1 << LCD_BPP, &timing);
+       ret = display_init(dev, lcdbase, 1 << l2bpp, &timing);
        if (ret)
                return ret;
 
-       panel_info.vl_col = roundup(timing.hactive.typ, 16);
-       panel_info.vl_row = timing.vactive.typ;
+       uc_priv->xsize = roundup(timing.hactive.typ, 16);
+       uc_priv->ysize = timing.vactive.typ;
+       uc_priv->bpix = l2bpp;
 
-       lcd_set_flush_dcache(1);
+       video_set_flush_dcache(dev, 1);
+       debug("%s: done\n", __func__);
 
        return 0;
 }
 
-void lcd_ctrl_init(void *lcdbase)
+static int tegra124_lcd_probe(struct udevice *dev)
 {
+       struct video_uc_platdata *plat = dev_get_uclass_platdata(dev);
        ulong start;
        int ret;
 
        start = get_timer(0);
-       ret = tegra124_lcd_init(lcdbase);
+       ret = tegra124_lcd_init(dev, (void *)plat->base, VIDEO_BPP16);
        debug("LCD init took %lu ms\n", get_timer(start));
        if (ret)
                printf("%s: Error %d\n", __func__, ret);
+
+       return 0;
 }
 
-void lcd_enable(void)
+static int tegra124_lcd_bind(struct udevice *dev)
 {
+       struct video_uc_platdata *uc_plat = dev_get_uclass_platdata(dev);
+
+       uc_plat->size = LCD_MAX_WIDTH * LCD_MAX_HEIGHT *
+                       (1 << VIDEO_BPP16) / 8;
+       debug("%s: Frame buffer size %x\n", __func__, uc_plat->size);
+
+       return 0;
 }
+
+static const struct udevice_id tegra124_lcd_ids[] = {
+       { .compatible = "nvidia,tegra124-dc" },
+       { }
+};
+
+U_BOOT_DRIVER(tegra124_dc) = {
+       .name   = "tegra124-dc",
+       .id     = UCLASS_VIDEO,
+       .of_match = tegra124_lcd_ids,
+       .bind   = tegra124_lcd_bind,
+       .probe  = tegra124_lcd_probe,
+};
index bb1805a24822e6cb81b3e4cd35efb4a1f43f43a0..5bf8524a5e8a7d315900aaec5e5f14f8c8ca9a06 100644 (file)
@@ -11,6 +11,7 @@
 #include <div64.h>
 #include <errno.h>
 #include <fdtdec.h>
+#include <video_bridge.h>
 #include <asm/io.h>
 #include <asm/arch-tegra/dc.h>
 #include "display.h"
@@ -26,9 +27,15 @@ struct tegra_dp_plat {
        ulong base;
 };
 
+/**
+ * struct tegra_dp_priv - private displayport driver info
+ *
+ * @dc_dev:    Display controller device that is sending the video feed
+ */
 struct tegra_dp_priv {
+       struct udevice *sor;
+       struct udevice *dc_dev;
        struct dpaux_ctlr *regs;
-       struct tegra_dc_sor_data *sor;
        u8 revision;
        int enabled;
 };
@@ -710,8 +717,8 @@ static int tegra_dc_dp_init_max_link_cfg(
        return 0;
 }
 
-static int tegra_dc_dp_set_assr(struct tegra_dp_priv *dp,
-                               struct tegra_dc_sor_data *sor, int ena)
+static int tegra_dc_dp_set_assr(struct tegra_dp_priv *priv,
+                               struct udevice *sor, int ena)
 {
        int ret;
 
@@ -719,7 +726,7 @@ static int tegra_dc_dp_set_assr(struct tegra_dp_priv *dp,
                DP_MAIN_LINK_CHANNEL_CODING_SET_ASC_RESET_ENABLE :
                DP_MAIN_LINK_CHANNEL_CODING_SET_ASC_RESET_DISABLE;
 
-       ret = tegra_dc_dp_dpcd_write(dp, DP_EDP_CONFIGURATION_SET,
+       ret = tegra_dc_dp_dpcd_write(priv, DP_EDP_CONFIGURATION_SET,
                                     dpcd_data);
        if (ret)
                return ret;
@@ -730,7 +737,7 @@ static int tegra_dc_dp_set_assr(struct tegra_dp_priv *dp,
 }
 
 static int tegra_dp_set_link_bandwidth(struct tegra_dp_priv *dp,
-                                      struct tegra_dc_sor_data *sor,
+                                      struct udevice *sor,
                                       u8 link_bw)
 {
        tegra_dc_sor_set_link_bandwidth(sor, link_bw);
@@ -741,7 +748,7 @@ static int tegra_dp_set_link_bandwidth(struct tegra_dp_priv *dp,
 
 static int tegra_dp_set_lane_count(struct tegra_dp_priv *dp,
                const struct tegra_dp_link_config *link_cfg,
-               struct tegra_dc_sor_data *sor)
+               struct udevice *sor)
 {
        u8      dpcd_data;
        int     ret;
@@ -1002,7 +1009,7 @@ fail:
 static int tegra_dp_lt_config(struct tegra_dp_priv *dp, u32 pe[4], u32 vs[4],
                              u32 pc[4], const struct tegra_dp_link_config *cfg)
 {
-       struct tegra_dc_sor_data *sor = dp->sor;
+       struct udevice *sor = dp->sor;
        u32 n_lanes = cfg->lane_count;
        u8 pc_supported = cfg->tps3_supported;
        u32 cnt;
@@ -1186,7 +1193,7 @@ static int tegra_dc_dp_full_link_training(struct tegra_dp_priv *dp,
                                          const struct display_timing *timing,
                                          struct tegra_dp_link_config *cfg)
 {
-       struct tegra_dc_sor_data *sor = dp->sor;
+       struct udevice *sor = dp->sor;
        int err;
        u32 pe[4], vs[4], pc[4];
 
@@ -1229,7 +1236,7 @@ fail:
  */
 static int tegra_dc_dp_fast_link_training(struct tegra_dp_priv *dp,
                const struct tegra_dp_link_config *link_cfg,
-               struct tegra_dc_sor_data *sor)
+               struct udevice *sor)
 {
        u8      link_bw;
        u8      lane_count;
@@ -1301,7 +1308,7 @@ static int tegra_dc_dp_fast_link_training(struct tegra_dp_priv *dp,
 static int tegra_dp_do_link_training(struct tegra_dp_priv *dp,
                struct tegra_dp_link_config *link_cfg,
                const struct display_timing *timing,
-               struct tegra_dc_sor_data *sor)
+               struct udevice *sor)
 {
        u8      link_bw;
        u8      lane_count;
@@ -1344,7 +1351,7 @@ static int tegra_dp_do_link_training(struct tegra_dp_priv *dp,
 
 static int tegra_dc_dp_explore_link_cfg(struct tegra_dp_priv *dp,
                        struct tegra_dp_link_config *link_cfg,
-                       struct tegra_dc_sor_data *sor,
+                       struct udevice *sor,
                        const struct display_timing *timing)
 {
        struct tegra_dp_link_config temp_cfg;
@@ -1444,7 +1451,7 @@ static int tegra_dc_dp_check_sink(struct tegra_dp_priv *dp,
                        printf("DP: Out of sync after %d retries\n", max_retry);
                        return -EIO;
                }
-               ret = tegra_dc_sor_detach(dp->sor);
+               ret = tegra_dc_sor_detach(dp->dc_dev, dp->sor);
                if (ret)
                        return ret;
                if (tegra_dc_dp_explore_link_cfg(dp, link_cfg, dp->sor,
@@ -1454,7 +1461,7 @@ static int tegra_dc_dp_check_sink(struct tegra_dp_priv *dp,
                }
 
                tegra_dc_sor_set_power_state(dp->sor, 1);
-               tegra_dc_sor_attach(dp->sor, link_cfg, timing);
+               tegra_dc_sor_attach(dp->dc_dev, dp->sor, link_cfg, timing);
 
                /* Increase delay_frame for next try in case the sink is
                   skipping more frames */
@@ -1467,7 +1474,7 @@ int tegra_dp_enable(struct udevice *dev, int panel_bpp,
 {
        struct tegra_dp_priv *priv = dev_get_priv(dev);
        struct tegra_dp_link_config slink_cfg, *link_cfg = &slink_cfg;
-       struct tegra_dc_sor_data *sor;
+       struct udevice *sor;
        int data;
        int retry;
        int ret;
@@ -1489,9 +1496,11 @@ int tegra_dp_enable(struct udevice *dev, int panel_bpp,
                return -ENOLINK;
        }
 
-       ret = tegra_dc_sor_init(&sor);
-       if (ret)
+       ret = uclass_first_device(UCLASS_VIDEO_BRIDGE, &sor);
+       if (ret || !sor) {
+               debug("dp: failed to find SOR device: ret=%d\n", ret);
                return ret;
+       }
        priv->sor = sor;
        ret = tegra_dc_sor_enable_dp(sor, link_cfg);
        if (ret)
@@ -1531,7 +1540,7 @@ int tegra_dp_enable(struct udevice *dev, int panel_bpp,
        }
 
        tegra_dc_sor_set_power_state(sor, 1);
-       ret = tegra_dc_sor_attach(sor, link_cfg, timing);
+       ret = tegra_dc_sor_attach(priv->dc_dev, sor, link_cfg, timing);
        if (ret && ret != -EEXIST)
                return ret;
 
@@ -1548,6 +1557,12 @@ int tegra_dp_enable(struct udevice *dev, int panel_bpp,
        /* Power down the unused lanes to save power - a few hundred mW */
        tegra_dc_sor_power_down_unused_lanes(sor, link_cfg);
 
+       ret = video_bridge_set_backlight(sor, 80);
+       if (ret) {
+               debug("dp: failed to set backlight\n");
+               return ret;
+       }
+
        priv->enabled = true;
 error_enable:
        return 0;
@@ -1583,10 +1598,14 @@ static int dp_tegra_probe(struct udevice *dev)
 {
        struct tegra_dp_plat *plat = dev_get_platdata(dev);
        struct tegra_dp_priv *priv = dev_get_priv(dev);
+       struct display_plat *disp_uc_plat = dev_get_uclass_platdata(dev);
 
        priv->regs = (struct dpaux_ctlr *)plat->base;
        priv->enabled = false;
 
+       /* Remember the display controller that is sending us video */
+       priv->dc_dev = disp_uc_plat->src_dev;
+
        return 0;
 }
 
index aa3d80c4c0fd97944b8abd4ef96202a1ba0106c2..e5cea51d48c81a01494effaba1d7eb674a9c5342 100644 (file)
@@ -5,9 +5,12 @@
  */
 
 #include <common.h>
+#include <dm.h>
 #include <errno.h>
 #include <fdtdec.h>
 #include <malloc.h>
+#include <panel.h>
+#include <video_bridge.h>
 #include <asm/io.h>
 #include <asm/arch/clock.h>
 #include <asm/arch-tegra/dc.h>
@@ -37,6 +40,14 @@ DECLARE_GLOBAL_DATA_PTR;
 #define APBDEV_PMC_IO_DPD2_STATUS_LVDS_OFF             (0 << 25)
 #define APBDEV_PMC_IO_DPD2_STATUS_LVDS_ON              (1 << 25)
 
+struct tegra_dc_sor_data {
+       void *base;
+       void *pmc_base;
+       u8 portnum;     /* 0 or 1 */
+       int power_is_up;
+       struct udevice *panel;
+};
+
 static inline u32 tegra_sor_readl(struct tegra_dc_sor_data *sor, u32 reg)
 {
        return readl((u32 *)sor->base + reg);
@@ -57,15 +68,19 @@ static inline void tegra_sor_write_field(struct tegra_dc_sor_data *sor,
        tegra_sor_writel(sor, reg, reg_val);
 }
 
-void tegra_dp_disable_tx_pu(struct tegra_dc_sor_data *sor)
+void tegra_dp_disable_tx_pu(struct udevice *dev)
 {
+       struct tegra_dc_sor_data *sor = dev_get_priv(dev);
+
        tegra_sor_write_field(sor, DP_PADCTL(sor->portnum),
                              DP_PADCTL_TX_PU_MASK, DP_PADCTL_TX_PU_DISABLE);
 }
 
-void tegra_dp_set_pe_vs_pc(struct tegra_dc_sor_data *sor, u32 mask, u32 pe_reg,
+void tegra_dp_set_pe_vs_pc(struct udevice *dev, u32 mask, u32 pe_reg,
                           u32 vs_reg, u32 pc_reg, u8 pc_supported)
 {
+       struct tegra_dc_sor_data *sor = dev_get_priv(dev);
+
        tegra_sor_write_field(sor, PR(sor->portnum), mask, pe_reg);
        tegra_sor_write_field(sor, DC(sor->portnum), mask, vs_reg);
        if (pc_supported) {
@@ -95,8 +110,9 @@ static int tegra_dc_sor_poll_register(struct tegra_dc_sor_data *sor, u32 reg,
        return -ETIMEDOUT;
 }
 
-int tegra_dc_sor_set_power_state(struct tegra_dc_sor_data *sor, int pu_pd)
+int tegra_dc_sor_set_power_state(struct udevice *dev, int pu_pd)
 {
+       struct tegra_dc_sor_data *sor = dev_get_priv(dev);
        u32 reg_val;
        u32 orig_val;
 
@@ -123,10 +139,11 @@ int tegra_dc_sor_set_power_state(struct tegra_dc_sor_data *sor, int pu_pd)
        return 0;
 }
 
-void tegra_dc_sor_set_dp_linkctl(struct tegra_dc_sor_data *sor, int ena,
+void tegra_dc_sor_set_dp_linkctl(struct udevice *dev, int ena,
                                 u8 training_pattern,
                                 const struct tegra_dp_link_config *link_cfg)
 {
+       struct tegra_dc_sor_data *sor = dev_get_priv(dev);
        u32 reg_val;
 
        reg_val = tegra_sor_readl(sor, DP_LINKCTL(sor->portnum));
@@ -194,9 +211,10 @@ static int tegra_dc_sor_enable_lane_sequencer(struct tegra_dc_sor_data *sor,
        return 0;
 }
 
-static int tegra_dc_sor_power_dplanes(struct tegra_dc_sor_data *sor,
+static int tegra_dc_sor_power_dplanes(struct udevice *dev,
                                      u32 lane_count, int pu)
 {
+       struct tegra_dc_sor_data *sor = dev_get_priv(dev);
        u32 reg_val;
 
        reg_val = tegra_sor_readl(sor, DP_PADCTL(sor->portnum));
@@ -218,15 +236,15 @@ static int tegra_dc_sor_power_dplanes(struct tegra_dc_sor_data *sor,
                }
 
                tegra_sor_writel(sor, DP_PADCTL(sor->portnum), reg_val);
-               tegra_dc_sor_set_lane_count(sor, lane_count);
+               tegra_dc_sor_set_lane_count(dev, lane_count);
        }
 
        return tegra_dc_sor_enable_lane_sequencer(sor, pu, 0);
 }
 
-void tegra_dc_sor_set_panel_power(struct tegra_dc_sor_data *sor,
-                                 int power_up)
+void tegra_dc_sor_set_panel_power(struct udevice *dev, int power_up)
 {
+       struct tegra_dc_sor_data *sor = dev_get_priv(dev);
        u32 reg_val;
 
        reg_val = tegra_sor_readl(sor, DP_PADCTL(sor->portnum));
@@ -255,14 +273,15 @@ static void tegra_dc_sor_config_pwm(struct tegra_dc_sor_data *sor, u32 pwm_div,
        }
 }
 
-static void tegra_dc_sor_set_dp_mode(struct tegra_dc_sor_data *sor,
+static void tegra_dc_sor_set_dp_mode(struct udevice *dev,
                                const struct tegra_dp_link_config *link_cfg)
 {
+       struct tegra_dc_sor_data *sor = dev_get_priv(dev);
        u32 reg_val;
 
-       tegra_dc_sor_set_link_bandwidth(sor, link_cfg->link_bw);
+       tegra_dc_sor_set_link_bandwidth(dev, link_cfg->link_bw);
 
-       tegra_dc_sor_set_dp_linkctl(sor, 1, training_pattern_none, link_cfg);
+       tegra_dc_sor_set_dp_linkctl(dev, 1, training_pattern_none, link_cfg);
        reg_val = tegra_sor_readl(sor, DP_CONFIG(sor->portnum));
        reg_val &= ~DP_CONFIG_WATERMARK_MASK;
        reg_val |= link_cfg->watermark;
@@ -351,8 +370,9 @@ static int tegra_dc_sor_io_set_dpd(struct tegra_dc_sor_data *sor, int up)
        return 0;
 }
 
-void tegra_dc_sor_set_internal_panel(struct tegra_dc_sor_data *sor, int is_int)
+void tegra_dc_sor_set_internal_panel(struct udevice *dev, int is_int)
 {
+       struct tegra_dc_sor_data *sor = dev_get_priv(dev);
        u32 reg_val;
 
        reg_val = tegra_sor_readl(sor, DP_SPARE(sor->portnum));
@@ -366,9 +386,10 @@ void tegra_dc_sor_set_internal_panel(struct tegra_dc_sor_data *sor, int is_int)
        tegra_sor_writel(sor, DP_SPARE(sor->portnum), reg_val);
 }
 
-void tegra_dc_sor_read_link_config(struct tegra_dc_sor_data *sor, u8 *link_bw,
+void tegra_dc_sor_read_link_config(struct udevice *dev, u8 *link_bw,
                                   u8 *lane_count)
 {
+       struct tegra_dc_sor_data *sor = dev_get_priv(dev);
        u32 reg_val;
 
        reg_val = tegra_sor_readl(sor, CLK_CNTRL);
@@ -395,15 +416,18 @@ void tegra_dc_sor_read_link_config(struct tegra_dc_sor_data *sor, u8 *link_bw,
        }
 }
 
-void tegra_dc_sor_set_link_bandwidth(struct tegra_dc_sor_data *sor, u8 link_bw)
+void tegra_dc_sor_set_link_bandwidth(struct udevice *dev, u8 link_bw)
 {
+       struct tegra_dc_sor_data *sor = dev_get_priv(dev);
+
        tegra_sor_write_field(sor, CLK_CNTRL,
                              CLK_CNTRL_DP_LINK_SPEED_MASK,
                              link_bw << CLK_CNTRL_DP_LINK_SPEED_SHIFT);
 }
 
-void tegra_dc_sor_set_lane_count(struct tegra_dc_sor_data *sor, u8 lane_count)
+void tegra_dc_sor_set_lane_count(struct udevice *dev, u8 lane_count)
 {
+       struct tegra_dc_sor_data *sor = dev_get_priv(dev);
        u32 reg_val;
 
        reg_val = tegra_sor_readl(sor, DP_LINKCTL(sor->portnum));
@@ -439,15 +463,16 @@ void tegra_dc_sor_set_lane_count(struct tegra_dc_sor_data *sor, u8 lane_count)
  * 4   1       0       0       0       0       0       1
  * 5   0       0       0       0       0       0       1
  */
-static int tegra_dc_sor_power_up(struct tegra_dc_sor_data *sor, int is_lvds)
+static int tegra_dc_sor_power_up(struct udevice *dev, int is_lvds)
 {
+       struct tegra_dc_sor_data *sor = dev_get_priv(dev);
        int ret;
 
        if (sor->power_is_up)
                return 0;
 
        /* Set link bw */
-       tegra_dc_sor_set_link_bandwidth(sor, is_lvds ?
+       tegra_dc_sor_set_link_bandwidth(dev, is_lvds ?
                                        CLK_CNTRL_DP_LINK_SPEED_LVDS :
                                        CLK_CNTRL_DP_LINK_SPEED_G1_62);
 
@@ -655,9 +680,10 @@ static void tegra_dc_sor_enable_dc(struct dc_ctlr *disp_ctrl)
        writel(reg_val, &disp_ctrl->cmd.state_access);
 }
 
-int tegra_dc_sor_enable_dp(struct tegra_dc_sor_data *sor,
+int tegra_dc_sor_enable_dp(struct udevice *dev,
                           const struct tegra_dp_link_config *link_cfg)
 {
+       struct tegra_dc_sor_data *sor = dev_get_priv(dev);
        int ret;
 
        tegra_sor_write_field(sor, CLK_CNTRL,
@@ -701,7 +727,7 @@ int tegra_dc_sor_enable_dp(struct tegra_dc_sor_data *sor,
                              PLL2_AUX2_OVERRIDE_POWERDOWN |
                              PLL2_AUX7_PORT_POWERDOWN_DISABLE);
 
-       ret = tegra_dc_sor_power_up(sor, 0);
+       ret = tegra_dc_sor_power_up(dev, 0);
        if (ret) {
                debug("DP failed to power up\n");
                return ret;
@@ -711,18 +737,19 @@ int tegra_dc_sor_enable_dp(struct tegra_dc_sor_data *sor,
        clock_sor_enable_edp_clock();
 
        /* Power up lanes */
-       tegra_dc_sor_power_dplanes(sor, link_cfg->lane_count, 1);
+       tegra_dc_sor_power_dplanes(dev, link_cfg->lane_count, 1);
 
-       tegra_dc_sor_set_dp_mode(sor, link_cfg);
+       tegra_dc_sor_set_dp_mode(dev, link_cfg);
        debug("%s ret\n", __func__);
 
        return 0;
 }
 
-int tegra_dc_sor_attach(struct tegra_dc_sor_data *sor,
+int tegra_dc_sor_attach(struct udevice *dc_dev, struct udevice *dev,
                        const struct tegra_dp_link_config *link_cfg,
                        const struct display_timing *timing)
 {
+       struct tegra_dc_sor_data *sor = dev_get_priv(dev);
        const void *blob = gd->fdt_blob;
        struct dc_ctlr *disp_ctrl;
        u32 reg_val;
@@ -730,9 +757,7 @@ int tegra_dc_sor_attach(struct tegra_dc_sor_data *sor,
 
        /* Use the first display controller */
        debug("%s\n", __func__);
-       node = fdtdec_next_compatible(blob, 0, COMPAT_NVIDIA_TEGRA124_DC);
-       if (node < 0)
-               return -ENOENT;
+       node = dc_dev->of_offset;
        disp_ctrl = (struct dc_ctlr *)fdtdec_get_addr(blob, node, "reg");
 
        tegra_dc_sor_enable_dc(disp_ctrl);
@@ -798,9 +823,11 @@ int tegra_dc_sor_attach(struct tegra_dc_sor_data *sor,
        return 0;
 }
 
-void tegra_dc_sor_set_lane_parm(struct tegra_dc_sor_data *sor,
+void tegra_dc_sor_set_lane_parm(struct udevice *dev,
                const struct tegra_dp_link_config *link_cfg)
 {
+       struct tegra_dc_sor_data *sor = dev_get_priv(dev);
+
        tegra_sor_writel(sor, LANE_DRIVE_CURRENT(sor->portnum),
                         link_cfg->drive_current);
        tegra_sor_writel(sor, PR(sor->portnum),
@@ -809,8 +836,8 @@ void tegra_dc_sor_set_lane_parm(struct tegra_dc_sor_data *sor,
                         link_cfg->postcursor);
        tegra_sor_writel(sor, LVDS, 0);
 
-       tegra_dc_sor_set_link_bandwidth(sor, link_cfg->link_bw);
-       tegra_dc_sor_set_lane_count(sor, link_cfg->lane_count);
+       tegra_dc_sor_set_link_bandwidth(dev, link_cfg->link_bw);
+       tegra_dc_sor_set_lane_count(dev, link_cfg->lane_count);
 
        tegra_sor_write_field(sor, DP_PADCTL(sor->portnum),
                              DP_PADCTL_TX_PU_ENABLE |
@@ -825,9 +852,10 @@ void tegra_dc_sor_set_lane_parm(struct tegra_dc_sor_data *sor,
        tegra_sor_write_field(sor, DP_PADCTL(sor->portnum), 0xf0, 0x0);
 }
 
-int tegra_dc_sor_set_voltage_swing(struct tegra_dc_sor_data *sor,
+int tegra_dc_sor_set_voltage_swing(struct udevice *dev,
                                    const struct tegra_dp_link_config *link_cfg)
 {
+       struct tegra_dc_sor_data *sor = dev_get_priv(dev);
        u32 drive_current = 0;
        u32 pre_emphasis = 0;
 
@@ -851,9 +879,10 @@ int tegra_dc_sor_set_voltage_swing(struct tegra_dc_sor_data *sor,
        return 0;
 }
 
-void tegra_dc_sor_power_down_unused_lanes(struct tegra_dc_sor_data *sor,
+void tegra_dc_sor_power_down_unused_lanes(struct udevice *dev,
                        const struct tegra_dp_link_config *link_cfg)
 {
+       struct tegra_dc_sor_data *sor = dev_get_priv(dev);
        u32 pad_ctrl = 0;
        int err = 0;
 
@@ -891,9 +920,10 @@ void tegra_dc_sor_power_down_unused_lanes(struct tegra_dc_sor_data *sor,
        }
 }
 
-int tegra_sor_precharge_lanes(struct tegra_dc_sor_data *sor,
+int tegra_sor_precharge_lanes(struct udevice *dev,
                              const struct tegra_dp_link_config *cfg)
 {
+       struct tegra_dc_sor_data *sor = dev_get_priv(dev);
        u32 val = 0;
 
        switch (cfg->lane_count) {
@@ -931,8 +961,9 @@ static void tegra_dc_sor_enable_sor(struct dc_ctlr *disp_ctrl, bool enable)
        writel(reg_val, &disp_ctrl->disp.disp_win_opt);
 }
 
-int tegra_dc_sor_detach(struct tegra_dc_sor_data *sor)
+int tegra_dc_sor_detach(struct udevice *dc_dev, struct udevice *dev)
 {
+       struct tegra_dc_sor_data *sor = dev_get_priv(dev);
        int dc_reg_ctx[DC_REG_SAVE_SPACE];
        const void *blob = gd->fdt_blob;
        struct dc_ctlr *disp_ctrl;
@@ -942,11 +973,7 @@ int tegra_dc_sor_detach(struct tegra_dc_sor_data *sor)
 
        debug("%s\n", __func__);
        /* Use the first display controller */
-       node = fdtdec_next_compatible(blob, 0, COMPAT_NVIDIA_TEGRA124_DC);
-       if (node < 0) {
-               ret = -ENOENT;
-               goto err;
-       }
+       node = dc_dev->of_offset;
        disp_ctrl = (struct dc_ctlr *)fdtdec_get_addr(blob, node, "reg");
 
        /* Sleep mode */
@@ -997,28 +1024,61 @@ err:
        return ret;
 }
 
-int tegra_dc_sor_init(struct tegra_dc_sor_data **sorp)
+static int tegra_sor_set_backlight(struct udevice *dev, int percent)
 {
+       struct tegra_dc_sor_data *priv = dev_get_priv(dev);
+       int ret;
+
+       ret = panel_enable_backlight(priv->panel);
+       if (ret) {
+               debug("sor: Cannot enable panel backlight\n");
+               return ret;
+       }
+
+       return 0;
+}
+
+static int tegra_sor_ofdata_to_platdata(struct udevice *dev)
+{
+       struct tegra_dc_sor_data *priv = dev_get_priv(dev);
        const void *blob = gd->fdt_blob;
-       struct tegra_dc_sor_data *sor;
        int node;
+       int ret;
 
-       node = fdtdec_next_compatible(blob, 0, COMPAT_NVIDIA_TEGRA124_SOR);
-       if (node < 0)
-               return -ENOENT;
-       sor = calloc(1, sizeof(*sor));
-       if (!sor)
-               return -ENOMEM;
-       sor->base = (void *)fdtdec_get_addr(blob, node, "reg");
+       priv->base = (void *)fdtdec_get_addr(blob, dev->of_offset, "reg");
 
        node = fdtdec_next_compatible(blob, 0, COMPAT_NVIDIA_TEGRA124_PMC);
-       if (node < 0)
+       if (node < 0) {
+               debug("%s: Cannot find PMC\n", __func__);
                return -ENOENT;
-       sor->pmc_base = (void *)fdtdec_get_addr(blob, node, "reg");
+       }
+       priv->pmc_base = (void *)fdtdec_get_addr(blob, node, "reg");
 
-       sor->power_is_up = 0;
-       sor->portnum = 0;
-       *sorp = sor;
+       ret = uclass_get_device_by_phandle(UCLASS_PANEL, dev, "nvidia,panel",
+                                          &priv->panel);
+       if (ret) {
+               debug("%s: Cannot find panel for '%s' (ret=%d)\n", __func__,
+                     dev->name, ret);
+               return ret;
+       }
 
        return 0;
 }
+
+static const struct video_bridge_ops tegra_sor_ops = {
+       .set_backlight  = tegra_sor_set_backlight,
+};
+
+static const struct udevice_id tegra_sor_ids[] = {
+       { .compatible = "nvidia,tegra124-sor" },
+       { }
+};
+
+U_BOOT_DRIVER(sor_tegra) = {
+       .name   = "sor_tegra",
+       .id     = UCLASS_VIDEO_BRIDGE,
+       .of_match = tegra_sor_ids,
+       .ofdata_to_platdata = tegra_sor_ofdata_to_platdata,
+       .ops    = &tegra_sor_ops,
+       .priv_auto_alloc_size = sizeof(struct tegra_dc_sor_data),
+};
index dc8fd03d808da491d141eb899fbbb96add664ee2..e854bef17d13c5cd3f4bb9cdbf453d4a850df1bc 100644 (file)
@@ -873,44 +873,37 @@ struct tegra_dp_link_config {
        u8      tps3_supported;
 };
 
-struct tegra_dc_sor_data {
-       void *base;
-       void *pmc_base;
-       u8  portnum;    /* 0 or 1 */
-       int power_is_up;
-};
-
 #define TEGRA_SOR_TIMEOUT_MS           1000
 #define TEGRA_SOR_ATTACH_TIMEOUT_MS    1000
 
-int tegra_dc_sor_enable_dp(struct tegra_dc_sor_data *sor,
+int tegra_dc_sor_enable_dp(struct udevice *sor,
                           const struct tegra_dp_link_config *link_cfg);
-int tegra_dc_sor_set_power_state(struct tegra_dc_sor_data *sor, int pu_pd);
-void tegra_dc_sor_set_dp_linkctl(struct tegra_dc_sor_data *sor, int ena,
+int tegra_dc_sor_set_power_state(struct udevice *sor, int pu_pd);
+void tegra_dc_sor_set_dp_linkctl(struct udevice *dev, int ena,
        u8 training_pattern, const struct tegra_dp_link_config *link_cfg);
-void tegra_dc_sor_set_link_bandwidth(struct tegra_dc_sor_data *sor, u8 link_bw);
-void tegra_dc_sor_set_lane_count(struct tegra_dc_sor_data *sor, u8 lane_count);
-void tegra_dc_sor_set_panel_power(struct tegra_dc_sor_data *sor,
+void tegra_dc_sor_set_link_bandwidth(struct udevice *dev, u8 link_bw);
+void tegra_dc_sor_set_lane_count(struct udevice *dev, u8 lane_count);
+void tegra_dc_sor_set_panel_power(struct udevice *sor,
                                  int power_up);
-void tegra_dc_sor_set_internal_panel(struct tegra_dc_sor_data *sor, int is_int);
-void tegra_dc_sor_read_link_config(struct tegra_dc_sor_data *sor, u8 *link_bw,
+void tegra_dc_sor_set_internal_panel(struct udevice *dev, int is_int);
+void tegra_dc_sor_read_link_config(struct udevice *dev, u8 *link_bw,
                                   u8 *lane_count);
-void tegra_dc_sor_set_lane_parm(struct tegra_dc_sor_data *sor,
-                       const struct tegra_dp_link_config *link_cfg);
-void tegra_dc_sor_power_down_unused_lanes(struct tegra_dc_sor_data *sor,
+void tegra_dc_sor_set_lane_parm(struct udevice *dev,
+               const struct tegra_dp_link_config *link_cfg);
+void tegra_dc_sor_power_down_unused_lanes(struct udevice *sor,
                        const struct tegra_dp_link_config *link_cfg);
-int tegra_dc_sor_set_voltage_swing(struct tegra_dc_sor_data *sor,
+int tegra_dc_sor_set_voltage_swing(struct udevice *sor,
                                const struct tegra_dp_link_config *link_cfg);
-int tegra_sor_precharge_lanes(struct tegra_dc_sor_data *sor,
+int tegra_sor_precharge_lanes(struct udevice *dev,
                              const struct tegra_dp_link_config *cfg);
-void tegra_dp_disable_tx_pu(struct tegra_dc_sor_data *sor);
-void tegra_dp_set_pe_vs_pc(struct tegra_dc_sor_data *sor, u32 mask,
-                          u32 pe_reg, u32 vs_reg, u32 pc_reg, u8 pc_supported);
+void tegra_dp_disable_tx_pu(struct udevice *sor);
+void tegra_dp_set_pe_vs_pc(struct udevice *dev, u32 mask, u32 pe_reg,
+                          u32 vs_reg, u32 pc_reg, u8 pc_supported);
 
-int tegra_dc_sor_attach(struct tegra_dc_sor_data *sor,
+int tegra_dc_sor_attach(struct udevice *dc_dev, struct udevice *sor,
                        const struct tegra_dp_link_config *link_cfg,
                        const struct display_timing *timing);
-int tegra_dc_sor_detach(struct tegra_dc_sor_data *sor);
+int tegra_dc_sor_detach(struct udevice *dc_dev, struct udevice *sor);
 
 void tegra_dc_sor_disable_win_short_raster(struct dc_ctlr *disp_ctrl,
                                           int *dc_reg_ctx);
@@ -918,5 +911,5 @@ int tegra_dc_sor_general_act(struct dc_ctlr *disp_ctrl);
 void tegra_dc_sor_restore_win_and_raster(struct dc_ctlr *disp_ctrl,
                                         int *dc_reg_ctx);
 
-int tegra_dc_sor_init(struct tegra_dc_sor_data **sorp);
+int tegra_dc_sor_init(struct udevice **sorp);
 #endif
index 176f6e902b3b3f911eaa225da9bf7a509536eef3..eb00f2e8da0ad836b4fdfaf4fd8eb8ea4db81f43 100644 (file)
 #define CONFIG_ENV_OFFSET              (-CONFIG_ENV_SIZE)
 
 /* LCD support */
-#define CONFIG_LCD
 #define CONFIG_PWM_TEGRA
 #define CONFIG_AS3722_POWER
-#define LCD_BPP                                LCD_COLOR16
 #define CONFIG_SYS_WHITE_ON_BLACK
 #define CONFIG_CMD_BMP
 
index d1c29a8a5d86b2913770e776d8d2955470467cc2..4caf3b6cbda229f71a8a222d9691fee5c8e4bd78 100644 (file)
@@ -120,7 +120,6 @@ enum fdt_compat_id {
        COMPAT_NVIDIA_TEGRA20_EMC_TABLE, /* Tegra20 memory timing table */
        COMPAT_NVIDIA_TEGRA20_NAND,     /* Tegra2 NAND controller */
        COMPAT_NVIDIA_TEGRA20_PWM,      /* Tegra 2 PWM controller */
-       COMPAT_NVIDIA_TEGRA124_DC,      /* Tegra 124 Display controller */
        COMPAT_NVIDIA_TEGRA124_SOR,     /* Tegra 124 Serial Output Resource */
        COMPAT_NVIDIA_TEGRA124_PMC,     /* Tegra 124 power mgmt controller */
        COMPAT_NVIDIA_TEGRA20_DC,       /* Tegra 2 Display controller */
index 1b1ca02e69e7c4de6bafdde14e04b5198d352620..b361a2579f107810a848f9f6d5cff5ebe0d73535 100644 (file)
@@ -27,7 +27,6 @@ static const char * const compat_names[COMPAT_COUNT] = {
        COMPAT(NVIDIA_TEGRA20_EMC_TABLE, "nvidia,tegra20-emc-table"),
        COMPAT(NVIDIA_TEGRA20_NAND, "nvidia,tegra20-nand"),
        COMPAT(NVIDIA_TEGRA20_PWM, "nvidia,tegra20-pwm"),
-       COMPAT(NVIDIA_TEGRA124_DC, "nvidia,tegra124-dc"),
        COMPAT(NVIDIA_TEGRA124_SOR, "nvidia,tegra124-sor"),
        COMPAT(NVIDIA_TEGRA124_PMC, "nvidia,tegra124-pmc"),
        COMPAT(NVIDIA_TEGRA20_DC, "nvidia,tegra20-dc"),