]> git.kernelconcepts.de Git - karo-tx-uboot.git/commitdiff
dm: video: Add support for video bridges
authorSimon Glass <sjg@chromium.org>
Fri, 3 Jul 2015 00:16:08 +0000 (18:16 -0600)
committerLothar Waßmann <LW@KARO-electronics.de>
Thu, 10 Sep 2015 06:17:15 +0000 (08:17 +0200)
A video bridge typically converts video from one format to another, e.g.
DisplayPort to LVDS. Add driver model support for these with a simple
interface to control activation and backlight. The uclass supports GPIO
control of power and reset lines.

Signed-off-by: Simon Glass <sjg@chromium.org>
drivers/video/Kconfig
drivers/video/Makefile
drivers/video/bridge/Kconfig [new file with mode: 0644]
drivers/video/bridge/Makefile [new file with mode: 0644]
drivers/video/bridge/video-bridge-uclass.c [new file with mode: 0644]
include/dm/uclass-id.h
include/video_bridge.h [new file with mode: 0644]

index 9ae23e8dd04742c64d76367d3cf2fd5e79228634..3244cd7eddba19fca48f61902d4c916248b67fef 100644 (file)
@@ -240,3 +240,5 @@ config VIDEO_TEGRA124
           HDMI. At present only eDP is supported by U-Boot. This option
           enables this support which can be used on devices which
           have an eDP display connected.
+
+source "drivers/video/bridge/Kconfig"
index 2ead7f192c56860976632a33ed37d2bc8024aaf9..599fe83b33ae82948577c59412f16081395b1fa3 100644 (file)
@@ -54,3 +54,5 @@ obj-$(CONFIG_AM335X_LCD) += am335x-fb.o
 obj-$(CONFIG_VIDEO_PARADE) += parade.o
 
 obj-${CONFIG_VIDEO_TEGRA124} += tegra124/
+
+obj-y += bridge/
diff --git a/drivers/video/bridge/Kconfig b/drivers/video/bridge/Kconfig
new file mode 100644 (file)
index 0000000..7ba6b17
--- /dev/null
@@ -0,0 +1,8 @@
+config VIDEO_BRIDGE
+       bool "Support video bridges"
+       depends on DM
+       help
+         Some platforms use video bridges to convert from one output to
+         another. For example, where the SoC only supports eDP and the LCD
+         requires LVDS, an eDP->LVDS bridge chip can be used to provide the
+         necessary conversion. This option enables support for these devices.
diff --git a/drivers/video/bridge/Makefile b/drivers/video/bridge/Makefile
new file mode 100644 (file)
index 0000000..f4bf087
--- /dev/null
@@ -0,0 +1,7 @@
+#
+#  Copyright (C) 2015 Google, Inc
+#  Written by Simon Glass <sjg@chromium.org>
+#
+#  SPDX-License-Identifier:    GPL-2.0+
+
+obj-$(CONFIG_VIDEO_BRIDGE) += video-bridge-uclass.o
diff --git a/drivers/video/bridge/video-bridge-uclass.c b/drivers/video/bridge/video-bridge-uclass.c
new file mode 100644 (file)
index 0000000..e1ea428
--- /dev/null
@@ -0,0 +1,111 @@
+/*
+ * Copyright (C) 2015 Google, Inc
+ * Written by Simon Glass <sjg@chromium.org>
+ *
+ * SPDX-License-Identifier:    GPL-2.0+
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <errno.h>
+#include <video_bridge.h>
+
+int video_bridge_set_backlight(struct udevice *dev, int percent)
+{
+       struct video_bridge_ops *ops = video_bridge_get_ops(dev);
+
+       if (!ops->set_backlight)
+               return -ENOSYS;
+
+       return ops->set_backlight(dev, percent);
+}
+
+int video_bridge_attach(struct udevice *dev)
+{
+       struct video_bridge_ops *ops = video_bridge_get_ops(dev);
+
+       if (!ops->attach)
+               return -ENOSYS;
+
+       return ops->attach(dev);
+}
+
+int video_bridge_check_attached(struct udevice *dev)
+{
+       struct video_bridge_priv *uc_priv = dev_get_uclass_priv(dev);
+       struct video_bridge_ops *ops = video_bridge_get_ops(dev);
+       int ret;
+
+       if (!ops->check_attached) {
+               ret = dm_gpio_get_value(&uc_priv->hotplug);
+
+               return ret > 0 ? 0 : ret == 0 ? -ENOTCONN : ret;
+       }
+
+       return ops->check_attached(dev);
+}
+
+static int video_bridge_pre_probe(struct udevice *dev)
+{
+       struct video_bridge_priv *uc_priv = dev_get_uclass_priv(dev);
+       int ret;
+
+       debug("%s\n", __func__);
+       ret = gpio_request_by_name(dev, "sleep-gpios", 0,
+                                  &uc_priv->sleep, GPIOD_IS_OUT);
+       if (ret) {
+               debug("%s: Could not decode sleep-gpios (%d)\n", __func__, ret);
+               return ret;
+       }
+       ret = dm_gpio_set_pull(&uc_priv->sleep, GPIO_PULL_NONE);
+       if (ret) {
+               debug("%s: Could not set sleep pull value\n", __func__);
+               return ret;
+       }
+       ret = gpio_request_by_name(dev, "reset-gpios", 0, &uc_priv->reset,
+                                  GPIOD_IS_OUT);
+       if (ret) {
+               debug("%s: Could not decode reset-gpios (%d)\n", __func__, ret);
+               return ret;
+       }
+       ret = dm_gpio_set_pull(&uc_priv->reset, GPIO_PULL_NONE);
+       if (ret) {
+               debug("%s: Could not set reset pull value\n", __func__);
+               return ret;
+       }
+       ret = gpio_request_by_name(dev, "hotplug-gpios", 0, &uc_priv->hotplug,
+                                  GPIOD_IS_IN);
+       if (ret && ret != -ENOENT) {
+               debug("%s: Could not decode hotplug (%d)\n", __func__, ret);
+               return ret;
+       }
+
+       return 0;
+}
+
+int video_bridge_set_active(struct udevice *dev, bool active)
+{
+       struct video_bridge_priv *uc_priv = dev_get_uclass_priv(dev);
+       int ret;
+
+       debug("%s: %d\n", __func__, active);
+       ret = dm_gpio_set_value(&uc_priv->sleep, !active);
+       if (ret)
+               return ret;
+       if (active) {
+               ret = dm_gpio_set_value(&uc_priv->reset, true);
+               if (ret)
+                       return ret;
+               udelay(10);
+               ret = dm_gpio_set_value(&uc_priv->reset, false);
+       }
+
+       return ret;
+}
+
+UCLASS_DRIVER(video_bridge) = {
+       .id             = UCLASS_VIDEO_BRIDGE,
+       .name           = "video_bridge",
+       .per_device_auto_alloc_size     = sizeof(struct video_bridge_priv),
+       .pre_probe      = video_bridge_pre_probe,
+};
index 777b101842dd7e5fb9e7745e34f28f12014fc899..c744044bb8aa5f80718a4926c9dc7952996e4b43 100644 (file)
@@ -57,6 +57,7 @@ enum uclass_id {
        UCLASS_USB,             /* USB bus */
        UCLASS_USB_DEV_GENERIC, /* USB generic device */
        UCLASS_USB_HUB,         /* USB hub */
