usb: typec: Add driver for NVIDIA Alt Modes
authorAjay Gupta <ajayg@nvidia.com>
Tue, 23 Apr 2019 14:21:51 +0000 (17:21 +0300)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 25 Apr 2019 09:04:56 +0000 (11:04 +0200)
Latest NVIDIA GPUs support VirtualLink device. Since USBIF
has not assigned a Standard ID (SID) for VirtualLink
so using NVIDA VID 0x955 as SVID.

Signed-off-by: Ajay Gupta <ajayg@nvidia.com>
Signed-off-by: Heikki Krogerus <heikki.krogerus@linux.intel.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/usb/typec/altmodes/Kconfig
drivers/usb/typec/altmodes/Makefile
drivers/usb/typec/altmodes/nvidia.c [new file with mode: 0644]
drivers/usb/typec/ucsi/ucsi.c
include/linux/usb/typec_dp.h

index ef2226e..187690f 100644 (file)
@@ -12,4 +12,14 @@ config TYPEC_DP_ALTMODE
          To compile this driver as a module, choose M here: the
          module will be called typec_displayport.
 
+config TYPEC_NVIDIA_ALTMODE
+       tristate "NVIDIA Alternate Mode driver"
+       depends on TYPEC_DP_ALTMODE
+       help
+         Latest NVIDIA GPUs support VirtualLink devices. Select this
+         to enable support for VirtualLink devices with NVIDIA GPUs.
+
+         To compile this driver as a module, choose M here: the
+         module will be called typec_displayport.
+
 endmenu
index eda8456..4571754 100644 (file)
@@ -2,3 +2,5 @@
 
 obj-$(CONFIG_TYPEC_DP_ALTMODE)         += typec_displayport.o
 typec_displayport-y                    := displayport.o
+obj-$(CONFIG_TYPEC_NVIDIA_ALTMODE)     += typec_nvidia.o
+typec_nvidia-y                         := nvidia.o
diff --git a/drivers/usb/typec/altmodes/nvidia.c b/drivers/usb/typec/altmodes/nvidia.c
new file mode 100644 (file)
index 0000000..c367697
--- /dev/null
@@ -0,0 +1,44 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2019 NVIDIA Corporation. All rights reserved.
+ *
+ * NVIDIA USB Type-C Alt Mode Driver
+ */
+#include <linux/module.h>
+#include <linux/usb/typec_altmode.h>
+#include <linux/usb/typec_dp.h>
+#include "displayport.h"
+
+static int nvidia_altmode_probe(struct typec_altmode *alt)
+{
+       if (alt->svid == USB_TYPEC_NVIDIA_VLINK_SID)
+               return dp_altmode_probe(alt);
+       else
+               return -ENOTSUPP;
+}
+
+static void nvidia_altmode_remove(struct typec_altmode *alt)
+{
+       if (alt->svid == USB_TYPEC_NVIDIA_VLINK_SID)
+               dp_altmode_remove(alt);
+}
+
+static const struct typec_device_id nvidia_typec_id[] = {
+       { USB_TYPEC_NVIDIA_VLINK_SID, TYPEC_ANY_MODE },
+       { },
+};
+MODULE_DEVICE_TABLE(typec, nvidia_typec_id);
+
+static struct typec_altmode_driver nvidia_altmode_driver = {
+       .id_table = nvidia_typec_id,
+       .probe = nvidia_altmode_probe,
+       .remove = nvidia_altmode_remove,
+       .driver = {
+               .name = "typec_nvidia",
+               .owner = THIS_MODULE,
+       },
+};
+module_typec_altmode_driver(nvidia_altmode_driver);
+
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("NVIDIA USB Type-C Alt Mode Driver");
index b4fb2e0..7850b85 100644 (file)
@@ -283,6 +283,7 @@ static int ucsi_register_altmode(struct ucsi_connector *con,
 
                switch (desc->svid) {
                case USB_TYPEC_DP_SID:
+               case USB_TYPEC_NVIDIA_VLINK_SID:
                        alt = ucsi_register_displayport(con, override, i, desc);
                        break;
                default:
@@ -404,7 +405,8 @@ static void ucsi_unregister_altmodes(struct ucsi_connector *con, u8 recipient)
 
        while (adev[i]) {
                if (recipient == UCSI_RECIPIENT_SOP &&
-                   adev[i]->svid == USB_TYPEC_DP_SID) {
+                   (adev[i]->svid == USB_TYPEC_DP_SID ||
+                       adev[i]->svid == USB_TYPEC_NVIDIA_VLINK_SID)) {
                        pdev = typec_altmode_get_partner(adev[i]);
                        ucsi_displayport_remove_partner((void *)pdev);
                }
index 7fa12ef..fc4c7ed 100644 (file)
@@ -5,6 +5,11 @@
 #include <linux/usb/typec_altmode.h>
 
 #define USB_TYPEC_DP_SID       0xff01
+/* USB IF has not assigned a Standard ID (SID) for VirtualLink,
+ * so the manufacturers of VirtualLink adapters use their Vendor
+ * IDs as the SVID.
+ */
+#define USB_TYPEC_NVIDIA_VLINK_SID     0x955   /* NVIDIA VirtualLink */
 #define USB_TYPEC_DP_MODE      1
 
 /*