Message ID | 20210503154647.142551-9-hdegoede@redhat.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | drm + usb-type-c: Add support for out-of-band hotplug notification (v2) | expand |
Hi Hans, On Mon, May 03, 2021 at 05:46:46PM +0200, Hans de Goede wrote: > Use the new drm_connector_find_by_fwnode() and > drm_connector_oob_hotplug_event() functions to let drm/kms drivers > know about DisplayPort over Type-C hotplug events. > > Signed-off-by: Hans de Goede <hdegoede@redhat.com> > --- > Changes in v2: > - Add missing depends on DRM to TYPEC_DP_ALTMODE Kconfig entry > --- > drivers/usb/typec/altmodes/Kconfig | 1 + > drivers/usb/typec/altmodes/displayport.c | 40 +++++++++++++++++++++++- > 2 files changed, 40 insertions(+), 1 deletion(-) > > diff --git a/drivers/usb/typec/altmodes/Kconfig b/drivers/usb/typec/altmodes/Kconfig > index 60d375e9c3c7..1a6b5e872b0d 100644 > --- a/drivers/usb/typec/altmodes/Kconfig > +++ b/drivers/usb/typec/altmodes/Kconfig > @@ -4,6 +4,7 @@ menu "USB Type-C Alternate Mode drivers" > > config TYPEC_DP_ALTMODE > tristate "DisplayPort Alternate Mode driver" > + depends on DRM > help > DisplayPort USB Type-C Alternate Mode allows DisplayPort > displays and adapters to be attached to the USB Type-C > diff --git a/drivers/usb/typec/altmodes/displayport.c b/drivers/usb/typec/altmodes/displayport.c > index aa669b9cf70e..f00dfc5c14b6 100644 > --- a/drivers/usb/typec/altmodes/displayport.c > +++ b/drivers/usb/typec/altmodes/displayport.c > @@ -11,8 +11,10 @@ > #include <linux/delay.h> > #include <linux/mutex.h> > #include <linux/module.h> > +#include <linux/property.h> > #include <linux/usb/pd_vdo.h> > #include <linux/usb/typec_dp.h> > +#include <drm/drm_connector.h> > #include "displayport.h" > > #define DP_HEADER(_dp, ver, cmd) (VDO((_dp)->alt->svid, 1, ver, cmd) \ > @@ -62,12 +64,30 @@ struct dp_altmode { > struct work_struct work; > struct typec_altmode *alt; > const struct typec_altmode *port; > + struct fwnode_handle *connector_fwnode; > }; > > +static void dp_altmode_notify_connector(struct dp_altmode *dp) > +{ > + struct drm_connector_oob_hotplug_event_data data = { }; > + u8 pin_assign = DP_CONF_GET_PIN_ASSIGN(dp->data.conf); > + > + data.connected = dp->data.status & DP_STATUS_HPD_STATE; > + data.orientation = typec_altmode_get_orientation(dp->alt); > + > + if (pin_assign & DP_PIN_ASSIGN_DP_ONLY_MASK) > + data.dp_lanes = 4; > + else if (pin_assign & DP_PIN_ASSIGN_MULTI_FUNC_MASK) > + data.dp_lanes = 2; > + > + drm_connector_oob_hotplug_event(dp->connector_fwnode, &data); > +} > + > static int dp_altmode_notify(struct dp_altmode *dp) > { > unsigned long conf; > u8 state; > + int ret; > > if (dp->data.conf) { > state = get_count_order(DP_CONF_GET_PIN_ASSIGN(dp->data.conf)); > @@ -76,7 +96,12 @@ static int dp_altmode_notify(struct dp_altmode *dp) > conf = TYPEC_STATE_USB; > } > > - return typec_altmode_notify(dp->alt, conf, &dp->data); > + ret = typec_altmode_notify(dp->alt, conf, &dp->data); > + if (ret) > + return ret; > + > + dp_altmode_notify_connector(dp); That is now going to be always called after configuration, right? The HPD is not necessarily issued at that point. I think that should be called from dp_altmode_status_update(), and probable only if there really is HPD IRQ or HPD State changes... I think? > + return 0; > } thanks,
Hi Heikki, On 5/5/21 12:17 PM, Heikki Krogerus wrote: > Hi Hans, > > On Mon, May 03, 2021 at 05:46:46PM +0200, Hans de Goede wrote: >> Use the new drm_connector_find_by_fwnode() and >> drm_connector_oob_hotplug_event() functions to let drm/kms drivers >> know about DisplayPort over Type-C hotplug events. >> >> Signed-off-by: Hans de Goede <hdegoede@redhat.com> >> --- >> Changes in v2: >> - Add missing depends on DRM to TYPEC_DP_ALTMODE Kconfig entry >> --- >> drivers/usb/typec/altmodes/Kconfig | 1 + >> drivers/usb/typec/altmodes/displayport.c | 40 +++++++++++++++++++++++- >> 2 files changed, 40 insertions(+), 1 deletion(-) >> >> diff --git a/drivers/usb/typec/altmodes/Kconfig b/drivers/usb/typec/altmodes/Kconfig >> index 60d375e9c3c7..1a6b5e872b0d 100644 >> --- a/drivers/usb/typec/altmodes/Kconfig >> +++ b/drivers/usb/typec/altmodes/Kconfig >> @@ -4,6 +4,7 @@ menu "USB Type-C Alternate Mode drivers" >> >> config TYPEC_DP_ALTMODE >> tristate "DisplayPort Alternate Mode driver" >> + depends on DRM >> help >> DisplayPort USB Type-C Alternate Mode allows DisplayPort >> displays and adapters to be attached to the USB Type-C >> diff --git a/drivers/usb/typec/altmodes/displayport.c b/drivers/usb/typec/altmodes/displayport.c >> index aa669b9cf70e..f00dfc5c14b6 100644 >> --- a/drivers/usb/typec/altmodes/displayport.c >> +++ b/drivers/usb/typec/altmodes/displayport.c >> @@ -11,8 +11,10 @@ >> #include <linux/delay.h> >> #include <linux/mutex.h> >> #include <linux/module.h> >> +#include <linux/property.h> >> #include <linux/usb/pd_vdo.h> >> #include <linux/usb/typec_dp.h> >> +#include <drm/drm_connector.h> >> #include "displayport.h" >> >> #define DP_HEADER(_dp, ver, cmd) (VDO((_dp)->alt->svid, 1, ver, cmd) \ >> @@ -62,12 +64,30 @@ struct dp_altmode { >> struct work_struct work; >> struct typec_altmode *alt; >> const struct typec_altmode *port; >> + struct fwnode_handle *connector_fwnode; >> }; >> >> +static void dp_altmode_notify_connector(struct dp_altmode *dp) >> +{ >> + struct drm_connector_oob_hotplug_event_data data = { }; >> + u8 pin_assign = DP_CONF_GET_PIN_ASSIGN(dp->data.conf); >> + >> + data.connected = dp->data.status & DP_STATUS_HPD_STATE; >> + data.orientation = typec_altmode_get_orientation(dp->alt); >> + >> + if (pin_assign & DP_PIN_ASSIGN_DP_ONLY_MASK) >> + data.dp_lanes = 4; >> + else if (pin_assign & DP_PIN_ASSIGN_MULTI_FUNC_MASK) >> + data.dp_lanes = 2; >> + >> + drm_connector_oob_hotplug_event(dp->connector_fwnode, &data); >> +} >> + >> static int dp_altmode_notify(struct dp_altmode *dp) >> { >> unsigned long conf; >> u8 state; >> + int ret; >> >> if (dp->data.conf) { >> state = get_count_order(DP_CONF_GET_PIN_ASSIGN(dp->data.conf)); >> @@ -76,7 +96,12 @@ static int dp_altmode_notify(struct dp_altmode *dp) >> conf = TYPEC_STATE_USB; >> } >> >> - return typec_altmode_notify(dp->alt, conf, &dp->data); >> + ret = typec_altmode_notify(dp->alt, conf, &dp->data); >> + if (ret) >> + return ret; >> + >> + dp_altmode_notify_connector(dp); > > That is now going to be always called after configuration, right? The > HPD is not necessarily issued at that point. > > I think that should be called from dp_altmode_status_update(), and > probable only if there really is HPD IRQ or HPD State changes... I > think? I did see this triggering a bit more often then necessary on the initial plugin of a DP-altmode capable Type-C "dongle", so what you are suggesting makes sense. I'll come up with a better approach for the next version. Regards, Hans
diff --git a/drivers/usb/typec/altmodes/Kconfig b/drivers/usb/typec/altmodes/Kconfig index 60d375e9c3c7..1a6b5e872b0d 100644 --- a/drivers/usb/typec/altmodes/Kconfig +++ b/drivers/usb/typec/altmodes/Kconfig @@ -4,6 +4,7 @@ menu "USB Type-C Alternate Mode drivers" config TYPEC_DP_ALTMODE tristate "DisplayPort Alternate Mode driver" + depends on DRM help DisplayPort USB Type-C Alternate Mode allows DisplayPort displays and adapters to be attached to the USB Type-C diff --git a/drivers/usb/typec/altmodes/displayport.c b/drivers/usb/typec/altmodes/displayport.c index aa669b9cf70e..f00dfc5c14b6 100644 --- a/drivers/usb/typec/altmodes/displayport.c +++ b/drivers/usb/typec/altmodes/displayport.c @@ -11,8 +11,10 @@ #include <linux/delay.h> #include <linux/mutex.h> #include <linux/module.h> +#include <linux/property.h> #include <linux/usb/pd_vdo.h> #include <linux/usb/typec_dp.h> +#include <drm/drm_connector.h> #include "displayport.h" #define DP_HEADER(_dp, ver, cmd) (VDO((_dp)->alt->svid, 1, ver, cmd) \ @@ -62,12 +64,30 @@ struct dp_altmode { struct work_struct work; struct typec_altmode *alt; const struct typec_altmode *port; + struct fwnode_handle *connector_fwnode; }; +static void dp_altmode_notify_connector(struct dp_altmode *dp) +{ + struct drm_connector_oob_hotplug_event_data data = { }; + u8 pin_assign = DP_CONF_GET_PIN_ASSIGN(dp->data.conf); + + data.connected = dp->data.status & DP_STATUS_HPD_STATE; + data.orientation = typec_altmode_get_orientation(dp->alt); + + if (pin_assign & DP_PIN_ASSIGN_DP_ONLY_MASK) + data.dp_lanes = 4; + else if (pin_assign & DP_PIN_ASSIGN_MULTI_FUNC_MASK) + data.dp_lanes = 2; + + drm_connector_oob_hotplug_event(dp->connector_fwnode, &data); +} + static int dp_altmode_notify(struct dp_altmode *dp) { unsigned long conf; u8 state; + int ret; if (dp->data.conf) { state = get_count_order(DP_CONF_GET_PIN_ASSIGN(dp->data.conf)); @@ -76,7 +96,12 @@ static int dp_altmode_notify(struct dp_altmode *dp) conf = TYPEC_STATE_USB; } - return typec_altmode_notify(dp->alt, conf, &dp->data); + ret = typec_altmode_notify(dp->alt, conf, &dp->data); + if (ret) + return ret; + + dp_altmode_notify_connector(dp); + return 0; } static int dp_altmode_configure(struct dp_altmode *dp, u8 con) @@ -512,6 +537,7 @@ static const struct attribute_group dp_altmode_group = { int dp_altmode_probe(struct typec_altmode *alt) { const struct typec_altmode *port = typec_altmode_get_partner(alt); + struct fwnode_handle *fwnode; struct dp_altmode *dp; int ret; @@ -540,6 +566,11 @@ int dp_altmode_probe(struct typec_altmode *alt) alt->desc = "DisplayPort"; alt->ops = &dp_altmode_ops; + fwnode = dev_fwnode(alt->dev.parent->parent); /* typec_port fwnode */ + dp->connector_fwnode = fwnode_find_reference(fwnode, "displayport", 0); + if (IS_ERR(dp->connector_fwnode)) + dp->connector_fwnode = NULL; + typec_altmode_set_drvdata(alt, dp); dp->state = DP_STATE_ENTER; @@ -555,6 +586,13 @@ void dp_altmode_remove(struct typec_altmode *alt) sysfs_remove_group(&alt->dev.kobj, &dp_altmode_group); cancel_work_sync(&dp->work); + + if (dp->connector_fwnode) { + dp->data.conf = 0; + dp->data.status = 0; + dp_altmode_notify_connector(dp); + fwnode_handle_put(dp->connector_fwnode); + } } EXPORT_SYMBOL_GPL(dp_altmode_remove);
Use the new drm_connector_find_by_fwnode() and drm_connector_oob_hotplug_event() functions to let drm/kms drivers know about DisplayPort over Type-C hotplug events. Signed-off-by: Hans de Goede <hdegoede@redhat.com> --- Changes in v2: - Add missing depends on DRM to TYPEC_DP_ALTMODE Kconfig entry --- drivers/usb/typec/altmodes/Kconfig | 1 + drivers/usb/typec/altmodes/displayport.c | 40 +++++++++++++++++++++++- 2 files changed, 40 insertions(+), 1 deletion(-)