+       UCLASS_VIDEO_BRIDGE,    /* Video bridge, e.g. DisplayPort to LVDS */
 
        UCLASS_COUNT,
        UCLASS_INVALID = -1,
diff --git a/include/video_bridge.h b/include/video_bridge.h
new file mode 100644 (file)
index 0000000..c7b8681
--- /dev/null
@@ -0,0 +1,92 @@
+/*
+ * Copyright (C) 2015 Google, Inc
+ * Written by Simon Glass <sjg@chromium.org>
+ *
+ * SPDX-License-Identifier:    GPL-2.0+
+ */
+
+#ifndef __VIDEO_BRIDGE
+#define __VIDEO_BRIDGE
+
+#include <asm/gpio.h>
+
+/**
+ * struct video_bridge_priv - uclass information for video bridges
+ *
+ * @sleep:     GPIO to assert to power down the bridge
+ * @reset:     GPIO to assert to reset the bridge
+ * @hotplug:   Optional GPIO to check if bridge is connected
+ */
+struct video_bridge_priv {
+       struct gpio_desc sleep;
+       struct gpio_desc reset;
+       struct gpio_desc hotplug;
+};
+
+/**
+ * Operations for video bridges
+ */
+struct video_bridge_ops {
+       /**
+        * attach() - attach a video bridge
+        *
+        * @return 0 if OK, -ve on error
+        */
+       int (*attach)(struct udevice *dev);
+
+       /**
+        * check_attached() - check if a bridge is correctly attached
+        *
+        * This method is optional - if not provided then the hotplug GPIO
+        * will be checked instead.
+        *
+        * @dev:        Device to check
+        * @return 0 if attached, -EENOTCONN if not, or other -ve error
+        */
+       int (*check_attached)(struct udevice *dev);
+
+       /**
+        * set_backlight() - Set the backlight brightness
+        *
+        * @dev:        device to adjust
+        * @percent:    brightness percentage (0=off, 100=full brightness)
+        * @return 0 if OK, -ve on error
+        */
+       int (*set_backlight)(struct udevice *dev, int percent);
+};
+
+#define video_bridge_get_ops(dev) \
+               ((struct video_bridge_ops *)(dev)->driver->ops)
+
+/**
+ * video_bridge_attach() - attach a video bridge
+ *
+ * @return 0 if OK, -ve on error
+ */
+int video_bridge_attach(struct udevice *dev);
+
+/**
+ * video_bridge_set_backlight() - Set the backlight brightness
+ *
+ * @percent:   brightness percentage (0=off, 100=full brightness)
+ * @return 0 if OK, -ve on error
+ */
+int video_bridge_set_backlight(struct udevice *dev, int percent);
+
+/**
+ * video_bridge_set_active() - take the bridge in/out of reset/powerdown
+ *
+ * @dev:       Device to adjust
+ * @active:    true to power up and reset, false to power down
+ */
+int video_bridge_set_active(struct udevice *dev, bool active);
+
+/**
+ * check_attached() - check if a bridge is correctly attached
+ *
+ * @dev:       Device to check
+ * @return 0 if attached, -EENOTCONN if not, or other -ve error
+ */
+int video_bridge_check_attached(struct udevice *dev);
+
+#endif