Example alternate mode driver. Meant only to give an idea how a real alternate mode driver *could* look like! Signed-off-by: Heikki Krogerus <heikki.krogerus@xxxxxxxxxxxxxxx> --- drivers/usb/typec/Kconfig | 2 + drivers/usb/typec/Makefile | 1 + drivers/usb/typec/altmodes/Kconfig | 9 +++ drivers/usb/typec/altmodes/Makefile | 2 + drivers/usb/typec/altmodes/dummy.c | 133 ++++++++++++++++++++++++++++++++++++ 5 files changed, 147 insertions(+) create mode 100644 drivers/usb/typec/altmodes/Kconfig create mode 100644 drivers/usb/typec/altmodes/Makefile create mode 100644 drivers/usb/typec/altmodes/dummy.c diff --git a/drivers/usb/typec/Kconfig b/drivers/usb/typec/Kconfig index 103cb8bce3e7..c7b3414125ca 100644 --- a/drivers/usb/typec/Kconfig +++ b/drivers/usb/typec/Kconfig @@ -35,4 +35,6 @@ endif source "drivers/usb/typec/ucsi/Kconfig" +source "drivers/usb/typec/altmodes/Kconfig" + endmenu diff --git a/drivers/usb/typec/Makefile b/drivers/usb/typec/Makefile index e157cc4526f0..bb98657d4927 100644 --- a/drivers/usb/typec/Makefile +++ b/drivers/usb/typec/Makefile @@ -5,3 +5,4 @@ obj-$(CONFIG_TYPEC_TCPM) += tcpm.o obj-y += fusb302/ obj-$(CONFIG_TYPEC_WCOVE) += typec_wcove.o obj-$(CONFIG_TYPEC_UCSI) += ucsi/ +obj-y += altmodes/ diff --git a/drivers/usb/typec/altmodes/Kconfig b/drivers/usb/typec/altmodes/Kconfig new file mode 100644 index 000000000000..6d25ad369745 --- /dev/null +++ b/drivers/usb/typec/altmodes/Kconfig @@ -0,0 +1,9 @@ + +menu "USB Type-C Alternate Mode drivers" + +config TYPEC_DUMMY_ALTMODE + tristate "Dummy Alternate Mode driver" + help + Driver for Dummy Alternate Mode. + +endmenu diff --git a/drivers/usb/typec/altmodes/Makefile b/drivers/usb/typec/altmodes/Makefile new file mode 100644 index 000000000000..a71e62b0acf5 --- /dev/null +++ b/drivers/usb/typec/altmodes/Makefile @@ -0,0 +1,2 @@ +obj-$(CONFIG_TYPEC_DUMMY_ALTMODE) += dummy_altmode.o +dummy_altmode-y := dummy.o diff --git a/drivers/usb/typec/altmodes/dummy.c b/drivers/usb/typec/altmodes/dummy.c new file mode 100644 index 000000000000..6225cc955726 --- /dev/null +++ b/drivers/usb/typec/altmodes/dummy.c @@ -0,0 +1,133 @@ +/** + * USB Typec-C DisplayPort Alternate Mode driver + * + * Copyright (C) 2017 Intel Corporation + * Author: Heikki Krogerus <heikki.krogerus@xxxxxxxxxxxxxxx> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +/* This is an example of an USB Type-C alternate mode driver. */ + +#include <linux/module.h> +#include <linux/usb/pd_vdo.h> +#include <linux/usb/typec_altmode.h> + +#define DUMMY_SVID 0xffff + +/* Dummy vendor specific commands */ +#define CMD_DUMMY1 VDO_CMD_VENDOR(1) +#define CMD_DUMMY2 VDO_CMD_VENDOR(2) + +/* Dummy pin configurations */ +enum { + DUMMY_CONF_USB, + DUMMY_CONF_A, + DUMMY_CONF_B, +}; + +static void dummy_attention(struct typec_altmode *altmode, + u32 header, u32 *vdo, int count) +{ + /* Process attention.. */ +} + +static void dummy_altmode_vdm(struct typec_altmode *altmode, + u32 header, u32 *vdo, int count) +{ + int cmd_type = PD_VDO_CMDT(header); + int cmd = PD_VDO_CMD(header); + u32 message[2]; + + switch (cmd_type) { + case CMDT_INIT: + /* Dummy altmode driver supports currently only DFP */ + + if (cmd == CMD_ATTENTION) + dummy_attention(altmode, header, vdo, count); + break; + case CMDT_RSP_ACK: + switch (cmd) { + case CMD_DISCOVER_MODES: + /* We could store the modes here. */ + break; + case CMD_ENTER_MODE: + /* Prepare the platform for pin configuration A */ + if (typec_altmode_notify(altmode, DUMMY_CONF_A, NULL)) { + /* Exit Mode? */ + break; + } + + /* Queue dummy1 command for pin configuration A */ + message[0] = VDO(DUMMY_SVID, 1, CMD_DUMMY1); + message[1] = 0x12345678 | DUMMY_CONF_A; + typec_altmode_send_vdm(altmode, message[0], + &message[1], 2); + + break; + case CMD_EXIT_MODE: + /* + * Tell the the platform to put the port to go back to + * USB mode + */ + typec_altmode_notify(altmode, DUMMY_CONF_USB, NULL); + + break; + case CMD_DUMMY1: + /* We are happy */ + break; + default: + break; + } + break; + case CMDT_RSP_NAK: + switch (cmd) { + case CMD_DUMMY1: + /* Port back to USB mode */ + typec_altmode_notify(altmode, DUMMY_CONF_USB, NULL); + + /* Exit Mode? */ + + break; + default: + break; + } + break; + default: + break; + } +} + +static int dummy_altmode_notify(struct typec_altmode *altmode, + unsigned long conf, void *data) +{ +} + +static struct typec_altmode_ops dummy_altmode_ops = { + .vdm = dummy_altmode_vdm, + .notify = dummy_altmode_notify, +}; + +static int dummy_altmode_probe(struct typec_altmode *alt) +{ + typec_altmode_register_ops(alt, &dummy_altmode_ops); + + return 0; +} + +static struct typec_altmode_driver dummy_altmode_driver = { + .svid = DUMMY_SVID, + .probe = dummy_altmode_probe, + .driver = { + .name = "dummy_altmode", + .owner = THIS_MODULE, + }, +}; + +module_typec_altmode_driver(dummy_altmode_driver); + +MODULE_AUTHOR("Heikki Krogerus <heikki.krogerus@xxxxxxxxxxxxxxx>"); +MODULE_LICENSE("GPL v2"); +MODULE_DESCRIPTION("DisplayPort Alternate Mode"); -- 2.14.1 -- To unsubscribe from this list: send the line "unsubscribe linux-usb" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html