Re: [PATCH] drm/vbox: Convert to Linux IRQ interfaces
Hi, On 7/6/21 9:50 AM, Thomas Zimmermann wrote: > Drop the DRM IRQ midlayer in favor of Linux IRQ interfaces. DRM's > IRQ helpers are mostly useful for UMS drivers. Modern KMS drivers > don't benefit from using it. > > Signed-off-by: Thomas Zimmermann Thanks, patch looks good to me: Reviewed-by: Hans de Goede And to make sure things don't regress I've also given this a test spin: Tested-by: Hans de Goede Note I assume that you will push this out do drmi-misc yourself (if you've not done so already given that this patch is somewhat old). Regards, Hans > --- > drivers/gpu/drm/vboxvideo/vbox_drv.c | 1 - > drivers/gpu/drm/vboxvideo/vbox_drv.h | 1 - > drivers/gpu/drm/vboxvideo/vbox_irq.c | 16 +++- > 3 files changed, 11 insertions(+), 7 deletions(-) > > diff --git a/drivers/gpu/drm/vboxvideo/vbox_drv.c > b/drivers/gpu/drm/vboxvideo/vbox_drv.c > index 879a2445cc44..2b81cb259d23 100644 > --- a/drivers/gpu/drm/vboxvideo/vbox_drv.c > +++ b/drivers/gpu/drm/vboxvideo/vbox_drv.c > @@ -184,7 +184,6 @@ static const struct drm_driver driver = { > .lastclose = drm_fb_helper_lastclose, > > .fops = &vbox_fops, > - .irq_handler = vbox_irq_handler, > .name = DRIVER_NAME, > .desc = DRIVER_DESC, > .date = DRIVER_DATE, > diff --git a/drivers/gpu/drm/vboxvideo/vbox_drv.h > b/drivers/gpu/drm/vboxvideo/vbox_drv.h > index ac7c2effc46f..4903b91d7fe4 100644 > --- a/drivers/gpu/drm/vboxvideo/vbox_drv.h > +++ b/drivers/gpu/drm/vboxvideo/vbox_drv.h > @@ -145,7 +145,6 @@ void vbox_mm_fini(struct vbox_private *vbox); > int vbox_irq_init(struct vbox_private *vbox); > void vbox_irq_fini(struct vbox_private *vbox); > void vbox_report_hotplug(struct vbox_private *vbox); > -irqreturn_t vbox_irq_handler(int irq, void *arg); > > /* vbox_hgsmi.c */ > void *hgsmi_buffer_alloc(struct gen_pool *guest_pool, size_t size, > diff --git a/drivers/gpu/drm/vboxvideo/vbox_irq.c > b/drivers/gpu/drm/vboxvideo/vbox_irq.c > index b3ded68603ba..903a6c48ee8b 100644 > --- a/drivers/gpu/drm/vboxvideo/vbox_irq.c > +++ b/drivers/gpu/drm/vboxvideo/vbox_irq.c > @@ -10,7 +10,8 @@ > */ > > #include > -#include > + > +#include > #include > > #include "vbox_drv.h" > @@ -31,7 +32,7 @@ void vbox_report_hotplug(struct vbox_private *vbox) > schedule_work(&vbox->hotplug_work); > } > > -irqreturn_t vbox_irq_handler(int irq, void *arg) > +static irqreturn_t vbox_irq_handler(int irq, void *arg) > { > struct drm_device *dev = (struct drm_device *)arg; > struct vbox_private *vbox = to_vbox_dev(dev); > @@ -170,16 +171,21 @@ static void vbox_hotplug_worker(struct work_struct > *work) > > int vbox_irq_init(struct vbox_private *vbox) > { > - struct pci_dev *pdev = to_pci_dev(vbox->ddev.dev); > + struct drm_device *dev = &vbox->ddev; > + struct pci_dev *pdev = to_pci_dev(dev->dev); > > INIT_WORK(&vbox->hotplug_work, vbox_hotplug_worker); > vbox_update_mode_hints(vbox); > > - return drm_irq_install(&vbox->ddev, pdev->irq); > + /* PCI devices require shared interrupts. */ > + return request_irq(pdev->irq, vbox_irq_handler, IRQF_SHARED, > dev->driver->name, dev); > } > > void vbox_irq_fini(struct vbox_private *vbox) > { > - drm_irq_uninstall(&vbox->ddev); > + struct drm_device *dev = &vbox->ddev; > + struct pci_dev *pdev = to_pci_dev(dev->dev); > + > + free_irq(pdev->irq, dev); > flush_work(&vbox->hotplug_work); > } >
Re: [PATCH 1/2] drm/i915/display/vlv_dsi: Do not skip panel_pwr_cycle_delay when disabling the panel
Hi, On 4/7/21 2:34 PM, Ville Syrjälä wrote: > On Tue, Apr 06, 2021 at 03:57:32PM +0200, Hans de Goede wrote: >> Hi, >> >> On 3/25/21 12:48 PM, Hans de Goede wrote: >>> After the recently added commit fe0f1e3bfdfe ("drm/i915: Shut down >>> displays gracefully on reboot"), the DSI panel on a Cherry Trail based >>> Predia Basic tablet would no longer properly light up after reboot. >>> >>> I've managed to reproduce this without rebooting by doing: >>> chvt 3; echo 1 > /sys/class/graphics/fb0/blank;\ >>> echo 0 > /sys/class/graphics/fb0/blank >>> >>> Which rapidly turns the panel off and back on again. >>> >>> The vlv_dsi.c code uses an intel_dsi_msleep() helper for the various delays >>> used for panel on/off, since starting with MIPI-sequences version >= 3 the >>> delays are already included inside the MIPI-sequences. >>> >>> The problems exposed by the "Shut down displays gracefully on reboot" >>> change, show that using this helper for the panel_pwr_cycle_delay is >>> not the right thing to do. This has not been noticed until now because >>> normally the panel never is cycled off and directly on again in quick >>> succession. >>> >>> Change the msleep for the panel_pwr_cycle_delay to a normal msleep() >>> call to avoid the panel staying black after a quick off + on cycle. >>> >>> Cc: Ville Syrjälä >>> Fixes: fe0f1e3bfdfe ("drm/i915: Shut down displays gracefully on reboot") >>> Signed-off-by: Hans de Goede >> >> Ping? Ville AFAICT this is ready for merging, can you review this please so >> that I can push it to drm-intel-next ? > > Didn't get the original mail, but lgtm. Yeah, these bounced I mentioned that in a p.s. in one of the emails in our private threads about the mail issues, with patchwork links, but I guess the p.s. was hidden in all the other stuff in that thread. Anyways this is solved now. > Reviewed-by: Ville Syrjälä Thank you, note this is patch 1/2 does the Reviewed-by apply to both? Patch 2/2 is here: https://patchwork.freedesktop.org/patch/425983/ Regards, Hans >>> --- >>> drivers/gpu/drm/i915/display/vlv_dsi.c | 4 ++-- >>> 1 file changed, 2 insertions(+), 2 deletions(-) >>> >>> diff --git a/drivers/gpu/drm/i915/display/vlv_dsi.c >>> b/drivers/gpu/drm/i915/display/vlv_dsi.c >>> index d5a3f69c5df3..38d5a1f3ded5 100644 >>> --- a/drivers/gpu/drm/i915/display/vlv_dsi.c >>> +++ b/drivers/gpu/drm/i915/display/vlv_dsi.c >>> @@ -996,14 +996,14 @@ static void intel_dsi_post_disable(struct >>> intel_atomic_state *state, >>> * FIXME As we do with eDP, just make a note of the time here >>> * and perform the wait before the next panel power on. >>> */ >>> - intel_dsi_msleep(intel_dsi, intel_dsi->panel_pwr_cycle_delay); >>> + msleep(intel_dsi->panel_pwr_cycle_delay); >>> } >>> >>> static void intel_dsi_shutdown(struct intel_encoder *encoder) >>> { >>> struct intel_dsi *intel_dsi = enc_to_intel_dsi(encoder); >>> >>> - intel_dsi_msleep(intel_dsi, intel_dsi->panel_pwr_cycle_delay); >>> + msleep(intel_dsi->panel_pwr_cycle_delay); >>> } >>> >>> static bool intel_dsi_get_hw_state(struct intel_encoder *encoder, >>> > ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
Re: [PATCH 1/2] drm/i915/display/vlv_dsi: Do not skip panel_pwr_cycle_delay when disabling the panel
Hi, On 4/7/21 3:57 PM, Ville Syrjälä wrote: > On Wed, Apr 07, 2021 at 03:50:35PM +0200, Hans de Goede wrote: >> Hi, >> >> On 4/7/21 2:34 PM, Ville Syrjälä wrote: >>> On Tue, Apr 06, 2021 at 03:57:32PM +0200, Hans de Goede wrote: >>>> Hi, >>>> >>>> On 3/25/21 12:48 PM, Hans de Goede wrote: >>>>> After the recently added commit fe0f1e3bfdfe ("drm/i915: Shut down >>>>> displays gracefully on reboot"), the DSI panel on a Cherry Trail based >>>>> Predia Basic tablet would no longer properly light up after reboot. >>>>> >>>>> I've managed to reproduce this without rebooting by doing: >>>>> chvt 3; echo 1 > /sys/class/graphics/fb0/blank;\ >>>>> echo 0 > /sys/class/graphics/fb0/blank >>>>> >>>>> Which rapidly turns the panel off and back on again. >>>>> >>>>> The vlv_dsi.c code uses an intel_dsi_msleep() helper for the various >>>>> delays >>>>> used for panel on/off, since starting with MIPI-sequences version >= 3 the >>>>> delays are already included inside the MIPI-sequences. >>>>> >>>>> The problems exposed by the "Shut down displays gracefully on reboot" >>>>> change, show that using this helper for the panel_pwr_cycle_delay is >>>>> not the right thing to do. This has not been noticed until now because >>>>> normally the panel never is cycled off and directly on again in quick >>>>> succession. >>>>> >>>>> Change the msleep for the panel_pwr_cycle_delay to a normal msleep() >>>>> call to avoid the panel staying black after a quick off + on cycle. >>>>> >>>>> Cc: Ville Syrjälä >>>>> Fixes: fe0f1e3bfdfe ("drm/i915: Shut down displays gracefully on reboot") >>>>> Signed-off-by: Hans de Goede >>>> >>>> Ping? Ville AFAICT this is ready for merging, can you review this please >>>> so that I can push it to drm-intel-next ? >>> >>> Didn't get the original mail, but lgtm. >> >> Yeah, these bounced I mentioned that in a p.s. in one of the emails >> in our private threads about the mail issues, with patchwork links, >> but I guess the p.s. was hidden in all the other stuff in that thread. >> Anyways this is solved now. >> >>> Reviewed-by: Ville Syrjälä >> >> Thank you, note this is patch 1/2 does the Reviewed-by apply to >> both? Patch 2/2 is here: >> >> https://patchwork.freedesktop.org/patch/425983/ > > That one looks good as well. > > Reviewed-by: Ville Syrjälä Thank you. I've pushed both to drm-intel-next now. Regards, Hans >>>>> --- >>>>> drivers/gpu/drm/i915/display/vlv_dsi.c | 4 ++-- >>>>> 1 file changed, 2 insertions(+), 2 deletions(-) >>>>> >>>>> diff --git a/drivers/gpu/drm/i915/display/vlv_dsi.c >>>>> b/drivers/gpu/drm/i915/display/vlv_dsi.c >>>>> index d5a3f69c5df3..38d5a1f3ded5 100644 >>>>> --- a/drivers/gpu/drm/i915/display/vlv_dsi.c >>>>> +++ b/drivers/gpu/drm/i915/display/vlv_dsi.c >>>>> @@ -996,14 +996,14 @@ static void intel_dsi_post_disable(struct >>>>> intel_atomic_state *state, >>>>>* FIXME As we do with eDP, just make a note of the time here >>>>>* and perform the wait before the next panel power on. >>>>>*/ >>>>> - intel_dsi_msleep(intel_dsi, intel_dsi->panel_pwr_cycle_delay); >>>>> + msleep(intel_dsi->panel_pwr_cycle_delay); >>>>> } >>>>> >>>>> static void intel_dsi_shutdown(struct intel_encoder *encoder) >>>>> { >>>>> struct intel_dsi *intel_dsi = enc_to_intel_dsi(encoder); >>>>> >>>>> - intel_dsi_msleep(intel_dsi, intel_dsi->panel_pwr_cycle_delay); >>>>> + msleep(intel_dsi->panel_pwr_cycle_delay); >>>>> } >>>>> >>>>> static bool intel_dsi_get_hw_state(struct intel_encoder *encoder, >>>>> >>> > ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH resend 0/9] drm: Add privacy-screen class and connector properties
Hi All, Here is the privacy-screen related code which I last posted in August of last year. To the best of my knowledge there is consensus about / everyone is in agreement with the new userspace API (2 connector properties) this patch-set add (patch 1 of the series). The blocker the last time was that there were no userspace users of the new properties and as a rule we don't add new drm userspace API without users. There now is GNOME userspace code using the new properties: https://hackmd.io/@3v1n0/rkyIy3BOw The new API works as designed for this userspace user and the branches mentioned at the above link add the following features to GNOME: 1. Showing an OSD notification when the privacy-screen is toggled on/off through hotkeys handled by the embedded-controller 2. Allowing control of the privacy-screen from the GNOME control-panel, including the on/off slider shown there updating to match the hw-setting when the setting is changed with the control-panel open. 3. Restoring the last user-setting at login This series consists of a number of different parts: 1. A new version of Rajat's privacy-screen connector properties patch, this adds new userspace API in the form of new properties 2. Since on most devices the privacy screen is actually controlled by some vendor specific ACPI/WMI interface which has a driver under drivers/platform/x86, we need some "glue" code to make this functionality available to KMS drivers. Patches 2-4 add a new privacy-screen class for this, which allows non KMS drivers (and possibly KMS drivers too) to register a privacy-screen device and also adds an interface for KMS drivers to get access to the privacy-screen associated with a specific connector. This is modelled similar to how we deal with e.g. PWMs and GPIOs in the kernel, including separate includes for consumers and providers(drivers). 3. Some drm_connector helper functions to keep the actual changes needed for this in individual KMS drivers as small as possible (patch 5). 4. Make the thinkpad_acpi code register a privacy-screen device on ThinkPads with a privacy-screen (patches 6-8) 5. Make the i915 driver export the privacy-screen functionality through the connector properties on the eDP connector. I believe that it would be best to merge the entire series, including the thinkpad_acpi changes through drm-misc in one go. As the pdx86 subsys maintainer I hereby give my ack for merging the thinkpad_acpi changes through drm-misc. There is one small caveat with this series, which it is good to be aware of. The i915 driver will now return -EPROBE_DEFER on Thinkpads with an eprivacy screen, until the thinkpad_acpi driver is loaded. This means that initrd generation tools will need to be updated to include thinkpad_acpi when the i915 driver is added to the initrd. Without this the loading of the i915 driver will be delayed to after the switch to real rootfs. Regards, Hans Hans de Goede (8): drm: Add privacy-screen class drm/privacy-screen: Add X86 specific arch init code drm/privacy-screen: Add notifier support drm/connector: Add a drm_connector privacy-screen helper functions platform/x86: thinkpad_acpi: Add hotkey_notify_extended_hotkey() helper platform/x86: thinkpad_acpi: Get privacy-screen / lcdshadow ACPI handles only once platform/x86: thinkpad_acpi: Register a privacy-screen device drm/i915: Add privacy-screen support Rajat Jain (1): drm/connector: Add support for privacy-screen properties (v4) Documentation/gpu/drm-kms-helpers.rst| 15 + Documentation/gpu/drm-kms.rst| 2 + MAINTAINERS | 8 + drivers/gpu/drm/Kconfig | 5 + drivers/gpu/drm/Makefile | 4 + drivers/gpu/drm/drm_atomic_uapi.c| 4 + drivers/gpu/drm/drm_connector.c | 214 drivers/gpu/drm/drm_privacy_screen.c | 493 +++ drivers/gpu/drm/drm_privacy_screen_x86.c | 82 +++ drivers/gpu/drm/i915/display/intel_display.c | 5 + drivers/gpu/drm/i915/display/intel_dp.c | 10 + drivers/gpu/drm/i915/i915_pci.c | 12 + drivers/platform/x86/Kconfig | 1 + drivers/platform/x86/thinkpad_acpi.c | 131 +++-- include/drm/drm_connector.h | 56 +++ include/drm/drm_privacy_screen_consumer.h| 32 ++ include/drm/drm_privacy_screen_driver.h | 84 include/drm/drm_privacy_screen_machine.h | 46 ++ 18 files changed, 1162 insertions(+), 42 deletions(-) create mode 100644 drivers/gpu/drm/drm_privacy_screen.c create mode 100644 drivers/gpu/drm/drm_privacy_screen_x86.c create mode 100644 include/drm/drm_privacy_screen_consumer.h create mode 100644 include/drm/drm_privacy_screen_driver.h create mode 100644 include/drm/drm_privacy_screen_machine.h -- 2.31.1 ___ dri-devel mailing list dri-devel@lists.f
[PATCH resend 2/9] drm: Add privacy-screen class
On some new laptops the LCD panel has a builtin electronic privacy-screen. We want to export this functionality as a property on the drm connector object. But often this functionality is not exposed on the GPU but on some other (ACPI) device. This commit adds a privacy-screen class allowing the driver for these other devices to register themselves as a privacy-screen provider; and allowing the drm/kms code to get a privacy-screen provider associated with a specific GPU/connector combo. Signed-off-by: Hans de Goede --- Documentation/gpu/drm-kms-helpers.rst | 15 + MAINTAINERS | 8 + drivers/gpu/drm/Kconfig | 5 + drivers/gpu/drm/Makefile | 1 + drivers/gpu/drm/drm_privacy_screen.c | 426 ++ include/drm/drm_privacy_screen_consumer.h | 27 ++ include/drm/drm_privacy_screen_driver.h | 80 include/drm/drm_privacy_screen_machine.h | 41 +++ 8 files changed, 603 insertions(+) create mode 100644 drivers/gpu/drm/drm_privacy_screen.c create mode 100644 include/drm/drm_privacy_screen_consumer.h create mode 100644 include/drm/drm_privacy_screen_driver.h create mode 100644 include/drm/drm_privacy_screen_machine.h diff --git a/Documentation/gpu/drm-kms-helpers.rst b/Documentation/gpu/drm-kms-helpers.rst index 389892f36185..5d8715d2f998 100644 --- a/Documentation/gpu/drm-kms-helpers.rst +++ b/Documentation/gpu/drm-kms-helpers.rst @@ -423,3 +423,18 @@ Legacy CRTC/Modeset Helper Functions Reference .. kernel-doc:: drivers/gpu/drm/drm_crtc_helper.c :export: + +Privacy-screen class + + +.. kernel-doc:: drivers/gpu/drm/drm_privacy_screen.c + :doc: overview + +.. kernel-doc:: include/drm/drm_privacy_screen_driver.h + :internal: + +.. kernel-doc:: include/drm/drm_privacy_screen_machine.h + :internal: + +.. kernel-doc:: drivers/gpu/drm/drm_privacy_screen.c + :export: diff --git a/MAINTAINERS b/MAINTAINERS index 7c45120759e6..8220295b2670 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -6129,6 +6129,14 @@ F: drivers/gpu/drm/drm_panel.c F: drivers/gpu/drm/panel/ F: include/drm/drm_panel.h +DRM PRIVACY-SCREEN CLASS +M: Hans de Goede +L: dri-devel@lists.freedesktop.org +S: Maintained +T: git git://anongit.freedesktop.org/drm/drm-misc +F: drivers/gpu/drm/drm_privacy_screen* +F: include/drm/drm_privacy_screen* + DRM TTM SUBSYSTEM M: Christian Koenig M: Huang Rui diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig index 3c16bd1afd87..da25ff3a0a34 100644 --- a/drivers/gpu/drm/Kconfig +++ b/drivers/gpu/drm/Kconfig @@ -474,3 +474,8 @@ config DRM_PANEL_ORIENTATION_QUIRKS config DRM_LIB_RANDOM bool default n + +# Separate option, used by drivers outside of drivers/gpu/drm +config DRM_PRIVACY_SCREEN + tristate + default n diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile index 5279db4392df..9a802605249d 100644 --- a/drivers/gpu/drm/Makefile +++ b/drivers/gpu/drm/Makefile @@ -62,6 +62,7 @@ obj-$(CONFIG_DRM) += drm.o obj-$(CONFIG_DRM_MIPI_DBI) += drm_mipi_dbi.o obj-$(CONFIG_DRM_MIPI_DSI) += drm_mipi_dsi.o obj-$(CONFIG_DRM_PANEL_ORIENTATION_QUIRKS) += drm_panel_orientation_quirks.o +obj-$(CONFIG_DRM_PRIVACY_SCREEN) += drm_privacy_screen.o obj-y += arm/ obj-$(CONFIG_DRM_TTM) += ttm/ obj-$(CONFIG_DRM_SCHED)+= scheduler/ diff --git a/drivers/gpu/drm/drm_privacy_screen.c b/drivers/gpu/drm/drm_privacy_screen.c new file mode 100644 index ..6296fd46156c --- /dev/null +++ b/drivers/gpu/drm/drm_privacy_screen.c @@ -0,0 +1,426 @@ +// SPDX-License-Identifier: MIT +/* + * Copyright (C) 2020 Red Hat, Inc. + * + * Authors: + * Hans de Goede + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/** + * DOC: overview + * + * This class allows non KMS drivers, from e.g. drivers/platform/x86 to + * register a privacy-screen device, which the KMS drivers can then use + * to implement the standard privacy-screen properties, see + * :ref:`Standard Connector Properties`. + * + * KMS drivers using a privacy-screen class device are advised to use the + * drm_connector_attach_privacy_screen_provider() and + * drm_connector_update_privacy_screen() helpers for dealing with this. + */ + +#define to_drm_privacy_screen(dev) \ + container_of(dev, struct drm_privacy_screen, dev) + +static DEFINE_MUTEX(drm_privacy_screen_lookup_lock); +static LIST_HEAD(drm_privacy_screen_lookup_list); + +static DEFINE_MUTEX(drm_privacy_screen_devs_lock); +static LIST_HEAD(drm_privacy_screen_devs); + +/*** drm_privacy_screen_machine.h functions ***/ + +/** + * drm_privacy_screen_lookup_add - add an entry to the static privacy-screen + *lookup list + * @lookup: lookup list entry to add + * + * Add an entry to the static privacy-screen lookup list. Note the + * &struct list_head which is part of the &am
[PATCH resend 1/9] drm/connector: Add support for privacy-screen properties (v4)
From: Rajat Jain Add support for generic electronic privacy screen properties, that can be added by systems that have an integrated EPS. Changes in v2 (Hans de Goede) - Create 2 properties, "privacy-screen sw-state" and "privacy-screen hw-state", to deal with devices where the OS might be locked out of making state changes - Write kerneldoc explaining how the 2 properties work together, what happens when changes to the state are made outside of the DRM code's control, etc. Changes in v3 (Hans de Goede) - Some small tweaks to the kerneldoc describing the 2 properties Changes in v4 (Hans de Goede) - Change the "Enabled, locked" and "Disabled, locked" hw-state enum value names to "Enabled-locked" and "Disabled-locked". The xrandr command shows all possible enum values separated by commas in its output, so having a comma in an enum name is not a good idea. - Do not add a privacy_screen_hw_state member to drm_connector_state since this property is immutable its value must be directly stored in the obj->properties->values array Signed-off-by: Rajat Jain Co-authored-by: Hans de Goede Acked-by: Pekka Paalanen Reviewed-by: Mario Limonciello Signed-off-by: Hans de Goede --- Documentation/gpu/drm-kms.rst | 2 + drivers/gpu/drm/drm_atomic_uapi.c | 4 ++ drivers/gpu/drm/drm_connector.c | 101 ++ include/drm/drm_connector.h | 44 + 4 files changed, 151 insertions(+) diff --git a/Documentation/gpu/drm-kms.rst b/Documentation/gpu/drm-kms.rst index 87e5023e3f55..36943f2b0c5d 100644 --- a/Documentation/gpu/drm-kms.rst +++ b/Documentation/gpu/drm-kms.rst @@ -475,6 +475,8 @@ Property Types and Blob Property Support .. kernel-doc:: drivers/gpu/drm/drm_property.c :export: +.. _standard_connector_properties: + Standard Connector Properties - diff --git a/drivers/gpu/drm/drm_atomic_uapi.c b/drivers/gpu/drm/drm_atomic_uapi.c index 268bb69c2e2f..d5339b683156 100644 --- a/drivers/gpu/drm/drm_atomic_uapi.c +++ b/drivers/gpu/drm/drm_atomic_uapi.c @@ -796,6 +796,8 @@ static int drm_atomic_connector_set_property(struct drm_connector *connector, fence_ptr); } else if (property == connector->max_bpc_property) { state->max_requested_bpc = val; + } else if (property == connector->privacy_screen_sw_state_property) { + state->privacy_screen_sw_state = val; } else if (connector->funcs->atomic_set_property) { return connector->funcs->atomic_set_property(connector, state, property, val); @@ -873,6 +875,8 @@ drm_atomic_connector_get_property(struct drm_connector *connector, *val = 0; } else if (property == connector->max_bpc_property) { *val = state->max_requested_bpc; + } else if (property == connector->privacy_screen_sw_state_property) { + *val = state->privacy_screen_sw_state; } else if (connector->funcs->atomic_get_property) { return connector->funcs->atomic_get_property(connector, state, property, val); diff --git a/drivers/gpu/drm/drm_connector.c b/drivers/gpu/drm/drm_connector.c index 7631f76e7f34..ca8a76decd4c 100644 --- a/drivers/gpu/drm/drm_connector.c +++ b/drivers/gpu/drm/drm_connector.c @@ -1244,6 +1244,46 @@ static const struct drm_prop_enum_list dp_colorspaces[] = { * For DVI-I and TVout there is also a matching property "select subconnector" * allowing to switch between signal types. * DP subconnector corresponds to a downstream port. + * + * privacy-screen sw-state, privacy-screen hw-state: + * These 2 optional properties can be used to query the state of the + * electronic privacy screen that is available on some displays; and in + * some cases also control the state. If a driver implements these + * properties then both properties must be present. + * + * "privacy-screen hw-state" is read-only and reflects the actual state + * of the privacy-screen, possible values: "Enabled", "Disabled, + * "Enabled-locked", "Disabled-locked". The locked states indicate + * that the state cannot be changed through the DRM API. E.g. there + * might be devices where the firmware-setup options, or a hardware + * slider-switch, offer always on / off modes. + * + * "privacy-screen sw-state" can be set to change the privacy-screen state + * when not locked. In this case the driver must update the hw-state + * property to reflect the new state on completion of the commit of the + * sw-state property. Setting the sw-state property when the hw-state is + * locked must be interpreted by the driver as a
[PATCH resend 3/9] drm/privacy-screen: Add X86 specific arch init code
Add X86 specific arch init code, which fills the privacy-screen lookup table by checking for various vendor specific ACPI interfaces for controlling the privacy-screen. This initial version only checks for the Lenovo Thinkpad specific ACPI methods for privacy-screen control. Signed-off-by: Hans de Goede --- drivers/gpu/drm/Makefile | 5 +- drivers/gpu/drm/drm_privacy_screen_x86.c | 82 include/drm/drm_privacy_screen_machine.h | 5 ++ 3 files changed, 91 insertions(+), 1 deletion(-) create mode 100644 drivers/gpu/drm/drm_privacy_screen_x86.c diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile index 9a802605249d..75166bd53e00 100644 --- a/drivers/gpu/drm/Makefile +++ b/drivers/gpu/drm/Makefile @@ -58,11 +58,14 @@ drm_kms_helper-$(CONFIG_DRM_DP_CEC) += drm_dp_cec.o obj-$(CONFIG_DRM_KMS_HELPER) += drm_kms_helper.o obj-$(CONFIG_DRM_DEBUG_SELFTEST) += selftests/ +drm_privacy_screen_helper-y := drm_privacy_screen.o +drm_privacy_screen_helper-$(CONFIG_X86) += drm_privacy_screen_x86.o +obj-$(CONFIG_DRM_PRIVACY_SCREEN) += drm_privacy_screen_helper.o + obj-$(CONFIG_DRM) += drm.o obj-$(CONFIG_DRM_MIPI_DBI) += drm_mipi_dbi.o obj-$(CONFIG_DRM_MIPI_DSI) += drm_mipi_dsi.o obj-$(CONFIG_DRM_PANEL_ORIENTATION_QUIRKS) += drm_panel_orientation_quirks.o -obj-$(CONFIG_DRM_PRIVACY_SCREEN) += drm_privacy_screen.o obj-y += arm/ obj-$(CONFIG_DRM_TTM) += ttm/ obj-$(CONFIG_DRM_SCHED)+= scheduler/ diff --git a/drivers/gpu/drm/drm_privacy_screen_x86.c b/drivers/gpu/drm/drm_privacy_screen_x86.c new file mode 100644 index ..f486d9087819 --- /dev/null +++ b/drivers/gpu/drm/drm_privacy_screen_x86.c @@ -0,0 +1,82 @@ +// SPDX-License-Identifier: MIT +/* + * Copyright (C) 2020 Red Hat, Inc. + * + * Authors: + * Hans de Goede + */ + +#include +#include + +static struct drm_privacy_screen_lookup arch_lookup; + +struct arch_init_data { + struct drm_privacy_screen_lookup lookup; + bool (*detect)(void); +}; + +static acpi_status __init acpi_set_handle(acpi_handle handle, u32 level, + void *context, void **return_value) +{ + *(acpi_handle *)return_value = handle; + return AE_CTRL_TERMINATE; +} + +static bool __init detect_thinkpad_privacy_screen(void) +{ + union acpi_object obj = { .type = ACPI_TYPE_INTEGER }; + struct acpi_object_list args = { .count = 1, .pointer = &obj, }; + acpi_handle ec_handle = NULL; + unsigned long long output; + acpi_status status; + + /* Get embedded-controller handle */ + status = acpi_get_devices("PNP0C09", acpi_set_handle, NULL, &ec_handle); + if (ACPI_FAILURE(status) || !ec_handle) + return false; + + /* And call the privacy-screen get-status method */ + status = acpi_evaluate_integer(ec_handle, "HKEY.GSSS", &args, &output); + if (ACPI_FAILURE(status)) + return false; + + return (output & 0x1) ? true : false; +} + +static const struct arch_init_data arch_init_data[] __initconst = { +#if IS_ENABLED(CONFIG_THINKPAD_ACPI) + { + .lookup = { + .dev_id = NULL, + .con_id = NULL, + .provider = "thinkpad_acpi", + }, + .detect = detect_thinkpad_privacy_screen, + }, +#endif +}; + +void __init drm_privacy_screen_arch_init(void) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(arch_init_data); i++) { + if (!arch_init_data[i].detect()) + continue; + + pr_info("Found '%s' privacy-screen provider\n", + arch_init_data[i].lookup.provider); + + /* Make a copy because arch_init_data is __initconst */ + arch_lookup = arch_init_data[i].lookup; + drm_privacy_screen_lookup_add(&arch_lookup); + break; + } +} + +void __exit drm_privacy_screen_arch_exit(void) +{ + if (arch_lookup.provider) + drm_privacy_screen_lookup_remove(&arch_lookup); +} diff --git a/include/drm/drm_privacy_screen_machine.h b/include/drm/drm_privacy_screen_machine.h index 55f4b4fd8e4e..0d2f2a443e8c 100644 --- a/include/drm/drm_privacy_screen_machine.h +++ b/include/drm/drm_privacy_screen_machine.h @@ -31,11 +31,16 @@ struct drm_privacy_screen_lookup { void drm_privacy_screen_lookup_add(struct drm_privacy_screen_lookup *lookup); void drm_privacy_screen_lookup_remove(struct drm_privacy_screen_lookup *lookup); +#ifdef CONFIG_X86 +void drm_privacy_screen_arch_init(void); +void drm_privacy_screen_arch_exit(void); +#else static inline void drm_privacy_screen_arch_init(void) { } static inline void drm_privacy_screen_arch_exit(void) { } +#endif #endif -- 2.31.1 ___ dri-devel mailing li
[PATCH resend 4/9] drm/privacy-screen: Add notifier support
Add support for privacy-screen consumers to register a notifier to be notified of external (e.g. done by the hw itself on a hotkey press) state changes. Signed-off-by: Hans de Goede --- drivers/gpu/drm/drm_privacy_screen.c | 67 +++ include/drm/drm_privacy_screen_consumer.h | 5 ++ include/drm/drm_privacy_screen_driver.h | 4 ++ 3 files changed, 76 insertions(+) diff --git a/drivers/gpu/drm/drm_privacy_screen.c b/drivers/gpu/drm/drm_privacy_screen.c index 6296fd46156c..7e78b4068e8f 100644 --- a/drivers/gpu/drm/drm_privacy_screen.c +++ b/drivers/gpu/drm/drm_privacy_screen.c @@ -254,6 +254,49 @@ void drm_privacy_screen_get_state(struct drm_privacy_screen *priv, } EXPORT_SYMBOL(drm_privacy_screen_get_state); +/** + * drm_privacy_screen_register_notifier - register a notifier + * @priv: Privacy screen to register the notifier with + * @nb: Notifier-block for the notifier to register + * + * Register a notifier with the privacy-screen to be notified of changes made + * to the privacy-screen state from outside of the privacy-screen class. + * E.g. the state may be changed by the hardware itself in response to a + * hotkey press. + * + * The notifier is called with no locks held. The new hw_state and sw_state + * can be retrieved using the drm_privacy_screen_get_state() function. + * A pointer to the drm_privacy_screen's struct is passed as the void *data + * argument of the notifier_block's notifier_call. + * + * The notifier will NOT be called when changes are made through + * drm_privacy_screen_set_sw_state(). It is only called for external changes. + * + * Return: 0 on success, negative error code on failure. + */ +int drm_privacy_screen_register_notifier(struct drm_privacy_screen *priv, +struct notifier_block *nb) +{ + return blocking_notifier_chain_register(&priv->notifier_head, nb); +} +EXPORT_SYMBOL(drm_privacy_screen_register_notifier); + +/** + * drm_privacy_screen_unregister_notifier - unregister a notifier + * @priv: Privacy screen to register the notifier with + * @nb: Notifier-block for the notifier to register + * + * Unregister a notifier registered with drm_privacy_screen_register_notifier(). + * + * Return: 0 on success, negative error code on failure. + */ +int drm_privacy_screen_unregister_notifier(struct drm_privacy_screen *priv, + struct notifier_block *nb) +{ + return blocking_notifier_chain_unregister(&priv->notifier_head, nb); +} +EXPORT_SYMBOL(drm_privacy_screen_unregister_notifier); + /*** drm_privacy_screen_driver.h functions ***/ static ssize_t sw_state_show(struct device *dev, @@ -352,6 +395,7 @@ struct drm_privacy_screen *drm_privacy_screen_register( return ERR_PTR(-ENOMEM); mutex_init(&priv->lock); + BLOCKING_INIT_NOTIFIER_HEAD(&priv->notifier_head); priv->dev.class = &drm_privacy_screen_class; priv->dev.parent = parent; @@ -399,6 +443,29 @@ void drm_privacy_screen_unregister(struct drm_privacy_screen *priv) } EXPORT_SYMBOL(drm_privacy_screen_unregister); +/** + * drm_privacy_screen_call_notifier_chain - notify consumers of state change + * @priv: Privacy screen to register the notifier with + * + * A privacy-screen provider driver can call this functions upon external + * changes to the privacy-screen state. E.g. the state may be changed by the + * hardware itself in response to a hotkey press. + * This function must be called without holding the privacy-screen lock. + * the driver must update sw_state and hw_state to reflect the new state before + * calling this function. + * The expected behavior from the driver upon receiving an external state + * change event is: 1. Take the lock; 2. Update sw_state and hw_state; + * 3. Release the lock. 4. Call drm_privacy_screen_call_notifier_chain(). + */ +void drm_privacy_screen_call_notifier_chain(struct drm_privacy_screen *priv) +{ + if (WARN_ON(mutex_is_locked(&priv->lock))) + return; + + blocking_notifier_call_chain(&priv->notifier_head, 0, priv); +} +EXPORT_SYMBOL(drm_privacy_screen_call_notifier_chain); + static int __init drm_privacy_screen_init(void) { int ret; diff --git a/include/drm/drm_privacy_screen_consumer.h b/include/drm/drm_privacy_screen_consumer.h index 169ba72bd60d..1f33dc1457ff 100644 --- a/include/drm/drm_privacy_screen_consumer.h +++ b/include/drm/drm_privacy_screen_consumer.h @@ -24,4 +24,9 @@ void drm_privacy_screen_get_state(struct drm_privacy_screen *priv, enum drm_privacy_screen_status *sw_state_ret, enum drm_privacy_screen_status *hw_state_ret); +int drm_privacy_screen_register_notifier(struct drm_privacy_screen *priv, +struct notifier_block *nb); +int drm_privacy_screen_unregister_notifier(struct drm_privacy_s
[PATCH resend 6/9] platform/x86: thinkpad_acpi: Add hotkey_notify_extended_hotkey() helper
Factor the extended hotkey handling out of hotkey_notify_hotkey() and into a new hotkey_notify_extended_hotkey() helper. This is a preparation patch for adding support the privacy-screen hotkey toggle (which needs some special handling, it should NOT send an evdev key-event to userspace...). Signed-off-by: Hans de Goede --- drivers/platform/x86/thinkpad_acpi.c | 30 ++-- 1 file changed, 19 insertions(+), 11 deletions(-) diff --git a/drivers/platform/x86/thinkpad_acpi.c b/drivers/platform/x86/thinkpad_acpi.c index 0d9e2ddbf904..683c175cc28a 100644 --- a/drivers/platform/x86/thinkpad_acpi.c +++ b/drivers/platform/x86/thinkpad_acpi.c @@ -3878,6 +3878,24 @@ static bool adaptive_keyboard_hotkey_notify_hotkey(unsigned int scancode) } } +static bool hotkey_notify_extended_hotkey(const u32 hkey) +{ + unsigned int scancode; + + /* Extended keycodes start at 0x300 and our offset into the map +* TP_ACPI_HOTKEYSCAN_EXTENDED_START. The calculated scancode +* will be positive, but might not be in the correct range. +*/ + scancode = (hkey & 0xfff) - (0x300 - TP_ACPI_HOTKEYSCAN_EXTENDED_START); + if (scancode >= TP_ACPI_HOTKEYSCAN_EXTENDED_START && + scancode < TPACPI_HOTKEY_MAP_LEN) { + tpacpi_input_send_key(scancode); + return true; + } + + return false; +} + static bool hotkey_notify_hotkey(const u32 hkey, bool *send_acpi_ev, bool *ignore_acpi_ev) @@ -3912,17 +3930,7 @@ static bool hotkey_notify_hotkey(const u32 hkey, return adaptive_keyboard_hotkey_notify_hotkey(scancode); case 3: - /* Extended keycodes start at 0x300 and our offset into the map -* TP_ACPI_HOTKEYSCAN_EXTENDED_START. The calculated scancode -* will be positive, but might not be in the correct range. -*/ - scancode -= (0x300 - TP_ACPI_HOTKEYSCAN_EXTENDED_START); - if (scancode >= TP_ACPI_HOTKEYSCAN_EXTENDED_START && - scancode < TPACPI_HOTKEY_MAP_LEN) { - tpacpi_input_send_key(scancode); - return true; - } - break; + return hotkey_notify_extended_hotkey(hkey); } return false; -- 2.31.1 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH resend 5/9] drm/connector: Add a drm_connector privacy-screen helper functions
Add 2 drm_connector privacy-screen helper functions: 1. drm_connector_attach_privacy_screen_provider(), this function creates and attaches the standard privacy-screen properties and registers a generic notifier for generating sysfs-connector-status-events on external changes to the privacy-screen status. 2. drm_connector_update_privacy_screen(), Check if the passed in atomic state contains a privacy-screen sw_state change for the connector and if it does, call drm_privacy_screen_set_sw_state() with the new sw_state. Signed-off-by: Hans de Goede --- drivers/gpu/drm/drm_connector.c | 113 include/drm/drm_connector.h | 12 2 files changed, 125 insertions(+) diff --git a/drivers/gpu/drm/drm_connector.c b/drivers/gpu/drm/drm_connector.c index ca8a76decd4c..958a332374af 100644 --- a/drivers/gpu/drm/drm_connector.c +++ b/drivers/gpu/drm/drm_connector.c @@ -20,6 +20,7 @@ * OF THIS SOFTWARE. */ +#include #include #include #include @@ -27,6 +28,7 @@ #include #include #include +#include #include #include @@ -451,6 +453,11 @@ void drm_connector_cleanup(struct drm_connector *connector) DRM_CONNECTOR_REGISTERED)) drm_connector_unregister(connector); + if (connector->privacy_screen) { + drm_privacy_screen_put(connector->privacy_screen); + connector->privacy_screen = NULL; + } + if (connector->tile_group) { drm_mode_put_tile_group(dev, connector->tile_group); connector->tile_group = NULL; @@ -530,6 +537,10 @@ int drm_connector_register(struct drm_connector *connector) /* Let userspace know we have a new connector */ drm_sysfs_hotplug_event(connector->dev); + if (connector->privacy_screen) + drm_privacy_screen_register_notifier(connector->privacy_screen, + &connector->privacy_screen_notifier); + goto unlock; err_debugfs: @@ -558,6 +569,11 @@ void drm_connector_unregister(struct drm_connector *connector) return; } + if (connector->privacy_screen) + drm_privacy_screen_unregister_notifier( + connector->privacy_screen, + &connector->privacy_screen_notifier); + if (connector->funcs->early_unregister) connector->funcs->early_unregister(connector); @@ -2353,6 +2369,103 @@ drm_connector_attach_privacy_screen_properties(struct drm_connector *connector) } EXPORT_SYMBOL(drm_connector_attach_privacy_screen_properties); +static void drm_connector_update_privacy_screen_properties( + struct drm_connector *connector) +{ + enum drm_privacy_screen_status sw_state, hw_state; + + drm_privacy_screen_get_state(connector->privacy_screen, +&sw_state, &hw_state); + + connector->state->privacy_screen_sw_state = sw_state; + drm_object_property_set_value(&connector->base, + connector->privacy_screen_hw_state_property, hw_state); +} + +static int drm_connector_privacy_screen_notifier( + struct notifier_block *nb, unsigned long action, void *data) +{ + struct drm_connector *connector = + container_of(nb, struct drm_connector, privacy_screen_notifier); + struct drm_device *dev = connector->dev; + + drm_modeset_lock(&dev->mode_config.connection_mutex, NULL); + drm_connector_update_privacy_screen_properties(connector); + drm_modeset_unlock(&dev->mode_config.connection_mutex); + + drm_sysfs_connector_status_event(connector, + connector->privacy_screen_sw_state_property); + drm_sysfs_connector_status_event(connector, + connector->privacy_screen_hw_state_property); + + return NOTIFY_DONE; +} + +/** + * drm_connector_attach_privacy_screen_provider - attach a privacy-screen to + *the connector + * @connector: connector to attach the privacy-screen to + * @priv: drm_privacy_screen to attach + * + * Create and attach the standard privacy-screen properties and register + * a generic notifier for generating sysfs-connector-status-events + * on external changes to the privacy-screen status. + * This function takes ownership of the passed in drm_privacy_screen and will + * call drm_privacy_screen_put() on it when the connector is destroyed. + */ +void drm_connector_attach_privacy_screen_provider( + struct drm_connector *connector, struct drm_privacy_screen *priv) +{ + connector->privacy_screen = priv; + connector->privacy_screen_notifier.notifier_call = + drm_connector_privacy_screen_notifier; + + drm_connector_create_privacy_screen_properties(connector); +
[PATCH resend 7/9] platform/x86: thinkpad_acpi: Get privacy-screen / lcdshadow ACPI handles only once
Get the privacy-screen / lcdshadow ACPI handles once and cache them, instead of retrieving them every time we need them. Signed-off-by: Hans de Goede --- drivers/platform/x86/thinkpad_acpi.c | 18 -- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/drivers/platform/x86/thinkpad_acpi.c b/drivers/platform/x86/thinkpad_acpi.c index 683c175cc28a..fe919700b8ae 100644 --- a/drivers/platform/x86/thinkpad_acpi.c +++ b/drivers/platform/x86/thinkpad_acpi.c @@ -9759,19 +9759,15 @@ static struct ibm_struct battery_driver_data = { * LCD Shadow subdriver, for the Lenovo PrivacyGuard feature */ +static acpi_handle lcdshadow_get_handle; +static acpi_handle lcdshadow_set_handle; static int lcdshadow_state; static int lcdshadow_on_off(bool state) { - acpi_handle set_shadow_handle; int output; - if (ACPI_FAILURE(acpi_get_handle(hkey_handle, "", &set_shadow_handle))) { - pr_warn("Thinkpad ACPI has no %s interface.\n", ""); - return -EIO; - } - - if (!acpi_evalf(set_shadow_handle, &output, NULL, "dd", (int)state)) + if (!acpi_evalf(lcdshadow_set_handle, &output, NULL, "dd", (int)state)) return -EIO; lcdshadow_state = state; @@ -9789,15 +9785,17 @@ static int lcdshadow_set(bool on) static int tpacpi_lcdshadow_init(struct ibm_init_struct *iibm) { - acpi_handle get_shadow_handle; + acpi_status status1, status2; int output; - if (ACPI_FAILURE(acpi_get_handle(hkey_handle, "GSSS", &get_shadow_handle))) { + status1 = acpi_get_handle(hkey_handle, "GSSS", &lcdshadow_get_handle); + status2 = acpi_get_handle(hkey_handle, "", &lcdshadow_set_handle); + if (ACPI_FAILURE(status1) || ACPI_FAILURE(status2)) { lcdshadow_state = -ENODEV; return 0; } - if (!acpi_evalf(get_shadow_handle, &output, NULL, "dd", 0)) { + if (!acpi_evalf(lcdshadow_get_handle, &output, NULL, "dd", 0)) { lcdshadow_state = -EIO; return -EIO; } -- 2.31.1 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH resend 8/9] platform/x86: thinkpad_acpi: Register a privacy-screen device
Register a privacy-screen device on laptops with a privacy-screen, this exports the PrivacyGuard features to user-space using a standardized vendor-agnostic sysfs interface. Note the sysfs interface is read-only. Registering a privacy-screen device with the new privacy-screen class code will also allow the GPU driver to get a handle to it and export the privacy-screen setting as a property on the DRM connector object for the LCD panel. This DRM connector property is news standardized interface which all user-space code should use to query and control the privacy-screen. Signed-off-by: Hans de Goede --- Changes in v2: - Make the new lcdshadow_set_sw_state, lcdshadow_get_hw_state and lcdshadow_ops symbols static - Update state and call drm_privacy_screen_call_notifier_chain() when the state is changed by pressing the Fn + D hotkey combo --- drivers/platform/x86/Kconfig | 1 + drivers/platform/x86/thinkpad_acpi.c | 91 2 files changed, 67 insertions(+), 25 deletions(-) diff --git a/drivers/platform/x86/Kconfig b/drivers/platform/x86/Kconfig index 461ec61530eb..404d80f99a03 100644 --- a/drivers/platform/x86/Kconfig +++ b/drivers/platform/x86/Kconfig @@ -485,6 +485,7 @@ config THINKPAD_ACPI depends on ACPI_VIDEO || ACPI_VIDEO = n depends on BACKLIGHT_CLASS_DEVICE select ACPI_PLATFORM_PROFILE + select DRM_PRIVACY_SCREEN select HWMON select NVRAM select NEW_LEDS diff --git a/drivers/platform/x86/thinkpad_acpi.c b/drivers/platform/x86/thinkpad_acpi.c index fe919700b8ae..766c6d64b0fb 100644 --- a/drivers/platform/x86/thinkpad_acpi.c +++ b/drivers/platform/x86/thinkpad_acpi.c @@ -73,6 +73,7 @@ #include #include #include +#include /* ThinkPad CMOS commands */ #define TP_CMOS_VOLUME_DOWN0 @@ -156,6 +157,7 @@ enum tpacpi_hkey_event_t { TP_HKEY_EV_VOL_UP = 0x1015, /* Volume up or unmute */ TP_HKEY_EV_VOL_DOWN = 0x1016, /* Volume down or unmute */ TP_HKEY_EV_VOL_MUTE = 0x1017, /* Mixer output mute */ + TP_HKEY_EV_PRIVACYGUARD_TOGGLE = 0x130f, /* Toggle priv.guard on/off */ /* Reasons for waking up from S3/S4 */ TP_HKEY_EV_WKUP_S3_UNDOCK = 0x2304, /* undock requested, S3 */ @@ -3882,6 +3884,12 @@ static bool hotkey_notify_extended_hotkey(const u32 hkey) { unsigned int scancode; + switch (hkey) { + case TP_HKEY_EV_PRIVACYGUARD_TOGGLE: + tpacpi_driver_event(hkey); + return true; + } + /* Extended keycodes start at 0x300 and our offset into the map * TP_ACPI_HOTKEYSCAN_EXTENDED_START. The calculated scancode * will be positive, but might not be in the correct range. @@ -9759,30 +9767,40 @@ static struct ibm_struct battery_driver_data = { * LCD Shadow subdriver, for the Lenovo PrivacyGuard feature */ +static struct drm_privacy_screen *lcdshadow_dev; static acpi_handle lcdshadow_get_handle; static acpi_handle lcdshadow_set_handle; -static int lcdshadow_state; -static int lcdshadow_on_off(bool state) +static int lcdshadow_set_sw_state(struct drm_privacy_screen *priv, + enum drm_privacy_screen_status state) { int output; + if (WARN_ON(!mutex_is_locked(&priv->lock))) + return -EIO; + if (!acpi_evalf(lcdshadow_set_handle, &output, NULL, "dd", (int)state)) return -EIO; - lcdshadow_state = state; + priv->hw_state = priv->sw_state = state; return 0; } -static int lcdshadow_set(bool on) +static void lcdshadow_get_hw_state(struct drm_privacy_screen *priv) { - if (lcdshadow_state < 0) - return lcdshadow_state; - if (lcdshadow_state == on) - return 0; - return lcdshadow_on_off(on); + int output; + + if (!acpi_evalf(lcdshadow_get_handle, &output, NULL, "dd", 0)) + return; + + priv->hw_state = priv->sw_state = output & 0x1; } +static const struct drm_privacy_screen_ops lcdshadow_ops = { + .set_sw_state = lcdshadow_set_sw_state, + .get_hw_state = lcdshadow_get_hw_state, +}; + static int tpacpi_lcdshadow_init(struct ibm_init_struct *iibm) { acpi_status status1, status2; @@ -9790,36 +9808,44 @@ static int tpacpi_lcdshadow_init(struct ibm_init_struct *iibm) status1 = acpi_get_handle(hkey_handle, "GSSS", &lcdshadow_get_handle); status2 = acpi_get_handle(hkey_handle, "", &lcdshadow_set_handle); - if (ACPI_FAILURE(status1) || ACPI_FAILURE(status2)) { - lcdshadow_state = -ENODEV; + if (ACPI_FAILURE(status1) || ACPI_FAILURE(status2)) return 0; - } - if (!acpi_evalf(lcdshadow_get_handle, &output, NULL, "dd", 0)) { - lcdshadow_state = -EIO; +
[PATCH resend 9/9] drm/i915: Add privacy-screen support
Add support for eDP panels with a built-in privacy screen using the new drm_privacy_screen class. One thing which stands out here is the addition of these 2 lines to intel_atomic_commit_tail: for_each_new_connector_in_state(&state->base, connector, ... drm_connector_update_privacy_screen(connector, state); It may seem more logical to instead take care of updating the privacy-screen state by marking the crtc as needing a modeset and then do this in both the encoder update_pipe (for fast-sets) and enable (for full modesets) callbacks. But ATM these callbacks only get passed the new connector_state and these callbacks are all called after drm_atomic_helper_swap_state() at which point there is no way to get the old state from the new state. Without access to the old state, we do not know if the sw_state of the privacy-screen has changes so we would need to call drm_privacy_screen_set_sw_state() unconditionally. This is undesirable since all current known privacy-screen providers use ACPI calls which are somewhat expensive to make. Also, as all providers use ACPI calls, rather then poking GPU registers, there is no need to order this together with other encoder operations. Since no GPU poking is involved having this as a separate step of the commit process actually is the logical thing to do. Signed-off-by: Hans de Goede --- drivers/gpu/drm/i915/display/intel_display.c | 5 + drivers/gpu/drm/i915/display/intel_dp.c | 10 ++ drivers/gpu/drm/i915/i915_pci.c | 12 3 files changed, 27 insertions(+) diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index 411b46c012f8..620d11d6bb31 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -10169,6 +10169,8 @@ static void intel_atomic_commit_tail(struct intel_atomic_state *state) struct drm_device *dev = state->base.dev; struct drm_i915_private *dev_priv = to_i915(dev); struct intel_crtc_state *new_crtc_state, *old_crtc_state; + struct drm_connector_state *new_connector_state; + struct drm_connector *connector; struct intel_crtc *crtc; u64 put_domains[I915_MAX_PIPES] = {}; intel_wakeref_t wakeref = 0; @@ -10266,6 +10268,9 @@ static void intel_atomic_commit_tail(struct intel_atomic_state *state) intel_color_load_luts(new_crtc_state); } + for_each_new_connector_in_state(&state->base, connector, new_connector_state, i) + drm_connector_update_privacy_screen(connector, &state->base); + /* * Now that the vblank has passed, we can go ahead and program the * optimal watermarks on platforms that need two-step watermark diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c index 6750949aa261..8ca3909e2ec9 100644 --- a/drivers/gpu/drm/i915/display/intel_dp.c +++ b/drivers/gpu/drm/i915/display/intel_dp.c @@ -37,6 +37,7 @@ #include #include #include +#include #include #include "g4x_dp.h" @@ -5178,6 +5179,7 @@ static bool intel_edp_init_connector(struct intel_dp *intel_dp, struct drm_connector *connector = &intel_connector->base; struct drm_display_mode *fixed_mode = NULL; struct drm_display_mode *downclock_mode = NULL; + struct drm_privacy_screen *privacy_screen; bool has_dpcd; enum pipe pipe = INVALID_PIPE; struct edid *edid; @@ -5268,6 +5270,14 @@ static bool intel_edp_init_connector(struct intel_dp *intel_dp, fixed_mode->hdisplay, fixed_mode->vdisplay); } + privacy_screen = drm_privacy_screen_get(&dev->pdev->dev, NULL); + if (!IS_ERR(privacy_screen)) { + drm_connector_attach_privacy_screen_provider(connector, +privacy_screen); + } else if (PTR_ERR(privacy_screen) != -ENODEV) { + drm_warn(&dev_priv->drm, "Error getting privacy-screen\n"); + } + return true; out_vdd_off: diff --git a/drivers/gpu/drm/i915/i915_pci.c b/drivers/gpu/drm/i915/i915_pci.c index 480553746794..95426e365400 100644 --- a/drivers/gpu/drm/i915/i915_pci.c +++ b/drivers/gpu/drm/i915/i915_pci.c @@ -26,6 +26,7 @@ #include #include +#include #include #include "display/intel_fbdev.h" @@ -1064,6 +1065,7 @@ static int i915_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) { struct intel_device_info *intel_info = (struct intel_device_info *) ent->driver_data; + struct drm_privacy_screen *privacy_screen; int err; if (intel_info->require_force_probe && @@ -1092,7 +1094,17 @@ static int i915_pci_probe(struct pci_dev *pdev, const struct pci_device_
[PATCH v2 0/9] drm: Add privacy-screen class and connector properties
Hi All, Here is v2 of my series to add a privacy-screen class and connector properties. The only significantly changed patch in this v2 is: [2/9] drm: Add privacy-screen class (v2) which was modified to fix the dependency issues which the lkp kernel test robot, see the patches changelog for details. Here is the v1 cover-letter which is still up2date: Here is the privacy-screen related code which I last posted in August of last year. To the best of my knowledge there is consensus about / everyone is in agreement with the new userspace API (2 connector properties) this patch-set add (patch 1 of the series). The blocker the last time was that there were no userspace users of the new properties and as a rule we don't add new drm userspace API without users. There now is GNOME userspace code using the new properties: https://hackmd.io/@3v1n0/rkyIy3BOw The new API works as designed for this userspace user and the branches mentioned at the above link add the following features to GNOME: 1. Showing an OSD notification when the privacy-screen is toggled on/off through hotkeys handled by the embedded-controller 2. Allowing control of the privacy-screen from the GNOME control-panel, including the on/off slider shown there updating to match the hw-setting when the setting is changed with the control-panel open. 3. Restoring the last user-setting at login This series consists of a number of different parts: 1. A new version of Rajat's privacy-screen connector properties patch, this adds new userspace API in the form of new properties 2. Since on most devices the privacy screen is actually controlled by some vendor specific ACPI/WMI interface which has a driver under drivers/platform/x86, we need some "glue" code to make this functionality available to KMS drivers. Patches 2-4 add a new privacy-screen class for this, which allows non KMS drivers (and possibly KMS drivers too) to register a privacy-screen device and also adds an interface for KMS drivers to get access to the privacy-screen associated with a specific connector. This is modelled similar to how we deal with e.g. PWMs and GPIOs in the kernel, including separate includes for consumers and providers(drivers). 3. Some drm_connector helper functions to keep the actual changes needed for this in individual KMS drivers as small as possible (patch 5). 4. Make the thinkpad_acpi code register a privacy-screen device on ThinkPads with a privacy-screen (patches 6-8) 5. Make the i915 driver export the privacy-screen functionality through the connector properties on the eDP connector. I believe that it would be best to merge the entire series, including the thinkpad_acpi changes through drm-misc in one go. As the pdx86 subsys maintainer I hereby give my ack for merging the thinkpad_acpi changes through drm-misc. There is one small caveat with this series, which it is good to be aware of. The i915 driver will now return -EPROBE_DEFER on Thinkpads with an eprivacy screen, until the thinkpad_acpi driver is loaded. This means that initrd generation tools will need to be updated to include thinkpad_acpi when the i915 driver is added to the initrd. Without this the loading of the i915 driver will be delayed to after the switch to real rootfs. Regards, Hans Hans de Goede (8): drm: Add privacy-screen class (v2) drm/privacy-screen: Add X86 specific arch init code drm/privacy-screen: Add notifier support drm/connector: Add a drm_connector privacy-screen helper functions platform/x86: thinkpad_acpi: Add hotkey_notify_extended_hotkey() helper platform/x86: thinkpad_acpi: Get privacy-screen / lcdshadow ACPI handles only once platform/x86: thinkpad_acpi: Register a privacy-screen device drm/i915: Add privacy-screen support Rajat Jain (1): drm/connector: Add support for privacy-screen properties (v4) Documentation/gpu/drm-kms-helpers.rst| 15 + Documentation/gpu/drm-kms.rst| 2 + MAINTAINERS | 8 + drivers/gpu/drm/Kconfig | 4 + drivers/gpu/drm/Makefile | 1 + drivers/gpu/drm/drm_atomic_uapi.c| 4 + drivers/gpu/drm/drm_connector.c | 214 + drivers/gpu/drm/drm_drv.c| 4 + drivers/gpu/drm/drm_privacy_screen.c | 468 +++ drivers/gpu/drm/drm_privacy_screen_x86.c | 86 drivers/gpu/drm/i915/display/intel_display.c | 5 + drivers/gpu/drm/i915/display/intel_dp.c | 10 + drivers/gpu/drm/i915/i915_pci.c | 12 + drivers/platform/x86/Kconfig | 2 + drivers/platform/x86/thinkpad_acpi.c | 131 -- include/drm/drm_connector.h | 56 +++ include/drm/drm_privacy_screen_consumer.h| 63 +++ include/drm/drm_privacy_screen_driver.h | 84 include/drm/drm_privacy_screen_machine.h | 46 ++ 19 files changed, 1173 insertions(+), 42 deletions(-) create
[PATCH v2 2/9] drm: Add privacy-screen class (v2)
On some new laptops the LCD panel has a builtin electronic privacy-screen. We want to export this functionality as a property on the drm connector object. But often this functionality is not exposed on the GPU but on some other (ACPI) device. This commit adds a privacy-screen class allowing the driver for these other devices to register themselves as a privacy-screen provider; and allowing the drm/kms code to get a privacy-screen provider associated with a specific GPU/connector combo. Changes in v2: - Make CONFIG_DRM_PRIVACY_SCREEN a bool which controls if the drm_privacy code gets built as part of the main drm module rather then making it a tristate which builds its own module. - Add a #if IS_ENABLED(CONFIG_DRM_PRIVACY_SCREEN) check to drm_privacy_screen_consumer.h and define stubs when the check fails. Together these 2 changes fix several dependency issues. - Remove module related code now that this is part of the main drm.ko - Use drm_class as class for the privacy-screen devices instead of adding a separate class for this Signed-off-by: Hans de Goede --- Documentation/gpu/drm-kms-helpers.rst | 15 + MAINTAINERS | 8 + drivers/gpu/drm/Kconfig | 4 + drivers/gpu/drm/Makefile | 1 + drivers/gpu/drm/drm_drv.c | 4 + drivers/gpu/drm/drm_privacy_screen.c | 401 ++ include/drm/drm_privacy_screen_consumer.h | 48 +++ include/drm/drm_privacy_screen_driver.h | 80 + include/drm/drm_privacy_screen_machine.h | 41 +++ 9 files changed, 602 insertions(+) create mode 100644 drivers/gpu/drm/drm_privacy_screen.c create mode 100644 include/drm/drm_privacy_screen_consumer.h create mode 100644 include/drm/drm_privacy_screen_driver.h create mode 100644 include/drm/drm_privacy_screen_machine.h diff --git a/Documentation/gpu/drm-kms-helpers.rst b/Documentation/gpu/drm-kms-helpers.rst index 389892f36185..5d8715d2f998 100644 --- a/Documentation/gpu/drm-kms-helpers.rst +++ b/Documentation/gpu/drm-kms-helpers.rst @@ -423,3 +423,18 @@ Legacy CRTC/Modeset Helper Functions Reference .. kernel-doc:: drivers/gpu/drm/drm_crtc_helper.c :export: + +Privacy-screen class + + +.. kernel-doc:: drivers/gpu/drm/drm_privacy_screen.c + :doc: overview + +.. kernel-doc:: include/drm/drm_privacy_screen_driver.h + :internal: + +.. kernel-doc:: include/drm/drm_privacy_screen_machine.h + :internal: + +.. kernel-doc:: drivers/gpu/drm/drm_privacy_screen.c + :export: diff --git a/MAINTAINERS b/MAINTAINERS index 0c91cd07db3a..5d3e7729e57c 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -6131,6 +6131,14 @@ F: drivers/gpu/drm/drm_panel.c F: drivers/gpu/drm/panel/ F: include/drm/drm_panel.h +DRM PRIVACY-SCREEN CLASS +M: Hans de Goede +L: dri-devel@lists.freedesktop.org +S: Maintained +T: git git://anongit.freedesktop.org/drm/drm-misc +F: drivers/gpu/drm/drm_privacy_screen* +F: include/drm/drm_privacy_screen* + DRM TTM SUBSYSTEM M: Christian Koenig M: Huang Rui diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig index 3c16bd1afd87..698ea8a32b2a 100644 --- a/drivers/gpu/drm/Kconfig +++ b/drivers/gpu/drm/Kconfig @@ -474,3 +474,7 @@ config DRM_PANEL_ORIENTATION_QUIRKS config DRM_LIB_RANDOM bool default n + +config DRM_PRIVACY_SCREEN + bool + default n diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile index 89e747fedc00..578853d18a3d 100644 --- a/drivers/gpu/drm/Makefile +++ b/drivers/gpu/drm/Makefile @@ -32,6 +32,7 @@ drm-$(CONFIG_AGP) += drm_agpsupport.o drm-$(CONFIG_PCI) += drm_pci.o drm-$(CONFIG_DEBUG_FS) += drm_debugfs.o drm_debugfs_crc.o drm-$(CONFIG_DRM_LOAD_EDID_FIRMWARE) += drm_edid_load.o +drm-$(CONFIG_DRM_PRIVACY_SCREEN) += drm_privacy_screen.o drm_vram_helper-y := drm_gem_vram_helper.o obj-$(CONFIG_DRM_VRAM_HELPER) += drm_vram_helper.o diff --git a/drivers/gpu/drm/drm_drv.c b/drivers/gpu/drm/drm_drv.c index c2f78dee9f2d..b33baa888be4 100644 --- a/drivers/gpu/drm/drm_drv.c +++ b/drivers/gpu/drm/drm_drv.c @@ -42,6 +42,7 @@ #include #include #include +#include #include "drm_crtc_internal.h" #include "drm_internal.h" @@ -1030,6 +1031,7 @@ static const struct file_operations drm_stub_fops = { static void drm_core_exit(void) { + drm_privacy_screen_lookup_exit(); unregister_chrdev(DRM_MAJOR, "drm"); debugfs_remove(drm_debugfs_root); drm_sysfs_destroy(); @@ -1056,6 +1058,8 @@ static int __init drm_core_init(void) if (ret < 0) goto error; + drm_privacy_screen_lookup_init(); + drm_core_init_complete = true; DRM_DEBUG("Initialized\n"); diff --git a/drivers/gpu/drm/drm_privacy_screen.c b/drivers/gpu/drm/drm_privacy_screen.c new file mode 100644 index ..294a09194bfb --- /dev/null +++ b/drivers/gpu/drm/drm_privacy_
[PATCH v2 1/9] drm/connector: Add support for privacy-screen properties (v4)
From: Rajat Jain Add support for generic electronic privacy screen properties, that can be added by systems that have an integrated EPS. Changes in v2 (Hans de Goede) - Create 2 properties, "privacy-screen sw-state" and "privacy-screen hw-state", to deal with devices where the OS might be locked out of making state changes - Write kerneldoc explaining how the 2 properties work together, what happens when changes to the state are made outside of the DRM code's control, etc. Changes in v3 (Hans de Goede) - Some small tweaks to the kerneldoc describing the 2 properties Changes in v4 (Hans de Goede) - Change the "Enabled, locked" and "Disabled, locked" hw-state enum value names to "Enabled-locked" and "Disabled-locked". The xrandr command shows all possible enum values separated by commas in its output, so having a comma in an enum name is not a good idea. - Do not add a privacy_screen_hw_state member to drm_connector_state since this property is immutable its value must be directly stored in the obj->properties->values array Signed-off-by: Rajat Jain Co-authored-by: Hans de Goede Acked-by: Pekka Paalanen Reviewed-by: Mario Limonciello Signed-off-by: Hans de Goede --- Documentation/gpu/drm-kms.rst | 2 + drivers/gpu/drm/drm_atomic_uapi.c | 4 ++ drivers/gpu/drm/drm_connector.c | 101 ++ include/drm/drm_connector.h | 44 + 4 files changed, 151 insertions(+) diff --git a/Documentation/gpu/drm-kms.rst b/Documentation/gpu/drm-kms.rst index 87e5023e3f55..36943f2b0c5d 100644 --- a/Documentation/gpu/drm-kms.rst +++ b/Documentation/gpu/drm-kms.rst @@ -475,6 +475,8 @@ Property Types and Blob Property Support .. kernel-doc:: drivers/gpu/drm/drm_property.c :export: +.. _standard_connector_properties: + Standard Connector Properties - diff --git a/drivers/gpu/drm/drm_atomic_uapi.c b/drivers/gpu/drm/drm_atomic_uapi.c index 268bb69c2e2f..d5339b683156 100644 --- a/drivers/gpu/drm/drm_atomic_uapi.c +++ b/drivers/gpu/drm/drm_atomic_uapi.c @@ -796,6 +796,8 @@ static int drm_atomic_connector_set_property(struct drm_connector *connector, fence_ptr); } else if (property == connector->max_bpc_property) { state->max_requested_bpc = val; + } else if (property == connector->privacy_screen_sw_state_property) { + state->privacy_screen_sw_state = val; } else if (connector->funcs->atomic_set_property) { return connector->funcs->atomic_set_property(connector, state, property, val); @@ -873,6 +875,8 @@ drm_atomic_connector_get_property(struct drm_connector *connector, *val = 0; } else if (property == connector->max_bpc_property) { *val = state->max_requested_bpc; + } else if (property == connector->privacy_screen_sw_state_property) { + *val = state->privacy_screen_sw_state; } else if (connector->funcs->atomic_get_property) { return connector->funcs->atomic_get_property(connector, state, property, val); diff --git a/drivers/gpu/drm/drm_connector.c b/drivers/gpu/drm/drm_connector.c index 7631f76e7f34..ca8a76decd4c 100644 --- a/drivers/gpu/drm/drm_connector.c +++ b/drivers/gpu/drm/drm_connector.c @@ -1244,6 +1244,46 @@ static const struct drm_prop_enum_list dp_colorspaces[] = { * For DVI-I and TVout there is also a matching property "select subconnector" * allowing to switch between signal types. * DP subconnector corresponds to a downstream port. + * + * privacy-screen sw-state, privacy-screen hw-state: + * These 2 optional properties can be used to query the state of the + * electronic privacy screen that is available on some displays; and in + * some cases also control the state. If a driver implements these + * properties then both properties must be present. + * + * "privacy-screen hw-state" is read-only and reflects the actual state + * of the privacy-screen, possible values: "Enabled", "Disabled, + * "Enabled-locked", "Disabled-locked". The locked states indicate + * that the state cannot be changed through the DRM API. E.g. there + * might be devices where the firmware-setup options, or a hardware + * slider-switch, offer always on / off modes. + * + * "privacy-screen sw-state" can be set to change the privacy-screen state + * when not locked. In this case the driver must update the hw-state + * property to reflect the new state on completion of the commit of the + * sw-state property. Setting the sw-state property when the hw-state is + * locked must be interpreted by the driver as a
[PATCH v2 3/9] drm/privacy-screen: Add X86 specific arch init code
Add X86 specific arch init code, which fills the privacy-screen lookup table by checking for various vendor specific ACPI interfaces for controlling the privacy-screen. This initial version only checks for the Lenovo Thinkpad specific ACPI methods for privacy-screen control. Signed-off-by: Hans de Goede --- drivers/gpu/drm/Makefile | 2 +- drivers/gpu/drm/drm_privacy_screen_x86.c | 86 include/drm/drm_privacy_screen_machine.h | 5 ++ 3 files changed, 92 insertions(+), 1 deletion(-) create mode 100644 drivers/gpu/drm/drm_privacy_screen_x86.c diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile index 578853d18a3d..2e226b57de24 100644 --- a/drivers/gpu/drm/Makefile +++ b/drivers/gpu/drm/Makefile @@ -32,7 +32,7 @@ drm-$(CONFIG_AGP) += drm_agpsupport.o drm-$(CONFIG_PCI) += drm_pci.o drm-$(CONFIG_DEBUG_FS) += drm_debugfs.o drm_debugfs_crc.o drm-$(CONFIG_DRM_LOAD_EDID_FIRMWARE) += drm_edid_load.o -drm-$(CONFIG_DRM_PRIVACY_SCREEN) += drm_privacy_screen.o +drm-$(CONFIG_DRM_PRIVACY_SCREEN) += drm_privacy_screen.o drm_privacy_screen_x86.o drm_vram_helper-y := drm_gem_vram_helper.o obj-$(CONFIG_DRM_VRAM_HELPER) += drm_vram_helper.o diff --git a/drivers/gpu/drm/drm_privacy_screen_x86.c b/drivers/gpu/drm/drm_privacy_screen_x86.c new file mode 100644 index ..a2cafb294ca6 --- /dev/null +++ b/drivers/gpu/drm/drm_privacy_screen_x86.c @@ -0,0 +1,86 @@ +// SPDX-License-Identifier: MIT +/* + * Copyright (C) 2020 Red Hat, Inc. + * + * Authors: + * Hans de Goede + */ + +#include +#include + +#ifdef CONFIG_X86 +static struct drm_privacy_screen_lookup arch_lookup; + +struct arch_init_data { + struct drm_privacy_screen_lookup lookup; + bool (*detect)(void); +}; + +#if IS_ENABLED(CONFIG_THINKPAD_ACPI) +static acpi_status __init acpi_set_handle(acpi_handle handle, u32 level, + void *context, void **return_value) +{ + *(acpi_handle *)return_value = handle; + return AE_CTRL_TERMINATE; +} + +static bool __init detect_thinkpad_privacy_screen(void) +{ + union acpi_object obj = { .type = ACPI_TYPE_INTEGER }; + struct acpi_object_list args = { .count = 1, .pointer = &obj, }; + acpi_handle ec_handle = NULL; + unsigned long long output; + acpi_status status; + + /* Get embedded-controller handle */ + status = acpi_get_devices("PNP0C09", acpi_set_handle, NULL, &ec_handle); + if (ACPI_FAILURE(status) || !ec_handle) + return false; + + /* And call the privacy-screen get-status method */ + status = acpi_evaluate_integer(ec_handle, "HKEY.GSSS", &args, &output); + if (ACPI_FAILURE(status)) + return false; + + return (output & 0x1) ? true : false; +} +#endif + +static const struct arch_init_data arch_init_data[] __initconst = { +#if IS_ENABLED(CONFIG_THINKPAD_ACPI) + { + .lookup = { + .dev_id = NULL, + .con_id = NULL, + .provider = "privacy_screen-thinkpad_acpi", + }, + .detect = detect_thinkpad_privacy_screen, + }, +#endif +}; + +void __init drm_privacy_screen_lookup_init(void) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(arch_init_data); i++) { + if (!arch_init_data[i].detect()) + continue; + + pr_info("Found '%s' privacy-screen provider\n", + arch_init_data[i].lookup.provider); + + /* Make a copy because arch_init_data is __initconst */ + arch_lookup = arch_init_data[i].lookup; + drm_privacy_screen_lookup_add(&arch_lookup); + break; + } +} + +void drm_privacy_screen_lookup_exit(void) +{ + if (arch_lookup.provider) + drm_privacy_screen_lookup_remove(&arch_lookup); +} +#endif /* ifdef CONFIG_X86 */ diff --git a/include/drm/drm_privacy_screen_machine.h b/include/drm/drm_privacy_screen_machine.h index aaa0d38cce92..02e5371904d3 100644 --- a/include/drm/drm_privacy_screen_machine.h +++ b/include/drm/drm_privacy_screen_machine.h @@ -31,11 +31,16 @@ struct drm_privacy_screen_lookup { void drm_privacy_screen_lookup_add(struct drm_privacy_screen_lookup *lookup); void drm_privacy_screen_lookup_remove(struct drm_privacy_screen_lookup *lookup); +#if IS_ENABLED(CONFIG_DRM_PRIVACY_SCREEN) && IS_ENABLED(CONFIG_X86) +void drm_privacy_screen_lookup_init(void); +void drm_privacy_screen_lookup_exit(void); +#else static inline void drm_privacy_screen_lookup_init(void) { } static inline void drm_privacy_screen_lookup_exit(void) { } +#endif #endif -- 2.31.1 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH v2 4/9] drm/privacy-screen: Add notifier support
Add support for privacy-screen consumers to register a notifier to be notified of external (e.g. done by the hw itself on a hotkey press) state changes. Signed-off-by: Hans de Goede --- drivers/gpu/drm/drm_privacy_screen.c | 67 +++ include/drm/drm_privacy_screen_consumer.h | 15 + include/drm/drm_privacy_screen_driver.h | 4 ++ 3 files changed, 86 insertions(+) diff --git a/drivers/gpu/drm/drm_privacy_screen.c b/drivers/gpu/drm/drm_privacy_screen.c index 294a09194bfb..7a5f878c3171 100644 --- a/drivers/gpu/drm/drm_privacy_screen.c +++ b/drivers/gpu/drm/drm_privacy_screen.c @@ -255,6 +255,49 @@ void drm_privacy_screen_get_state(struct drm_privacy_screen *priv, } EXPORT_SYMBOL(drm_privacy_screen_get_state); +/** + * drm_privacy_screen_register_notifier - register a notifier + * @priv: Privacy screen to register the notifier with + * @nb: Notifier-block for the notifier to register + * + * Register a notifier with the privacy-screen to be notified of changes made + * to the privacy-screen state from outside of the privacy-screen class. + * E.g. the state may be changed by the hardware itself in response to a + * hotkey press. + * + * The notifier is called with no locks held. The new hw_state and sw_state + * can be retrieved using the drm_privacy_screen_get_state() function. + * A pointer to the drm_privacy_screen's struct is passed as the void *data + * argument of the notifier_block's notifier_call. + * + * The notifier will NOT be called when changes are made through + * drm_privacy_screen_set_sw_state(). It is only called for external changes. + * + * Return: 0 on success, negative error code on failure. + */ +int drm_privacy_screen_register_notifier(struct drm_privacy_screen *priv, +struct notifier_block *nb) +{ + return blocking_notifier_chain_register(&priv->notifier_head, nb); +} +EXPORT_SYMBOL(drm_privacy_screen_register_notifier); + +/** + * drm_privacy_screen_unregister_notifier - unregister a notifier + * @priv: Privacy screen to register the notifier with + * @nb: Notifier-block for the notifier to register + * + * Unregister a notifier registered with drm_privacy_screen_register_notifier(). + * + * Return: 0 on success, negative error code on failure. + */ +int drm_privacy_screen_unregister_notifier(struct drm_privacy_screen *priv, + struct notifier_block *nb) +{ + return blocking_notifier_chain_unregister(&priv->notifier_head, nb); +} +EXPORT_SYMBOL(drm_privacy_screen_unregister_notifier); + /*** drm_privacy_screen_driver.h functions ***/ static ssize_t sw_state_show(struct device *dev, @@ -352,6 +395,7 @@ struct drm_privacy_screen *drm_privacy_screen_register( return ERR_PTR(-ENOMEM); mutex_init(&priv->lock); + BLOCKING_INIT_NOTIFIER_HEAD(&priv->notifier_head); priv->dev.class = drm_class; priv->dev.type = &drm_privacy_screen_type; @@ -399,3 +443,26 @@ void drm_privacy_screen_unregister(struct drm_privacy_screen *priv) device_unregister(&priv->dev); } EXPORT_SYMBOL(drm_privacy_screen_unregister); + +/** + * drm_privacy_screen_call_notifier_chain - notify consumers of state change + * @priv: Privacy screen to register the notifier with + * + * A privacy-screen provider driver can call this functions upon external + * changes to the privacy-screen state. E.g. the state may be changed by the + * hardware itself in response to a hotkey press. + * This function must be called without holding the privacy-screen lock. + * the driver must update sw_state and hw_state to reflect the new state before + * calling this function. + * The expected behavior from the driver upon receiving an external state + * change event is: 1. Take the lock; 2. Update sw_state and hw_state; + * 3. Release the lock. 4. Call drm_privacy_screen_call_notifier_chain(). + */ +void drm_privacy_screen_call_notifier_chain(struct drm_privacy_screen *priv) +{ + if (WARN_ON(mutex_is_locked(&priv->lock))) + return; + + blocking_notifier_call_chain(&priv->notifier_head, 0, priv); +} +EXPORT_SYMBOL(drm_privacy_screen_call_notifier_chain); diff --git a/include/drm/drm_privacy_screen_consumer.h b/include/drm/drm_privacy_screen_consumer.h index 941c88b46889..31746a745439 100644 --- a/include/drm/drm_privacy_screen_consumer.h +++ b/include/drm/drm_privacy_screen_consumer.h @@ -24,6 +24,11 @@ int drm_privacy_screen_set_sw_state(struct drm_privacy_screen *priv, void drm_privacy_screen_get_state(struct drm_privacy_screen *priv, enum drm_privacy_screen_status *sw_state_ret, enum drm_privacy_screen_status *hw_state_ret); + +int drm_privacy_screen_register_notifier(struct drm_privacy_screen *priv, +struct notifier_block *nb); +int d
[PATCH v2 6/9] platform/x86: thinkpad_acpi: Add hotkey_notify_extended_hotkey() helper
Factor the extended hotkey handling out of hotkey_notify_hotkey() and into a new hotkey_notify_extended_hotkey() helper. This is a preparation patch for adding support the privacy-screen hotkey toggle (which needs some special handling, it should NOT send an evdev key-event to userspace...). Signed-off-by: Hans de Goede --- drivers/platform/x86/thinkpad_acpi.c | 30 ++-- 1 file changed, 19 insertions(+), 11 deletions(-) diff --git a/drivers/platform/x86/thinkpad_acpi.c b/drivers/platform/x86/thinkpad_acpi.c index 0d9e2ddbf904..683c175cc28a 100644 --- a/drivers/platform/x86/thinkpad_acpi.c +++ b/drivers/platform/x86/thinkpad_acpi.c @@ -3878,6 +3878,24 @@ static bool adaptive_keyboard_hotkey_notify_hotkey(unsigned int scancode) } } +static bool hotkey_notify_extended_hotkey(const u32 hkey) +{ + unsigned int scancode; + + /* Extended keycodes start at 0x300 and our offset into the map +* TP_ACPI_HOTKEYSCAN_EXTENDED_START. The calculated scancode +* will be positive, but might not be in the correct range. +*/ + scancode = (hkey & 0xfff) - (0x300 - TP_ACPI_HOTKEYSCAN_EXTENDED_START); + if (scancode >= TP_ACPI_HOTKEYSCAN_EXTENDED_START && + scancode < TPACPI_HOTKEY_MAP_LEN) { + tpacpi_input_send_key(scancode); + return true; + } + + return false; +} + static bool hotkey_notify_hotkey(const u32 hkey, bool *send_acpi_ev, bool *ignore_acpi_ev) @@ -3912,17 +3930,7 @@ static bool hotkey_notify_hotkey(const u32 hkey, return adaptive_keyboard_hotkey_notify_hotkey(scancode); case 3: - /* Extended keycodes start at 0x300 and our offset into the map -* TP_ACPI_HOTKEYSCAN_EXTENDED_START. The calculated scancode -* will be positive, but might not be in the correct range. -*/ - scancode -= (0x300 - TP_ACPI_HOTKEYSCAN_EXTENDED_START); - if (scancode >= TP_ACPI_HOTKEYSCAN_EXTENDED_START && - scancode < TPACPI_HOTKEY_MAP_LEN) { - tpacpi_input_send_key(scancode); - return true; - } - break; + return hotkey_notify_extended_hotkey(hkey); } return false; -- 2.31.1 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH v2 7/9] platform/x86: thinkpad_acpi: Get privacy-screen / lcdshadow ACPI handles only once
Get the privacy-screen / lcdshadow ACPI handles once and cache them, instead of retrieving them every time we need them. Signed-off-by: Hans de Goede --- drivers/platform/x86/thinkpad_acpi.c | 18 -- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/drivers/platform/x86/thinkpad_acpi.c b/drivers/platform/x86/thinkpad_acpi.c index 683c175cc28a..fe919700b8ae 100644 --- a/drivers/platform/x86/thinkpad_acpi.c +++ b/drivers/platform/x86/thinkpad_acpi.c @@ -9759,19 +9759,15 @@ static struct ibm_struct battery_driver_data = { * LCD Shadow subdriver, for the Lenovo PrivacyGuard feature */ +static acpi_handle lcdshadow_get_handle; +static acpi_handle lcdshadow_set_handle; static int lcdshadow_state; static int lcdshadow_on_off(bool state) { - acpi_handle set_shadow_handle; int output; - if (ACPI_FAILURE(acpi_get_handle(hkey_handle, "", &set_shadow_handle))) { - pr_warn("Thinkpad ACPI has no %s interface.\n", ""); - return -EIO; - } - - if (!acpi_evalf(set_shadow_handle, &output, NULL, "dd", (int)state)) + if (!acpi_evalf(lcdshadow_set_handle, &output, NULL, "dd", (int)state)) return -EIO; lcdshadow_state = state; @@ -9789,15 +9785,17 @@ static int lcdshadow_set(bool on) static int tpacpi_lcdshadow_init(struct ibm_init_struct *iibm) { - acpi_handle get_shadow_handle; + acpi_status status1, status2; int output; - if (ACPI_FAILURE(acpi_get_handle(hkey_handle, "GSSS", &get_shadow_handle))) { + status1 = acpi_get_handle(hkey_handle, "GSSS", &lcdshadow_get_handle); + status2 = acpi_get_handle(hkey_handle, "", &lcdshadow_set_handle); + if (ACPI_FAILURE(status1) || ACPI_FAILURE(status2)) { lcdshadow_state = -ENODEV; return 0; } - if (!acpi_evalf(get_shadow_handle, &output, NULL, "dd", 0)) { + if (!acpi_evalf(lcdshadow_get_handle, &output, NULL, "dd", 0)) { lcdshadow_state = -EIO; return -EIO; } -- 2.31.1 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH v2 5/9] drm/connector: Add a drm_connector privacy-screen helper functions
Add 2 drm_connector privacy-screen helper functions: 1. drm_connector_attach_privacy_screen_provider(), this function creates and attaches the standard privacy-screen properties and registers a generic notifier for generating sysfs-connector-status-events on external changes to the privacy-screen status. 2. drm_connector_update_privacy_screen(), Check if the passed in atomic state contains a privacy-screen sw_state change for the connector and if it does, call drm_privacy_screen_set_sw_state() with the new sw_state. Signed-off-by: Hans de Goede --- drivers/gpu/drm/drm_connector.c | 113 include/drm/drm_connector.h | 12 2 files changed, 125 insertions(+) diff --git a/drivers/gpu/drm/drm_connector.c b/drivers/gpu/drm/drm_connector.c index ca8a76decd4c..958a332374af 100644 --- a/drivers/gpu/drm/drm_connector.c +++ b/drivers/gpu/drm/drm_connector.c @@ -20,6 +20,7 @@ * OF THIS SOFTWARE. */ +#include #include #include #include @@ -27,6 +28,7 @@ #include #include #include +#include #include #include @@ -451,6 +453,11 @@ void drm_connector_cleanup(struct drm_connector *connector) DRM_CONNECTOR_REGISTERED)) drm_connector_unregister(connector); + if (connector->privacy_screen) { + drm_privacy_screen_put(connector->privacy_screen); + connector->privacy_screen = NULL; + } + if (connector->tile_group) { drm_mode_put_tile_group(dev, connector->tile_group); connector->tile_group = NULL; @@ -530,6 +537,10 @@ int drm_connector_register(struct drm_connector *connector) /* Let userspace know we have a new connector */ drm_sysfs_hotplug_event(connector->dev); + if (connector->privacy_screen) + drm_privacy_screen_register_notifier(connector->privacy_screen, + &connector->privacy_screen_notifier); + goto unlock; err_debugfs: @@ -558,6 +569,11 @@ void drm_connector_unregister(struct drm_connector *connector) return; } + if (connector->privacy_screen) + drm_privacy_screen_unregister_notifier( + connector->privacy_screen, + &connector->privacy_screen_notifier); + if (connector->funcs->early_unregister) connector->funcs->early_unregister(connector); @@ -2353,6 +2369,103 @@ drm_connector_attach_privacy_screen_properties(struct drm_connector *connector) } EXPORT_SYMBOL(drm_connector_attach_privacy_screen_properties); +static void drm_connector_update_privacy_screen_properties( + struct drm_connector *connector) +{ + enum drm_privacy_screen_status sw_state, hw_state; + + drm_privacy_screen_get_state(connector->privacy_screen, +&sw_state, &hw_state); + + connector->state->privacy_screen_sw_state = sw_state; + drm_object_property_set_value(&connector->base, + connector->privacy_screen_hw_state_property, hw_state); +} + +static int drm_connector_privacy_screen_notifier( + struct notifier_block *nb, unsigned long action, void *data) +{ + struct drm_connector *connector = + container_of(nb, struct drm_connector, privacy_screen_notifier); + struct drm_device *dev = connector->dev; + + drm_modeset_lock(&dev->mode_config.connection_mutex, NULL); + drm_connector_update_privacy_screen_properties(connector); + drm_modeset_unlock(&dev->mode_config.connection_mutex); + + drm_sysfs_connector_status_event(connector, + connector->privacy_screen_sw_state_property); + drm_sysfs_connector_status_event(connector, + connector->privacy_screen_hw_state_property); + + return NOTIFY_DONE; +} + +/** + * drm_connector_attach_privacy_screen_provider - attach a privacy-screen to + *the connector + * @connector: connector to attach the privacy-screen to + * @priv: drm_privacy_screen to attach + * + * Create and attach the standard privacy-screen properties and register + * a generic notifier for generating sysfs-connector-status-events + * on external changes to the privacy-screen status. + * This function takes ownership of the passed in drm_privacy_screen and will + * call drm_privacy_screen_put() on it when the connector is destroyed. + */ +void drm_connector_attach_privacy_screen_provider( + struct drm_connector *connector, struct drm_privacy_screen *priv) +{ + connector->privacy_screen = priv; + connector->privacy_screen_notifier.notifier_call = + drm_connector_privacy_screen_notifier; + + drm_connector_create_privacy_screen_properties(connector); +
[PATCH v2 8/9] platform/x86: thinkpad_acpi: Register a privacy-screen device
Register a privacy-screen device on laptops with a privacy-screen, this exports the PrivacyGuard features to user-space using a standardized vendor-agnostic sysfs interface. Note the sysfs interface is read-only. Registering a privacy-screen device with the new privacy-screen class code will also allow the GPU driver to get a handle to it and export the privacy-screen setting as a property on the DRM connector object for the LCD panel. This DRM connector property is news standardized interface which all user-space code should use to query and control the privacy-screen. Signed-off-by: Hans de Goede --- Changes in v2: - Make the new lcdshadow_set_sw_state, lcdshadow_get_hw_state and lcdshadow_ops symbols static - Update state and call drm_privacy_screen_call_notifier_chain() when the state is changed by pressing the Fn + D hotkey combo --- drivers/platform/x86/Kconfig | 2 + drivers/platform/x86/thinkpad_acpi.c | 91 2 files changed, 68 insertions(+), 25 deletions(-) diff --git a/drivers/platform/x86/Kconfig b/drivers/platform/x86/Kconfig index 461ec61530eb..ae49f1658aba 100644 --- a/drivers/platform/x86/Kconfig +++ b/drivers/platform/x86/Kconfig @@ -484,7 +484,9 @@ config THINKPAD_ACPI depends on RFKILL || RFKILL = n depends on ACPI_VIDEO || ACPI_VIDEO = n depends on BACKLIGHT_CLASS_DEVICE + depends on DRM select ACPI_PLATFORM_PROFILE + select DRM_PRIVACY_SCREEN select HWMON select NVRAM select NEW_LEDS diff --git a/drivers/platform/x86/thinkpad_acpi.c b/drivers/platform/x86/thinkpad_acpi.c index fe919700b8ae..766c6d64b0fb 100644 --- a/drivers/platform/x86/thinkpad_acpi.c +++ b/drivers/platform/x86/thinkpad_acpi.c @@ -73,6 +73,7 @@ #include #include #include +#include /* ThinkPad CMOS commands */ #define TP_CMOS_VOLUME_DOWN0 @@ -156,6 +157,7 @@ enum tpacpi_hkey_event_t { TP_HKEY_EV_VOL_UP = 0x1015, /* Volume up or unmute */ TP_HKEY_EV_VOL_DOWN = 0x1016, /* Volume down or unmute */ TP_HKEY_EV_VOL_MUTE = 0x1017, /* Mixer output mute */ + TP_HKEY_EV_PRIVACYGUARD_TOGGLE = 0x130f, /* Toggle priv.guard on/off */ /* Reasons for waking up from S3/S4 */ TP_HKEY_EV_WKUP_S3_UNDOCK = 0x2304, /* undock requested, S3 */ @@ -3882,6 +3884,12 @@ static bool hotkey_notify_extended_hotkey(const u32 hkey) { unsigned int scancode; + switch (hkey) { + case TP_HKEY_EV_PRIVACYGUARD_TOGGLE: + tpacpi_driver_event(hkey); + return true; + } + /* Extended keycodes start at 0x300 and our offset into the map * TP_ACPI_HOTKEYSCAN_EXTENDED_START. The calculated scancode * will be positive, but might not be in the correct range. @@ -9759,30 +9767,40 @@ static struct ibm_struct battery_driver_data = { * LCD Shadow subdriver, for the Lenovo PrivacyGuard feature */ +static struct drm_privacy_screen *lcdshadow_dev; static acpi_handle lcdshadow_get_handle; static acpi_handle lcdshadow_set_handle; -static int lcdshadow_state; -static int lcdshadow_on_off(bool state) +static int lcdshadow_set_sw_state(struct drm_privacy_screen *priv, + enum drm_privacy_screen_status state) { int output; + if (WARN_ON(!mutex_is_locked(&priv->lock))) + return -EIO; + if (!acpi_evalf(lcdshadow_set_handle, &output, NULL, "dd", (int)state)) return -EIO; - lcdshadow_state = state; + priv->hw_state = priv->sw_state = state; return 0; } -static int lcdshadow_set(bool on) +static void lcdshadow_get_hw_state(struct drm_privacy_screen *priv) { - if (lcdshadow_state < 0) - return lcdshadow_state; - if (lcdshadow_state == on) - return 0; - return lcdshadow_on_off(on); + int output; + + if (!acpi_evalf(lcdshadow_get_handle, &output, NULL, "dd", 0)) + return; + + priv->hw_state = priv->sw_state = output & 0x1; } +static const struct drm_privacy_screen_ops lcdshadow_ops = { + .set_sw_state = lcdshadow_set_sw_state, + .get_hw_state = lcdshadow_get_hw_state, +}; + static int tpacpi_lcdshadow_init(struct ibm_init_struct *iibm) { acpi_status status1, status2; @@ -9790,36 +9808,44 @@ static int tpacpi_lcdshadow_init(struct ibm_init_struct *iibm) status1 = acpi_get_handle(hkey_handle, "GSSS", &lcdshadow_get_handle); status2 = acpi_get_handle(hkey_handle, "", &lcdshadow_set_handle); - if (ACPI_FAILURE(status1) || ACPI_FAILURE(status2)) { - lcdshadow_state = -ENODEV; + if (ACPI_FAILURE(status1) || ACPI_FAILURE(status2)) return 0; - } - if (!acpi_evalf(lcdshadow_get_handle, &output, NULL, "dd&q
[PATCH v2 9/9] drm/i915: Add privacy-screen support
Add support for eDP panels with a built-in privacy screen using the new drm_privacy_screen class. One thing which stands out here is the addition of these 2 lines to intel_atomic_commit_tail: for_each_new_connector_in_state(&state->base, connector, ... drm_connector_update_privacy_screen(connector, state); It may seem more logical to instead take care of updating the privacy-screen state by marking the crtc as needing a modeset and then do this in both the encoder update_pipe (for fast-sets) and enable (for full modesets) callbacks. But ATM these callbacks only get passed the new connector_state and these callbacks are all called after drm_atomic_helper_swap_state() at which point there is no way to get the old state from the new state. Without access to the old state, we do not know if the sw_state of the privacy-screen has changes so we would need to call drm_privacy_screen_set_sw_state() unconditionally. This is undesirable since all current known privacy-screen providers use ACPI calls which are somewhat expensive to make. Also, as all providers use ACPI calls, rather then poking GPU registers, there is no need to order this together with other encoder operations. Since no GPU poking is involved having this as a separate step of the commit process actually is the logical thing to do. Signed-off-by: Hans de Goede --- drivers/gpu/drm/i915/display/intel_display.c | 5 + drivers/gpu/drm/i915/display/intel_dp.c | 10 ++ drivers/gpu/drm/i915/i915_pci.c | 12 3 files changed, 27 insertions(+) diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index a10e26380ef3..b11fcc660446 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -10159,6 +10159,8 @@ static void intel_atomic_commit_tail(struct intel_atomic_state *state) struct drm_device *dev = state->base.dev; struct drm_i915_private *dev_priv = to_i915(dev); struct intel_crtc_state *new_crtc_state, *old_crtc_state; + struct drm_connector_state *new_connector_state; + struct drm_connector *connector; struct intel_crtc *crtc; u64 put_domains[I915_MAX_PIPES] = {}; intel_wakeref_t wakeref = 0; @@ -10256,6 +10258,9 @@ static void intel_atomic_commit_tail(struct intel_atomic_state *state) intel_color_load_luts(new_crtc_state); } + for_each_new_connector_in_state(&state->base, connector, new_connector_state, i) + drm_connector_update_privacy_screen(connector, &state->base); + /* * Now that the vblank has passed, we can go ahead and program the * optimal watermarks on platforms that need two-step watermark diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c index 52ea09fc5e70..57864782d922 100644 --- a/drivers/gpu/drm/i915/display/intel_dp.c +++ b/drivers/gpu/drm/i915/display/intel_dp.c @@ -37,6 +37,7 @@ #include #include #include +#include #include #include "g4x_dp.h" @@ -5178,6 +5179,7 @@ static bool intel_edp_init_connector(struct intel_dp *intel_dp, struct drm_connector *connector = &intel_connector->base; struct drm_display_mode *fixed_mode = NULL; struct drm_display_mode *downclock_mode = NULL; + struct drm_privacy_screen *privacy_screen; bool has_dpcd; enum pipe pipe = INVALID_PIPE; struct edid *edid; @@ -5268,6 +5270,14 @@ static bool intel_edp_init_connector(struct intel_dp *intel_dp, fixed_mode->hdisplay, fixed_mode->vdisplay); } + privacy_screen = drm_privacy_screen_get(&dev->pdev->dev, NULL); + if (!IS_ERR(privacy_screen)) { + drm_connector_attach_privacy_screen_provider(connector, +privacy_screen); + } else if (PTR_ERR(privacy_screen) != -ENODEV) { + drm_warn(&dev_priv->drm, "Error getting privacy-screen\n"); + } + return true; out_vdd_off: diff --git a/drivers/gpu/drm/i915/i915_pci.c b/drivers/gpu/drm/i915/i915_pci.c index 7786217638ed..09d52ecc3713 100644 --- a/drivers/gpu/drm/i915/i915_pci.c +++ b/drivers/gpu/drm/i915/i915_pci.c @@ -26,6 +26,7 @@ #include #include +#include #include #include "display/intel_fbdev.h" @@ -1067,6 +1068,7 @@ static int i915_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) { struct intel_device_info *intel_info = (struct intel_device_info *) ent->driver_data; + struct drm_privacy_screen *privacy_screen; int err; if (intel_info->require_force_probe && @@ -1095,7 +1097,17 @@ static int i915_pci_probe(struct pci_dev *pdev, const struct pci_device_
Re: [PATCH v2 0/9] drm: Add privacy-screen class and connector properties
Hi, On 4/22/21 10:51 AM, Simon Ser wrote: > Hi, > > On Wednesday, April 21st, 2021 at 10:47 PM, Hans de Goede > wrote: > >> There now is GNOME userspace code using the new properties: >> https://hackmd.io/@3v1n0/rkyIy3BOw > > Thanks for working on this. > > Can these patches be submitted as merge requests against the upstream > projects? It would be nice to get some feedback from the maintainers, > and be able to easily leave some comments there as well. I guess Marco was waiting for the kernel bits too land before submitting these, but I agree that it would probably be good to have these submitted now, we can mark them as WIP to avoid them getting merged before the kernel side is finalized. Marco, can you take care of submitting WIP merge-reqs for these? Regards, Hans ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH 0/9] drm + usb-type-c: Add support for out-of-band hotplug notification
Hi All, Here is a new attempt to make DP over Type-C work on devices where the Type-C controller does not drive the HPD pin on the GPU, but instead we need to forward HPD events from the Type-C controller to the DRM driver. For anyone interested here are the old (2019!) patches for this: https://patchwork.freedesktop.org/patch/288491/ https://patchwork.freedesktop.org/patch/288493/ https://patchwork.freedesktop.org/patch/288495/ Last time I posted this the biggest change requested was for more info to be included in the event send to the DRM-subsystem, specifically sending the following info was requested: 1. Which DP connector on the GPU the event is for 2. How many lanes are available 3. Connector orientation This series is basically an entirely new approach, which no longer uses the notifier framework at all. Instead the Type-C code looksup a connector based on a fwnode (this was suggested by Heikki Krogerus) and then calls a new oob_hotplug_event drm_connector_func directly on the connector, passing the requested info as argument. This series not only touches drm subsys files but it also touches drivers/usb/typec/altmodes/typec_displayport.c, that file usually does not see a whole lot of changes. So I believe it would be best to just merge the entire series through drm-misc, Assuming we can get an ack from Greg for merging the typec_displayport.c changes this way. Regards, Hans Hans de Goede (8): drm/connector: Make the drm_sysfs connector->kdev device hold a reference to the connector drm/connector: Add a fwnode pointer to drm_connector and register with ACPI drm/connector: Add drm_connector_find_by_fwnode() function drm/connector: Add support for out-of-band hotplug notification drm/i915/dp: Add support for out-of-bound hotplug events usb: typec: altmodes/displayport: Make dp_altmode_notify() more generic usb: typec: altmodes/displayport: Notify drm subsys of hotplug events platform/x86/intel_cht_int33fe: Correct "displayport" fwnode reference Heikki Krogerus (1): drm/i915: Associate ACPI connector nodes with connector entries drivers/gpu/drm/drm_connector.c | 20 +++ drivers/gpu/drm/drm_sysfs.c | 129 -- drivers/gpu/drm/i915/display/intel_acpi.c | 40 ++ drivers/gpu/drm/i915/display/intel_acpi.h | 3 + drivers/gpu/drm/i915/display/intel_display.c | 1 + drivers/gpu/drm/i915/display/intel_dp.c | 13 ++ .../platform/x86/intel_cht_int33fe_typec.c| 4 +- drivers/usb/typec/altmodes/displayport.c | 78 --- include/drm/drm_connector.h | 36 + 9 files changed, 292 insertions(+), 32 deletions(-) -- 2.31.1 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH 1/9] drm/connector: Make the drm_sysfs connector->kdev device hold a reference to the connector
Userspace could hold open a reference to the connector->kdev device, through e.g. holding a sysfs-atrtribute open after drm_sysfs_connector_remove() has been called. In this case the connector could be free-ed while the connector->kdev device's drvdata is still pointing to it. Give drm_connector devices there own device type, which allows us to specify our own release function and make drm_sysfs_connector_add() take a reference on the connector object, and have the new release function put the reference when the device is released. Giving drm_connector devices there own device type, will also allow checking if a device is a drm_connector device with a "if (device->type == &drm_sysfs_device_connector)" check. Note that the setting of the name member of the device_type struct will cause udev events for drm_connector-s to now contain DEVTYPE=drm_connector as extra info. So this extends the uevent part of the userspace API. Signed-off-by: Hans de Goede --- drivers/gpu/drm/drm_sysfs.c | 54 +++-- 1 file changed, 46 insertions(+), 8 deletions(-) diff --git a/drivers/gpu/drm/drm_sysfs.c b/drivers/gpu/drm/drm_sysfs.c index f0336c804639..c344c6d5e738 100644 --- a/drivers/gpu/drm/drm_sysfs.c +++ b/drivers/gpu/drm/drm_sysfs.c @@ -50,6 +50,10 @@ static struct device_type drm_sysfs_device_minor = { .name = "drm_minor" }; +static struct device_type drm_sysfs_device_connector = { + .name = "drm_connector", +}; + struct class *drm_class; static char *drm_devnode(struct device *dev, umode_t *mode) @@ -271,30 +275,64 @@ static const struct attribute_group *connector_dev_groups[] = { NULL }; +static void drm_sysfs_connector_release(struct device *dev) +{ + struct drm_connector *connector = to_drm_connector(dev); + + drm_connector_put(connector); + kfree(dev); +} + int drm_sysfs_connector_add(struct drm_connector *connector) { struct drm_device *dev = connector->dev; + struct device *kdev; + int r; if (connector->kdev) return 0; - connector->kdev = - device_create_with_groups(drm_class, dev->primary->kdev, 0, - connector, connector_dev_groups, - "card%d-%s", dev->primary->index, - connector->name); + kdev = kzalloc(sizeof(*kdev), GFP_KERNEL); + if (!kdev) + return -ENOMEM; + + device_initialize(kdev); + kdev->class = drm_class; + kdev->type = &drm_sysfs_device_connector; + kdev->parent = dev->primary->kdev; + kdev->groups = connector_dev_groups; + kdev->release = drm_sysfs_connector_release; + dev_set_drvdata(kdev, connector); + + r = dev_set_name(kdev, "card%d-%s", dev->primary->index, connector->name); + if (r) + goto err_free; + DRM_DEBUG("adding \"%s\" to sysfs\n", connector->name); - if (IS_ERR(connector->kdev)) { - DRM_ERROR("failed to register connector device: %ld\n", PTR_ERR(connector->kdev)); - return PTR_ERR(connector->kdev); + r = device_add(kdev); + if (r) { + DRM_ERROR("failed to register connector device: %d\n", r); + goto err_free; } + /* +* Ensure the connector object does not get free-ed if userspace still has +* references open to the device through e.g. the connector sysfs-attributes. +*/ + drm_connector_get(connector); + + connector->kdev = kdev; + if (connector->ddc) return sysfs_create_link(&connector->kdev->kobj, &connector->ddc->dev.kobj, "ddc"); return 0; + +err_free: + put_device(kdev); + return r; } void drm_sysfs_connector_remove(struct drm_connector *connector) -- 2.31.1 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH 2/9] drm/connector: Add a fwnode pointer to drm_connector and register with ACPI
Add a fwnode pointer to struct drm_connector and register an acpi_bus_type for the connectors with the ACPI subsystem (when CONFIG_ACPI is enabled). The adding of the fwnode pointer allows drivers to associate a fwnode that represents a connector with that connector. When the new fwnode pointer points to an ACPI-companion, then the new acpi_bus_type will cause the ACPI subsys to bind the device instantiated for the connector with the fwnode by calling acpi_bind_one(). This will result in a firmware_node symlink under /sys/class/card#-/ which helps to verify that the fwnode-s and connectors are properly matched. Co-authored-by: Heikki Krogerus Signed-off-by: Heikki Krogerus Signed-off-by: Hans de Goede --- drivers/gpu/drm/drm_sysfs.c | 37 + include/drm/drm_connector.h | 2 ++ 2 files changed, 39 insertions(+) diff --git a/drivers/gpu/drm/drm_sysfs.c b/drivers/gpu/drm/drm_sysfs.c index c344c6d5e738..c1d3e2b843b7 100644 --- a/drivers/gpu/drm/drm_sysfs.c +++ b/drivers/gpu/drm/drm_sysfs.c @@ -10,6 +10,7 @@ * Copyright (c) 2003-2004 IBM Corp. */ +#include #include #include #include @@ -56,6 +57,39 @@ static struct device_type drm_sysfs_device_connector = { struct class *drm_class; +#ifdef CONFIG_ACPI +static bool drm_connector_acpi_bus_match(struct device *dev) +{ + return dev->type == &drm_sysfs_device_connector; +} + +static struct acpi_device *drm_connector_acpi_find_companion(struct device *dev) +{ + struct drm_connector *connector = to_drm_connector(dev); + + return to_acpi_device_node(connector->fwnode); +} + +static struct acpi_bus_type drm_connector_acpi_bus = { + .name = "drm_connector", + .match = drm_connector_acpi_bus_match, + .find_companion = drm_connector_acpi_find_companion, +}; + +static void drm_sysfs_acpi_register(void) +{ + register_acpi_bus_type(&drm_connector_acpi_bus); +} + +static void drm_sysfs_acpi_unregister(void) +{ + unregister_acpi_bus_type(&drm_connector_acpi_bus); +} +#else +static void drm_sysfs_acpi_register(void) { } +static void drm_sysfs_acpi_unregister(void) { } +#endif + static char *drm_devnode(struct device *dev, umode_t *mode) { return kasprintf(GFP_KERNEL, "dri/%s", dev_name(dev)); @@ -89,6 +123,8 @@ int drm_sysfs_init(void) } drm_class->devnode = drm_devnode; + + drm_sysfs_acpi_register(); return 0; } @@ -101,6 +137,7 @@ void drm_sysfs_destroy(void) { if (IS_ERR_OR_NULL(drm_class)) return; + drm_sysfs_acpi_unregister(); class_remove_file(drm_class, &class_attr_version.attr); class_destroy(drm_class); drm_class = NULL; diff --git a/include/drm/drm_connector.h b/include/drm/drm_connector.h index 0261801af62c..d20bfd7576ed 100644 --- a/include/drm/drm_connector.h +++ b/include/drm/drm_connector.h @@ -1254,6 +1254,8 @@ struct drm_connector { struct device *kdev; /** @attr: sysfs attributes */ struct device_attribute *attr; + /** @fwnode: associated fwnode supplied by platform firmware */ + struct fwnode_handle *fwnode; /** * @head: -- 2.31.1 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH 3/9] drm/connector: Add drm_connector_find_by_fwnode() function
Add a function which allows other subsystems to find a connector based on a fwnode. This will be used by the USB-Type-C code to be able to find the DP connector to which to send hotplug events received by a Type-C port in DP-alternate-mode. Note this function is defined in drivers/gpu/drm/drm_sysfs.c because it needs access to the drm_sysfs_device_connector device_type struct. Signed-off-by: Hans de Goede --- drivers/gpu/drm/drm_sysfs.c | 38 + include/drm/drm_connector.h | 1 + 2 files changed, 39 insertions(+) diff --git a/drivers/gpu/drm/drm_sysfs.c b/drivers/gpu/drm/drm_sysfs.c index c1d3e2b843b7..ca71c46fad78 100644 --- a/drivers/gpu/drm/drm_sysfs.c +++ b/drivers/gpu/drm/drm_sysfs.c @@ -520,3 +520,41 @@ void drm_class_device_unregister(struct device *dev) return device_unregister(dev); } EXPORT_SYMBOL_GPL(drm_class_device_unregister); + +/** + * drm_connector_find_by_fwnode - Find a connector based on the associated fwnode + * @fwnode: fwnode for which to find the matching drm_connector + * + * This functions looks up a drm_connector based on its associated fwnode. When + * a connector is found a reference to the connector is returned. The caller must + * call drm_connector_put() to release this reference when it is done with the + * connector. + * + * Returns: A reference to the found connector or NULL if no matching connector was found + */ +struct drm_connector *drm_connector_find_by_fwnode(struct fwnode_handle *fwnode) +{ + struct drm_connector *connector, *found = NULL; + struct class_dev_iter iter; + struct device *dev; + + if (!fwnode) + return NULL; + + class_dev_iter_init(&iter, drm_class, NULL, &drm_sysfs_device_connector); + while ((dev = class_dev_iter_next(&iter))) { + connector = to_drm_connector(dev); + + if ((connector->fwnode == fwnode) || + (connector->fwnode && connector->fwnode->secondary == fwnode)) { + drm_connector_get(connector); + found = connector; + break; + } + + } + class_dev_iter_exit(&iter); + + return found; +} +EXPORT_SYMBOL(drm_connector_find_by_fwnode); diff --git a/include/drm/drm_connector.h b/include/drm/drm_connector.h index d20bfd7576ed..1e5d154d1f4a 100644 --- a/include/drm/drm_connector.h +++ b/include/drm/drm_connector.h @@ -1696,6 +1696,7 @@ drm_connector_is_unregistered(struct drm_connector *connector) DRM_CONNECTOR_UNREGISTERED; } +struct drm_connector *drm_connector_find_by_fwnode(struct fwnode_handle *fwnode); const char *drm_get_connector_type_name(unsigned int connector_type); const char *drm_get_connector_status_name(enum drm_connector_status status); const char *drm_get_subpixel_order_name(enum subpixel_order order); -- 2.31.1 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH 4/9] drm/connector: Add support for out-of-band hotplug notification
Add a new drm_connector_oob_hotplug_event() function and oob_hotplug_event drm_connector_funcs member. On some hardware a hotplug event notification may come from outside the display driver / device. An example of this is some USB Type-C setups where the hardware muxes the DisplayPort data and aux-lines but does not pass the altmode HPD status bit to the GPU's DP HPD pin. In cases like this the new drm_connector_oob_hotplug_event() function can be used to report these out-of-band events after obtaining a drm_connector reference through calling drm_connector_find_by_fwnode(). Signed-off-by: Hans de Goede --- drivers/gpu/drm/drm_connector.c | 20 include/drm/drm_connector.h | 33 + 2 files changed, 53 insertions(+) diff --git a/drivers/gpu/drm/drm_connector.c b/drivers/gpu/drm/drm_connector.c index 87c68563e6c3..7d3adc41c11a 100644 --- a/drivers/gpu/drm/drm_connector.c +++ b/drivers/gpu/drm/drm_connector.c @@ -2676,6 +2676,26 @@ int drm_mode_getconnector(struct drm_device *dev, void *data, return ret; } +/** + * drm_connector_oob_hotplug_event - Report out-of-band hotplug event to connector + * @connector: connector to report the event on + * @data: data related to the event + * + * On some hardware a hotplug event notification may come from outside the display + * driver / device. An example of this is some USB Type-C setups where the hardware + * muxes the DisplayPort data and aux-lines but does not pass the altmode HPD + * status bit to the GPU's DP HPD pin. + * + * This function can be used to report these out-of-band events after obtaining + * a drm_connector reference through calling drm_connector_find_by_fwnode(). + */ +void drm_connector_oob_hotplug_event(struct drm_connector *connector, +struct drm_connector_oob_hotplug_event_data *data) +{ + if (connector->funcs->oob_hotplug_event) + connector->funcs->oob_hotplug_event(connector, data); +} +EXPORT_SYMBOL(drm_connector_oob_hotplug_event); /** * DOC: Tile group diff --git a/include/drm/drm_connector.h b/include/drm/drm_connector.h index 1e5d154d1f4a..6a10f8890809 100644 --- a/include/drm/drm_connector.h +++ b/include/drm/drm_connector.h @@ -27,6 +27,7 @@ #include #include #include +#include /* For enum typec_orientation */ #include #include @@ -649,6 +650,27 @@ struct drm_connector_tv_margins { unsigned int top; }; +/** + * struct drm_connector_oob_hotplug_event_data: OOB hotplug event data + * + * Contains data about out-of-band hotplug events, signalled through + * drm_connector_oob_hotplug_event(). + */ +struct drm_connector_oob_hotplug_event_data { + /** +* @connected: New connected status for the connector. +*/ + bool connected; + /** +* @dp_lanes: Number of available displayport lanes, 0 if unknown. +*/ + int dp_lanes; + /** +* @orientation: Connector orientation. +*/ + enum typec_orientation orientation; +}; + /** * struct drm_tv_connector_state - TV connector related states * @subconnector: selected subconnector @@ -1110,6 +1132,15 @@ struct drm_connector_funcs { */ void (*atomic_print_state)(struct drm_printer *p, const struct drm_connector_state *state); + + /** +* @oob_hotplug_event: +* +* This will get called when a hotplug-event for a drm-connector +* has been received from a source outside the display driver / device. +*/ + void (*oob_hotplug_event)(struct drm_connector *connector, + struct drm_connector_oob_hotplug_event_data *data); }; /** @@ -1697,6 +1728,8 @@ drm_connector_is_unregistered(struct drm_connector *connector) } struct drm_connector *drm_connector_find_by_fwnode(struct fwnode_handle *fwnode); +void drm_connector_oob_hotplug_event(struct drm_connector *connector, +struct drm_connector_oob_hotplug_event_data *data); const char *drm_get_connector_type_name(unsigned int connector_type); const char *drm_get_connector_status_name(enum drm_connector_status status); const char *drm_get_subpixel_order_name(enum subpixel_order order); -- 2.31.1 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH 7/9] usb: typec: altmodes/displayport: Make dp_altmode_notify() more generic
Make dp_altmode_notify() handle the dp->data.conf == 0 case too, rather then having separate code-paths for this in various places which call it. Signed-off-by: Hans de Goede --- drivers/usb/typec/altmodes/displayport.c | 35 +--- 1 file changed, 13 insertions(+), 22 deletions(-) diff --git a/drivers/usb/typec/altmodes/displayport.c b/drivers/usb/typec/altmodes/displayport.c index b7f094435b00..aa669b9cf70e 100644 --- a/drivers/usb/typec/altmodes/displayport.c +++ b/drivers/usb/typec/altmodes/displayport.c @@ -66,10 +66,17 @@ struct dp_altmode { static int dp_altmode_notify(struct dp_altmode *dp) { - u8 state = get_count_order(DP_CONF_GET_PIN_ASSIGN(dp->data.conf)); + unsigned long conf; + u8 state; + + if (dp->data.conf) { + state = get_count_order(DP_CONF_GET_PIN_ASSIGN(dp->data.conf)); + conf = TYPEC_MODAL_STATE(state); + } else { + conf = TYPEC_STATE_USB; + } - return typec_altmode_notify(dp->alt, TYPEC_MODAL_STATE(state), - &dp->data); + return typec_altmode_notify(dp->alt, conf, &dp->data); } static int dp_altmode_configure(struct dp_altmode *dp, u8 con) @@ -137,21 +144,10 @@ static int dp_altmode_status_update(struct dp_altmode *dp) static int dp_altmode_configured(struct dp_altmode *dp) { - int ret; - sysfs_notify(&dp->alt->dev.kobj, "displayport", "configuration"); - - if (!dp->data.conf) - return typec_altmode_notify(dp->alt, TYPEC_STATE_USB, - &dp->data); - - ret = dp_altmode_notify(dp); - if (ret) - return ret; - sysfs_notify(&dp->alt->dev.kobj, "displayport", "pin_assignment"); - return 0; + return dp_altmode_notify(dp); } static int dp_altmode_configure_vdm(struct dp_altmode *dp, u32 conf) @@ -172,13 +168,8 @@ static int dp_altmode_configure_vdm(struct dp_altmode *dp, u32 conf) } ret = typec_altmode_vdm(dp->alt, header, &conf, 2); - if (ret) { - if (DP_CONF_GET_PIN_ASSIGN(dp->data.conf)) - dp_altmode_notify(dp); - else - typec_altmode_notify(dp->alt, TYPEC_STATE_USB, -&dp->data); - } + if (ret) + dp_altmode_notify(dp); return ret; } -- 2.31.1 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH 6/9] drm/i915/dp: Add support for out-of-bound hotplug events
On some Cherry Trail devices, DisplayPort over Type-C is supported through a USB-PD microcontroller (e.g. a fusb302) + a mux to switch the superspeed datalines between USB-3 and DP (e.g. a pi3usb30532). The kernel in this case does the PD/alt-mode negotiation itself, rather then everything being handled in firmware. So the kernel itself picks an alt-mode, tells the Type-C "dongle" to switch to DP mode and sets the mux accordingly. In this setup the HPD pin is not connected, so the i915 driver needs to respond to a software event and scan the DP port for changes manually. This commit adds support for this. Together with the recent addition of DP alt-mode support to the Type-C subsystem this makes DP over Type-C work on these devices. Signed-off-by: Hans de Goede --- drivers/gpu/drm/i915/display/intel_dp.c | 13 + 1 file changed, 13 insertions(+) diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c index 64a73b3ced94..1029720cc945 100644 --- a/drivers/gpu/drm/i915/display/intel_dp.c +++ b/drivers/gpu/drm/i915/display/intel_dp.c @@ -5846,6 +5846,18 @@ static int intel_dp_connector_atomic_check(struct drm_connector *conn, return intel_modeset_synced_crtcs(state, conn); } +static void intel_dp_oob_hotplug_event(struct drm_connector *connector, + struct drm_connector_oob_hotplug_event_data *data) +{ + struct intel_encoder *encoder = intel_attached_encoder(to_intel_connector(connector)); + struct drm_i915_private *i915 = to_i915(connector->dev); + + spin_lock_irq(&i915->irq_lock); + i915->hotplug.event_bits |= BIT(encoder->hpd_pin); + spin_unlock_irq(&i915->irq_lock); + queue_delayed_work(system_wq, &i915->hotplug.hotplug_work, 0); +} + static const struct drm_connector_funcs intel_dp_connector_funcs = { .force = intel_dp_force, .fill_modes = drm_helper_probe_single_connector_modes, @@ -5856,6 +5868,7 @@ static const struct drm_connector_funcs intel_dp_connector_funcs = { .destroy = intel_connector_destroy, .atomic_destroy_state = drm_atomic_helper_connector_destroy_state, .atomic_duplicate_state = intel_digital_connector_duplicate_state, + .oob_hotplug_event = intel_dp_oob_hotplug_event, }; static const struct drm_connector_helper_funcs intel_dp_connector_helper_funcs = { -- 2.31.1 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH 5/9] drm/i915: Associate ACPI connector nodes with connector entries
From: Heikki Krogerus On Intel platforms we know that the ACPI connector device node order will follow the order the driver (i915) decides. The decision is made using the custom Intel ACPI OpRegion (intel_opregion.c), though the driver does not actually know that the values it sends to ACPI there are used for associating a device node for the connectors, and assigning address for them. In reality that custom Intel ACPI OpRegion actually violates ACPI specification (we supply dynamic information to objects that are defined static, for example _ADR), however, it makes assigning correct connector node for a connector entry straightforward (it's one-on-one mapping). Signed-off-by: Heikki Krogerus [hdego...@redhat.com: Move intel_acpi_assign_connector_fwnodes() to intel_acpi.c] Signed-off-by: Hans de Goede --- drivers/gpu/drm/i915/display/intel_acpi.c| 40 drivers/gpu/drm/i915/display/intel_acpi.h| 3 ++ drivers/gpu/drm/i915/display/intel_display.c | 1 + 3 files changed, 44 insertions(+) diff --git a/drivers/gpu/drm/i915/display/intel_acpi.c b/drivers/gpu/drm/i915/display/intel_acpi.c index 833d0c1be4f1..9f266dfda7dd 100644 --- a/drivers/gpu/drm/i915/display/intel_acpi.c +++ b/drivers/gpu/drm/i915/display/intel_acpi.c @@ -263,3 +263,43 @@ void intel_acpi_device_id_update(struct drm_i915_private *dev_priv) } drm_connector_list_iter_end(&conn_iter); } + +/* NOTE: The connector order must be final before this is called. */ +void intel_acpi_assign_connector_fwnodes(struct drm_i915_private *i915) +{ + struct drm_connector_list_iter conn_iter; + struct drm_device *drm_dev = &i915->drm; + struct device *kdev = &drm_dev->pdev->dev; + struct fwnode_handle *fwnode = NULL; + struct drm_connector *connector; + struct acpi_device *adev; + + drm_connector_list_iter_begin(drm_dev, &conn_iter); + drm_for_each_connector_iter(connector, &conn_iter) { + /* Always getting the next, even when the last was not used. */ + fwnode = device_get_next_child_node(kdev, fwnode); + if (!fwnode) + break; + + switch (connector->connector_type) { + case DRM_MODE_CONNECTOR_LVDS: + case DRM_MODE_CONNECTOR_eDP: + case DRM_MODE_CONNECTOR_DSI: + /* +* Integrated displays have a specific address 0x1f on +* most Intel platforms, but not on all of them. +*/ + adev = acpi_find_child_device(ACPI_COMPANION(kdev), + 0x1f, 0); + if (adev) { + connector->fwnode = acpi_fwnode_handle(adev); + break; + } + fallthrough; + default: + connector->fwnode = fwnode; + break; + } + } + drm_connector_list_iter_end(&conn_iter); +} diff --git a/drivers/gpu/drm/i915/display/intel_acpi.h b/drivers/gpu/drm/i915/display/intel_acpi.h index e8b068661d22..d2435691f4b5 100644 --- a/drivers/gpu/drm/i915/display/intel_acpi.h +++ b/drivers/gpu/drm/i915/display/intel_acpi.h @@ -12,11 +12,14 @@ struct drm_i915_private; void intel_register_dsm_handler(void); void intel_unregister_dsm_handler(void); void intel_acpi_device_id_update(struct drm_i915_private *i915); +void intel_acpi_assign_connector_fwnodes(struct drm_i915_private *i915); #else static inline void intel_register_dsm_handler(void) { return; } static inline void intel_unregister_dsm_handler(void) { return; } static inline void intel_acpi_device_id_update(struct drm_i915_private *i915) { return; } +static inline +void intel_acpi_assign_connector_fwnodes(struct drm_i915_private *i915) { return; } #endif /* CONFIG_ACPI */ #endif /* __INTEL_ACPI_H__ */ diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index 828ef4c5625f..87cad549632c 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -14970,6 +14970,7 @@ int intel_modeset_init_nogem(struct drm_i915_private *i915) drm_modeset_lock_all(dev); intel_modeset_setup_hw_state(dev, dev->mode_config.acquire_ctx); + intel_acpi_assign_connector_fwnodes(i915); drm_modeset_unlock_all(dev); for_each_intel_crtc(dev, crtc) { -- 2.31.1 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH 9/9] platform/x86/intel_cht_int33fe: Correct "displayport" fwnode reference
The Type-C connector on these devices is connected to DP-2 not DP-1, so the reference must be to the DD04 child-node of the GPU, rather then the DD02 child-node. Signed-off-by: Hans de Goede --- drivers/platform/x86/intel_cht_int33fe_typec.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/platform/x86/intel_cht_int33fe_typec.c b/drivers/platform/x86/intel_cht_int33fe_typec.c index b61bad9cc8d2..d59544167430 100644 --- a/drivers/platform/x86/intel_cht_int33fe_typec.c +++ b/drivers/platform/x86/intel_cht_int33fe_typec.c @@ -168,8 +168,8 @@ static int cht_int33fe_setup_dp(struct cht_int33fe_data *data) return -ENODEV; } - /* Then the DP child device node */ - data->dp = device_get_named_child_node(&pdev->dev, "DD02"); + /* Then the DP-2 child device node */ + data->dp = device_get_named_child_node(&pdev->dev, "DD04"); pci_dev_put(pdev); if (!data->dp) return -ENODEV; -- 2.31.1 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH 8/9] usb: typec: altmodes/displayport: Notify drm subsys of hotplug events
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 --- drivers/usb/typec/altmodes/displayport.c | 45 +++- 1 file changed, 44 insertions(+), 1 deletion(-) diff --git a/drivers/usb/typec/altmodes/displayport.c b/drivers/usb/typec/altmodes/displayport.c index aa669b9cf70e..c95ccd2a965c 100644 --- a/drivers/usb/typec/altmodes/displayport.c +++ b/drivers/usb/typec/altmodes/displayport.c @@ -11,8 +11,10 @@ #include #include #include +#include #include #include +#include #include "displayport.h" #define DP_HEADER(_dp, ver, cmd) (VDO((_dp)->alt->svid, 1, ver, cmd) \ @@ -62,12 +64,35 @@ 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); + struct drm_connector *connector; + + 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; + + connector = drm_connector_find_by_fwnode(dp->connector_fwnode); + if (connector) { + drm_connector_oob_hotplug_event(connector, &data); + drm_connector_put(connector); + } +} + 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 +101,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 +542,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 +571,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 +591,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); -- 2.31.1 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
Re: [PATCH 0/9] drm + usb-type-c: Add support for out-of-band hotplug notification
Hi, On 4/28/21 11:52 PM, Hans de Goede wrote: > Hi All, > > Here is a new attempt to make DP over Type-C work on devices where the > Type-C controller does not drive the HPD pin on the GPU, but instead > we need to forward HPD events from the Type-C controller to the DRM driver. > > For anyone interested here are the old (2019!) patches for this: > > https://patchwork.freedesktop.org/patch/288491/ > https://patchwork.freedesktop.org/patch/288493/ > https://patchwork.freedesktop.org/patch/288495/ > > Last time I posted this the biggest change requested was for more info to > be included in the event send to the DRM-subsystem, specifically sending > the following info was requested: > > 1. Which DP connector on the GPU the event is for > 2. How many lanes are available > 3. Connector orientation > > This series is basically an entirely new approach, which no longer > uses the notifier framework at all. Instead the Type-C code looksup > a connector based on a fwnode (this was suggested by Heikki Krogerus) > and then calls a new oob_hotplug_event drm_connector_func directly > on the connector, passing the requested info as argument. p.s. Info such as the orientation and the number of dp-lanes is now passed to the drm_connector_oob_hotplug_event() function as requested in the review of the old code, but nothing is done with it for now. Using this info falls well outside of my knowledge of the i915 driver so this is left to a follow-up patch (I will be available to test patches for this). Regards, Hans ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
Re: [PATCH 1/9] drm/connector: Make the drm_sysfs connector->kdev device hold a reference to the connector
Hi, On 4/29/21 1:40 PM, Daniel Vetter wrote: > On Wed, Apr 28, 2021 at 11:52:49PM +0200, Hans de Goede wrote: >> Userspace could hold open a reference to the connector->kdev device, >> through e.g. holding a sysfs-atrtribute open after >> drm_sysfs_connector_remove() has been called. In this case the connector >> could be free-ed while the connector->kdev device's drvdata is still >> pointing to it. >> >> Give drm_connector devices there own device type, which allows >> us to specify our own release function and make drm_sysfs_connector_add() >> take a reference on the connector object, and have the new release >> function put the reference when the device is released. >> >> Giving drm_connector devices there own device type, will also allow >> checking if a device is a drm_connector device with a >> "if (device->type == &drm_sysfs_device_connector)" check. >> >> Note that the setting of the name member of the device_type struct will >> cause udev events for drm_connector-s to now contain DEVTYPE=drm_connector >> as extra info. So this extends the uevent part of the userspace API. >> >> Signed-off-by: Hans de Goede > > Are you sure? I thought sysfs is supposed to flush out any pending > operations (they complete fast) and handle open fd internally? So I did some digging in fs/kernfs and it looks like you right, once the file has been removed from sysfs any accesses through an open fd will fail with -ENODEV, interesting I did not know this. We still need this change though to make sure that the "drm/connector: Add drm_connector_find_by_fwnode() function" does not end up following a dangling drvdat pointer from one if the drm_connector kdev-s. The class_dev_iter_init() in drm_connector_find_by_fwnode() gets a reference on all devices and between getting that reference and it calling drm_connector_get() - drm_connector_unregister() may run and drop the possibly last reference to the drm_connector object, freeing it and leaving the kdev's drvdata as a dangling pointer. But I obviously need to rewrite the commit message of this commit as it currently is completely wrong. Maybe I should even squash this into the commit adding drm_connector_find_by_fwnode() ? Note sure about that though I personally think this is best kept as a new preparation patch but with a new commit msg. > Also I'd assume this creates a loop since the connector holds a reference > on the kdev? So I was wondering the same thing when working on this code and I checked. the reference on the kdev is dropped from: drm_connector_unregister() -> drm_sysfs_connector_remove() and then happens independent of the reference count on the connector-drm-obj dropping to 0. So what this change does is it keeps a reference to the drm_connector obj as long as someone is keeping a reference to the connnector->kdev device around after drm_connector_unregister() but as soon as that kdev device ref is dropped, so will the drm_connector's obj reference. I also tested this using a dock with DP MST, which dynamically adds/removes connectors on plug-in / plug-out of the dock-cable and I added a printk to the new drm_sysfs_connector_release() this adds and that printk triggered pretty much immediately on unplug as expected, releasing the extra drm_connector obj as soon as drm_connector_unregister() got called. Regards, Hans > -Daniel > >> --- >> drivers/gpu/drm/drm_sysfs.c | 54 +++-- >> 1 file changed, 46 insertions(+), 8 deletions(-) >> >> diff --git a/drivers/gpu/drm/drm_sysfs.c b/drivers/gpu/drm/drm_sysfs.c >> index f0336c804639..c344c6d5e738 100644 >> --- a/drivers/gpu/drm/drm_sysfs.c >> +++ b/drivers/gpu/drm/drm_sysfs.c >> @@ -50,6 +50,10 @@ static struct device_type drm_sysfs_device_minor = { >> .name = "drm_minor" >> }; >> >> +static struct device_type drm_sysfs_device_connector = { >> +.name = "drm_connector", >> +}; >> + >> struct class *drm_class; >> >> static char *drm_devnode(struct device *dev, umode_t *mode) >> @@ -271,30 +275,64 @@ static const struct attribute_group >> *connector_dev_groups[] = { >> NULL >> }; >> >> +static void drm_sysfs_connector_release(struct device *dev) >> +{ >> +struct drm_connector *connector = to_drm_connector(dev); >> + >> +drm_connector_put(connector); >> +kfree(dev); >> +} >> + >> int drm_sysfs_connector_add(struct drm_connector *connector) >> { >> struct drm_device *dev = connector->dev; >> +struct device *kdev; >> +int r; >> >> if (c
Re: [PATCH 1/9] drm/connector: Make the drm_sysfs connector->kdev device hold a reference to the connector
Hi, On 4/29/21 2:04 PM, Daniel Vetter wrote: > On Thu, Apr 29, 2021 at 01:54:46PM +0200, Greg Kroah-Hartman wrote: >> On Thu, Apr 29, 2021 at 01:40:28PM +0200, Daniel Vetter wrote: >>> On Wed, Apr 28, 2021 at 11:52:49PM +0200, Hans de Goede wrote: >>>> Userspace could hold open a reference to the connector->kdev device, >>>> through e.g. holding a sysfs-atrtribute open after >>>> drm_sysfs_connector_remove() has been called. In this case the connector >>>> could be free-ed while the connector->kdev device's drvdata is still >>>> pointing to it. >>>> >>>> Give drm_connector devices there own device type, which allows >>>> us to specify our own release function and make drm_sysfs_connector_add() >>>> take a reference on the connector object, and have the new release >>>> function put the reference when the device is released. >>>> >>>> Giving drm_connector devices there own device type, will also allow >>>> checking if a device is a drm_connector device with a >>>> "if (device->type == &drm_sysfs_device_connector)" check. >>>> >>>> Note that the setting of the name member of the device_type struct will >>>> cause udev events for drm_connector-s to now contain DEVTYPE=drm_connector >>>> as extra info. So this extends the uevent part of the userspace API. >>>> >>>> Signed-off-by: Hans de Goede >>> >>> Are you sure? I thought sysfs is supposed to flush out any pending >>> operations (they complete fast) and handle open fd internally? >> >> Yes, it "should" :) > > Thanks for confirming my vague memories :-) > > Hans, pls drop this one. Please see my earlier reply to your review of this patch, it is still needed but for a different reason: """ We still need this change though to make sure that the "drm/connector: Add drm_connector_find_by_fwnode() function" does not end up following a dangling drvdat pointer from one if the drm_connector kdev-s. The class_dev_iter_init() in drm_connector_find_by_fwnode() gets a reference on all devices and between getting that reference and it calling drm_connector_get() - drm_connector_unregister() may run and drop the possibly last reference to the drm_connector object, freeing it and leaving the kdev's drvdata as a dangling pointer. """ This is actually why I added it initially, and while adding it I came up with this wrong theory of why it was necessary independently of the drm_connector_find_by_fwnode() addition, sorry about that. Regards, Hans ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
Re: [PATCH 1/9] drm/connector: Make the drm_sysfs connector->kdev device hold a reference to the connector
Hi, On 4/29/21 9:09 PM, Daniel Vetter wrote: > On Thu, Apr 29, 2021 at 02:33:17PM +0200, Hans de Goede wrote: >> Hi, >> >> On 4/29/21 2:04 PM, Daniel Vetter wrote: >>> On Thu, Apr 29, 2021 at 01:54:46PM +0200, Greg Kroah-Hartman wrote: >>>> On Thu, Apr 29, 2021 at 01:40:28PM +0200, Daniel Vetter wrote: >>>>> On Wed, Apr 28, 2021 at 11:52:49PM +0200, Hans de Goede wrote: >>>>>> Userspace could hold open a reference to the connector->kdev device, >>>>>> through e.g. holding a sysfs-atrtribute open after >>>>>> drm_sysfs_connector_remove() has been called. In this case the connector >>>>>> could be free-ed while the connector->kdev device's drvdata is still >>>>>> pointing to it. >>>>>> >>>>>> Give drm_connector devices there own device type, which allows >>>>>> us to specify our own release function and make drm_sysfs_connector_add() >>>>>> take a reference on the connector object, and have the new release >>>>>> function put the reference when the device is released. >>>>>> >>>>>> Giving drm_connector devices there own device type, will also allow >>>>>> checking if a device is a drm_connector device with a >>>>>> "if (device->type == &drm_sysfs_device_connector)" check. >>>>>> >>>>>> Note that the setting of the name member of the device_type struct will >>>>>> cause udev events for drm_connector-s to now contain >>>>>> DEVTYPE=drm_connector >>>>>> as extra info. So this extends the uevent part of the userspace API. >>>>>> >>>>>> Signed-off-by: Hans de Goede >>>>> >>>>> Are you sure? I thought sysfs is supposed to flush out any pending >>>>> operations (they complete fast) and handle open fd internally? >>>> >>>> Yes, it "should" :) >>> >>> Thanks for confirming my vague memories :-) >>> >>> Hans, pls drop this one. >> >> Please see my earlier reply to your review of this patch, it is >> still needed but for a different reason: >> >> """ >> We still need this change though to make sure that the >> "drm/connector: Add drm_connector_find_by_fwnode() function" >> does not end up following a dangling drvdat pointer from one >> if the drm_connector kdev-s. >> >> The class_dev_iter_init() in drm_connector_find_by_fwnode() gets >> a reference on all devices and between getting that reference >> and it calling drm_connector_get() - drm_connector_unregister() >> may run and drop the possibly last reference to the >> drm_connector object, freeing it and leaving the kdev's >> drvdata as a dangling pointer. >> """ >> >> This is actually why I added it initially, and while adding it >> I came up with this wrong theory of why it was necessary independently >> of the drm_connector_find_by_fwnode() addition, sorry about that. > > Generally that's handled by a kref_get_unless_zero under the protection of > the lock which protects the weak reference. Which I think is the right > model here (at a glance at least) since this is a lookup function. I'm afraid that things are a bit more complicated here. The idea here is that we have a subsystem outside of the DRM subsystem which received a hotplug event for a drm-connector. The only info which this subsystem has is a reference on the fwnode level (either through device-tree or to platform-code instantiating software-fwnode-s + links for this). So in order to deliver the hotplug event to the connector we need to lookup the connector by fwnode. I've chosen to implement this by iterating over all drm_class devices with a dev_type of drm_connector using class_dev_iter_init() and friends. This makes sure that we either get a reference to the device, or that we skip the device if it is being deleted. But this just gives us a reference to the connector->kdev, not to the connector itself. A pointer to the connector itself is stored as drvdata inside the device, but without taking a reference as this patch does, there is no guarantee that that pointer does not point to possibly free-ed mem. We could set drvdata to 0 from drm_sysfs_connector_remove() Before calling device_unregister(connector->kdev) and then do something like this inside drm_connector_find_by_fwnode(): /* * Lock the device to ensure we either see the drvdata == NULL * set by drm_sysfs_connector_remove(); or we block the removal * from co
Re: [PATCH 1/9] drm/connector: Make the drm_sysfs connector->kdev device hold a reference to the connector
Hi, On 4/30/21 1:38 PM, Daniel Vetter wrote: > On Fri, Apr 30, 2021 at 1:28 PM Hans de Goede wrote: >> >> Hi, >> >> On 4/29/21 9:09 PM, Daniel Vetter wrote: >>> On Thu, Apr 29, 2021 at 02:33:17PM +0200, Hans de Goede wrote: >>>> Hi, >>>> >>>> On 4/29/21 2:04 PM, Daniel Vetter wrote: >>>>> On Thu, Apr 29, 2021 at 01:54:46PM +0200, Greg Kroah-Hartman wrote: >>>>>> On Thu, Apr 29, 2021 at 01:40:28PM +0200, Daniel Vetter wrote: >>>>>>> On Wed, Apr 28, 2021 at 11:52:49PM +0200, Hans de Goede wrote: >>>>>>>> Userspace could hold open a reference to the connector->kdev device, >>>>>>>> through e.g. holding a sysfs-atrtribute open after >>>>>>>> drm_sysfs_connector_remove() has been called. In this case the >>>>>>>> connector >>>>>>>> could be free-ed while the connector->kdev device's drvdata is still >>>>>>>> pointing to it. >>>>>>>> >>>>>>>> Give drm_connector devices there own device type, which allows >>>>>>>> us to specify our own release function and make >>>>>>>> drm_sysfs_connector_add() >>>>>>>> take a reference on the connector object, and have the new release >>>>>>>> function put the reference when the device is released. >>>>>>>> >>>>>>>> Giving drm_connector devices there own device type, will also allow >>>>>>>> checking if a device is a drm_connector device with a >>>>>>>> "if (device->type == &drm_sysfs_device_connector)" check. >>>>>>>> >>>>>>>> Note that the setting of the name member of the device_type struct will >>>>>>>> cause udev events for drm_connector-s to now contain >>>>>>>> DEVTYPE=drm_connector >>>>>>>> as extra info. So this extends the uevent part of the userspace API. >>>>>>>> >>>>>>>> Signed-off-by: Hans de Goede >>>>>>> >>>>>>> Are you sure? I thought sysfs is supposed to flush out any pending >>>>>>> operations (they complete fast) and handle open fd internally? >>>>>> >>>>>> Yes, it "should" :) >>>>> >>>>> Thanks for confirming my vague memories :-) >>>>> >>>>> Hans, pls drop this one. >>>> >>>> Please see my earlier reply to your review of this patch, it is >>>> still needed but for a different reason: >>>> >>>> """ >>>> We still need this change though to make sure that the >>>> "drm/connector: Add drm_connector_find_by_fwnode() function" >>>> does not end up following a dangling drvdat pointer from one >>>> if the drm_connector kdev-s. >>>> >>>> The class_dev_iter_init() in drm_connector_find_by_fwnode() gets >>>> a reference on all devices and between getting that reference >>>> and it calling drm_connector_get() - drm_connector_unregister() >>>> may run and drop the possibly last reference to the >>>> drm_connector object, freeing it and leaving the kdev's >>>> drvdata as a dangling pointer. >>>> """ >>>> >>>> This is actually why I added it initially, and while adding it >>>> I came up with this wrong theory of why it was necessary independently >>>> of the drm_connector_find_by_fwnode() addition, sorry about that. >>> >>> Generally that's handled by a kref_get_unless_zero under the protection of >>> the lock which protects the weak reference. Which I think is the right >>> model here (at a glance at least) since this is a lookup function. >> >> I'm afraid that things are a bit more complicated here. The idea here >> is that we have a subsystem outside of the DRM subsystem which received >> a hotplug event for a drm-connector. The only info which this subsystem >> has is a reference on the fwnode level (either through device-tree or >> to platform-code instantiating software-fwnode-s + links for this). >> >> So in order to deliver the hotplug event to the connector we need >> to lookup the connector by fwnode. >> >> I've chosen to implement this by iterating over all drm_class >> devices with
Re: [PATCH 1/9] drm/connector: Make the drm_sysfs connector->kdev device hold a reference to the connector
p.s. On 4/30/21 1:38 PM, Daniel Vetter wrote: Offtopic: > I'm also not sure why we have to use the kdev stuff here. For other > random objects we need to look up we're building that functionality on > that object. It means you need to keep another list_head around for > that lookup, but that's really not a big cost. E.g. drm_bridge/panel > work like that. So I took a peek at the bridge/panel code and that actually seems to have an issue with removal vs lookup. It is not even just a race, it seems a lookup does not take a reference and there is nothing stopping a user from doing an unbind or rmmod causing the panel to be removed while other code which got a pointer to the panel through of_drm_find_panel() will not be prepared to deal with that pointer all of a sudden no longer being valid. Now this would be a case of the user shooting his-self in the foot (where as connectors can actually dynamically disappear under normal circumstances), but ideally we really should do better here. Is there a TODO list somewhere for issues like this ? Or shall I submit a patch adding a FIXME comment, or is this considered not worth the trouble of fixing it? Regards, Hans ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH 0/8] drm + usb-type-c: Add support for out-of-band hotplug notification (v4 resend)
Hi all, Here is a rebased-resend of v4 of my patchset making DP over Type-C work on devices where the Type-C controller does not drive the HPD pin on the GPU, but instead we need to forward HPD events from the Type-C controller to the DRM driver. Changes in v4 resend: - Rebase on top of latest drm-tip Changes in v4: - Rebase on top of latest drm-tip - Add forward declaration for struct fwnode_handle to drm_crtc_internal.h (fixes warning reported by kernel test robot ) - Add Heikki's Reviewed-by to patch 7 & 8 - Add Heikki's Tested-by to the series Changes in v3: - Base on top of latest drm-tip, which should fix the CI being unable to apply (and thus to test) the patches - Make intel_acpi_assign_connector_fwnodes() take a ref on the fwnode it stores in connector->fwnode and have drm_connector_cleanup() put this reference - Drop data argument from drm_connector_oob_hotplug_event() - Make the Type-C DP altmode code only call drm_connector_oob_hotplug_event() when the HPD bit in the status vdo changes - Drop the platform/x86/intel_cht_int33fe: Correct "displayport" fwnode reference patch, this will be merged independently through the pdx86 tree Changes in v2: - Replace the bogus "drm/connector: Make the drm_sysfs connector->kdev device hold a reference to the connector" patch with: "drm/connector: Give connector sysfs devices there own device_type" the new patch is a dep for patch 2/9 see the patches - Stop using a class-dev-iter, instead at a global connector list to drm_connector.c and use that to find the connector by the fwnode, similar to how we already do this in drm_panel.c and drm_bridge.c - Make drm_connector_oob_hotplug_event() take a fwnode pointer as argument, rather then a drm_connector pointer and let it do the lookup itself. This allows making drm_connector_find_by_fwnode() a drm-internal function and avoids code outside the drm subsystem potentially holding on the a drm_connector reference for a longer period. This series not only touches drm subsys files but it also touches drivers/usb/typec/altmodes/typec_displayport.c, that file usually does not see a whole lot of changes. So I believe it would be best to just merge the entire series through drm-misc, Assuming we can get an ack from Greg for merging the typec_displayport.c changes this way. Regards, Hans Hans de Goede (7): drm/connector: Give connector sysfs devices there own device_type drm/connector: Add a fwnode pointer to drm_connector and register with ACPI (v2) drm/connector: Add drm_connector_find_by_fwnode() function (v3) drm/connector: Add support for out-of-band hotplug notification (v3) drm/i915/dp: Add support for out-of-bound hotplug events usb: typec: altmodes/displayport: Make dp_altmode_notify() more generic usb: typec: altmodes/displayport: Notify drm subsys of hotplug events Heikki Krogerus (1): drm/i915: Associate ACPI connector nodes with connector entries (v2) drivers/gpu/drm/drm_connector.c | 79 ++ drivers/gpu/drm/drm_crtc_internal.h | 2 + drivers/gpu/drm/drm_sysfs.c | 87 +--- drivers/gpu/drm/i915/display/intel_acpi.c| 46 +++ drivers/gpu/drm/i915/display/intel_acpi.h| 3 + drivers/gpu/drm/i915/display/intel_display.c | 1 + drivers/gpu/drm/i915/display/intel_dp.c | 12 +++ drivers/usb/typec/altmodes/Kconfig | 1 + drivers/usb/typec/altmodes/displayport.c | 58 - include/drm/drm_connector.h | 25 ++ 10 files changed, 279 insertions(+), 35 deletions(-) -- 2.31.1
[PATCH 1/8] drm/connector: Give connector sysfs devices there own device_type
Give connector sysfs devices there own device_type, this allows us to check if a device passed to functions dealing with generic devices is a drm_connector or not. A check like this is necessary in the drm_connector_acpi_bus_match() function added in the next patch in this series. Tested-by: Heikki Krogerus Signed-off-by: Hans de Goede --- drivers/gpu/drm/drm_sysfs.c | 50 +++-- 1 file changed, 37 insertions(+), 13 deletions(-) diff --git a/drivers/gpu/drm/drm_sysfs.c b/drivers/gpu/drm/drm_sysfs.c index 968a9560b4aa..f9d92bbb1f98 100644 --- a/drivers/gpu/drm/drm_sysfs.c +++ b/drivers/gpu/drm/drm_sysfs.c @@ -50,6 +50,10 @@ static struct device_type drm_sysfs_device_minor = { .name = "drm_minor" }; +static struct device_type drm_sysfs_device_connector = { + .name = "drm_connector", +}; + struct class *drm_class; static char *drm_devnode(struct device *dev, umode_t *mode) @@ -102,6 +106,11 @@ void drm_sysfs_destroy(void) drm_class = NULL; } +static void drm_sysfs_release(struct device *dev) +{ + kfree(dev); +} + /* * Connector properties */ @@ -273,27 +282,47 @@ static const struct attribute_group *connector_dev_groups[] = { int drm_sysfs_connector_add(struct drm_connector *connector) { struct drm_device *dev = connector->dev; + struct device *kdev; + int r; if (connector->kdev) return 0; - connector->kdev = - device_create_with_groups(drm_class, dev->primary->kdev, 0, - connector, connector_dev_groups, - "card%d-%s", dev->primary->index, - connector->name); + kdev = kzalloc(sizeof(*kdev), GFP_KERNEL); + if (!kdev) + return -ENOMEM; + + device_initialize(kdev); + kdev->class = drm_class; + kdev->type = &drm_sysfs_device_connector; + kdev->parent = dev->primary->kdev; + kdev->groups = connector_dev_groups; + kdev->release = drm_sysfs_release; + dev_set_drvdata(kdev, connector); + + r = dev_set_name(kdev, "card%d-%s", dev->primary->index, connector->name); + if (r) + goto err_free; + DRM_DEBUG("adding \"%s\" to sysfs\n", connector->name); - if (IS_ERR(connector->kdev)) { - DRM_ERROR("failed to register connector device: %ld\n", PTR_ERR(connector->kdev)); - return PTR_ERR(connector->kdev); + r = device_add(kdev); + if (r) { + DRM_ERROR("failed to register connector device: %d\n", r); + goto err_free; } + connector->kdev = kdev; + if (connector->ddc) return sysfs_create_link(&connector->kdev->kobj, &connector->ddc->dev.kobj, "ddc"); return 0; + +err_free: + put_device(kdev); + return r; } void drm_sysfs_connector_remove(struct drm_connector *connector) @@ -374,11 +403,6 @@ void drm_sysfs_connector_status_event(struct drm_connector *connector, } EXPORT_SYMBOL(drm_sysfs_connector_status_event); -static void drm_sysfs_release(struct device *dev) -{ - kfree(dev); -} - struct device *drm_sysfs_minor_alloc(struct drm_minor *minor) { const char *minor_str; -- 2.31.1
[PATCH 2/8] drm/connector: Add a fwnode pointer to drm_connector and register with ACPI (v2)
Add a fwnode pointer to struct drm_connector and register an acpi_bus_type for the connectors with the ACPI subsystem (when CONFIG_ACPI is enabled). The adding of the fwnode pointer allows drivers to associate a fwnode that represents a connector with that connector. When the new fwnode pointer points to an ACPI-companion, then the new acpi_bus_type will cause the ACPI subsys to bind the device instantiated for the connector with the fwnode by calling acpi_bind_one(). This will result in a firmware_node symlink under /sys/class/card#-/ which helps to verify that the fwnode-s and connectors are properly matched. Changes in v2: - Make drm_connector_cleanup() call fwnode_handle_put() on connector->fwnode and document this Co-developed-by: Heikki Krogerus Signed-off-by: Heikki Krogerus Tested-by: Heikki Krogerus Signed-off-by: Hans de Goede --- drivers/gpu/drm/drm_connector.c | 2 ++ drivers/gpu/drm/drm_sysfs.c | 37 + include/drm/drm_connector.h | 8 +++ 3 files changed, 47 insertions(+) diff --git a/drivers/gpu/drm/drm_connector.c b/drivers/gpu/drm/drm_connector.c index 2ba257b1ae20..3ad359a216ff 100644 --- a/drivers/gpu/drm/drm_connector.c +++ b/drivers/gpu/drm/drm_connector.c @@ -474,6 +474,8 @@ void drm_connector_cleanup(struct drm_connector *connector) drm_mode_object_unregister(dev, &connector->base); kfree(connector->name); connector->name = NULL; + fwnode_handle_put(connector->fwnode); + connector->fwnode = NULL; spin_lock_irq(&dev->mode_config.connector_list_lock); list_del(&connector->head); dev->mode_config.num_connector--; diff --git a/drivers/gpu/drm/drm_sysfs.c b/drivers/gpu/drm/drm_sysfs.c index f9d92bbb1f98..bf9edce8e2d1 100644 --- a/drivers/gpu/drm/drm_sysfs.c +++ b/drivers/gpu/drm/drm_sysfs.c @@ -10,6 +10,7 @@ * Copyright (c) 2003-2004 IBM Corp. */ +#include #include #include #include @@ -56,6 +57,39 @@ static struct device_type drm_sysfs_device_connector = { struct class *drm_class; +#ifdef CONFIG_ACPI +static bool drm_connector_acpi_bus_match(struct device *dev) +{ + return dev->type == &drm_sysfs_device_connector; +} + +static struct acpi_device *drm_connector_acpi_find_companion(struct device *dev) +{ + struct drm_connector *connector = to_drm_connector(dev); + + return to_acpi_device_node(connector->fwnode); +} + +static struct acpi_bus_type drm_connector_acpi_bus = { + .name = "drm_connector", + .match = drm_connector_acpi_bus_match, + .find_companion = drm_connector_acpi_find_companion, +}; + +static void drm_sysfs_acpi_register(void) +{ + register_acpi_bus_type(&drm_connector_acpi_bus); +} + +static void drm_sysfs_acpi_unregister(void) +{ + unregister_acpi_bus_type(&drm_connector_acpi_bus); +} +#else +static void drm_sysfs_acpi_register(void) { } +static void drm_sysfs_acpi_unregister(void) { } +#endif + static char *drm_devnode(struct device *dev, umode_t *mode) { return kasprintf(GFP_KERNEL, "dri/%s", dev_name(dev)); @@ -89,6 +123,8 @@ int drm_sysfs_init(void) } drm_class->devnode = drm_devnode; + + drm_sysfs_acpi_register(); return 0; } @@ -101,6 +137,7 @@ void drm_sysfs_destroy(void) { if (IS_ERR_OR_NULL(drm_class)) return; + drm_sysfs_acpi_unregister(); class_remove_file(drm_class, &class_attr_version.attr); class_destroy(drm_class); drm_class = NULL; diff --git a/include/drm/drm_connector.h b/include/drm/drm_connector.h index 1647960c9e50..69dd488a2154 100644 --- a/include/drm/drm_connector.h +++ b/include/drm/drm_connector.h @@ -1228,6 +1228,14 @@ struct drm_connector { struct device *kdev; /** @attr: sysfs attributes */ struct device_attribute *attr; + /** +* @fwnode: associated fwnode supplied by platform firmware +* +* Drivers can set this to associate a fwnode with a connector, drivers +* are expected to get a reference on the fwnode when setting this. +* drm_connector_cleanup() will call fwnode_handle_put() on this. +*/ + struct fwnode_handle *fwnode; /** * @head: -- 2.31.1
[PATCH 3/8] drm/connector: Add drm_connector_find_by_fwnode() function (v3)
Add a function to find a connector based on a fwnode. This will be used by the new drm_connector_oob_hotplug_event() function which is added by the next patch in this patch-set. Changes in v2: - Complete rewrite to use a global connector list in drm_connector.c rather then using a class-dev-iter in drm_sysfs.c Changes in v3: - Add forward declaration for struct fwnode_handle to drm_crtc_internal.h (fixes warning reported by kernel test robot ) Tested-by: Heikki Krogerus Signed-off-by: Hans de Goede --- drivers/gpu/drm/drm_connector.c | 50 + drivers/gpu/drm/drm_crtc_internal.h | 2 ++ include/drm/drm_connector.h | 8 + 3 files changed, 60 insertions(+) diff --git a/drivers/gpu/drm/drm_connector.c b/drivers/gpu/drm/drm_connector.c index 3ad359a216ff..7d72bcefa4d6 100644 --- a/drivers/gpu/drm/drm_connector.c +++ b/drivers/gpu/drm/drm_connector.c @@ -65,6 +65,14 @@ * support can instead use e.g. drm_helper_hpd_irq_event(). */ +/* + * Global connector list for drm_connector_find_by_fwnode(). + * Note drm_connector_[un]register() first take connector->lock and then + * take the connector_list_lock. + */ +static DEFINE_MUTEX(connector_list_lock); +static LIST_HEAD(connector_list); + struct drm_conn_prop_enum_list { int type; const char *name; @@ -267,6 +275,7 @@ int drm_connector_init(struct drm_device *dev, goto out_put_type_id; } + INIT_LIST_HEAD(&connector->global_connector_list_entry); INIT_LIST_HEAD(&connector->probed_modes); INIT_LIST_HEAD(&connector->modes); mutex_init(&connector->mutex); @@ -534,6 +543,9 @@ int drm_connector_register(struct drm_connector *connector) /* Let userspace know we have a new connector */ drm_sysfs_hotplug_event(connector->dev); + mutex_lock(&connector_list_lock); + list_add_tail(&connector->global_connector_list_entry, &connector_list); + mutex_unlock(&connector_list_lock); goto unlock; err_debugfs: @@ -562,6 +574,10 @@ void drm_connector_unregister(struct drm_connector *connector) return; } + mutex_lock(&connector_list_lock); + list_del_init(&connector->global_connector_list_entry); + mutex_unlock(&connector_list_lock); + if (connector->funcs->early_unregister) connector->funcs->early_unregister(connector); @@ -2545,6 +2561,40 @@ int drm_mode_getconnector(struct drm_device *dev, void *data, return ret; } +/** + * drm_connector_find_by_fwnode - Find a connector based on the associated fwnode + * @fwnode: fwnode for which to find the matching drm_connector + * + * This functions looks up a drm_connector based on its associated fwnode. When + * a connector is found a reference to the connector is returned. The caller must + * call drm_connector_put() to release this reference when it is done with the + * connector. + * + * Returns: A reference to the found connector or an ERR_PTR(). + */ +struct drm_connector *drm_connector_find_by_fwnode(struct fwnode_handle *fwnode) +{ + struct drm_connector *connector, *found = ERR_PTR(-ENODEV); + + if (!fwnode) + return ERR_PTR(-ENODEV); + + mutex_lock(&connector_list_lock); + + list_for_each_entry(connector, &connector_list, global_connector_list_entry) { + if (connector->fwnode == fwnode || + (connector->fwnode && connector->fwnode->secondary == fwnode)) { + drm_connector_get(connector); + found = connector; + break; + } + } + + mutex_unlock(&connector_list_lock); + + return found; +} + /** * DOC: Tile group diff --git a/drivers/gpu/drm/drm_crtc_internal.h b/drivers/gpu/drm/drm_crtc_internal.h index edb772947cb4..63279e984342 100644 --- a/drivers/gpu/drm/drm_crtc_internal.h +++ b/drivers/gpu/drm/drm_crtc_internal.h @@ -58,6 +58,7 @@ struct drm_property; struct edid; struct kref; struct work_struct; +struct fwnode_handle; /* drm_crtc.c */ int drm_mode_crtc_set_obj_prop(struct drm_mode_object *obj, @@ -186,6 +187,7 @@ int drm_connector_set_obj_prop(struct drm_mode_object *obj, int drm_connector_create_standard_properties(struct drm_device *dev); const char *drm_get_connector_force_name(enum drm_connector_force force); void drm_connector_free_work_fn(struct work_struct *work); +struct drm_connector *drm_connector_find_by_fwnode(struct fwnode_handle *fwnode); /* IOCTL */ int drm_connector_property_set_ioctl(struct drm_device *dev, diff --git a/include/drm/drm_connector.h b/include/drm/drm_connector.h index 69dd488a2154..8132c48b56ae 100644 --- a/include/drm/drm_connector.h +++ b/include/drm/drm_connector.h @@ -1247,6 +1247,14 @@ struct drm_connector { */ struct lis
[PATCH 4/8] drm/connector: Add support for out-of-band hotplug notification (v3)
Add a new drm_connector_oob_hotplug_event() function and oob_hotplug_event drm_connector_funcs member. On some hardware a hotplug event notification may come from outside the display driver / device. An example of this is some USB Type-C setups where the hardware muxes the DisplayPort data and aux-lines but does not pass the altmode HPD status bit to the GPU's DP HPD pin. In cases like this the new drm_connector_oob_hotplug_event() function can be used to report these out-of-band events. Changes in v2: - Make drm_connector_oob_hotplug_event() take a fwnode as argument and have it call drm_connector_find_by_fwnode() internally. This allows making drm_connector_find_by_fwnode() a drm-internal function and avoids code outside the drm subsystem potentially holding on the a drm_connector reference for a longer period. Changes in v3: - Drop the data argument to the drm_connector_oob_hotplug_event function since it is not used atm. This can be re-added later when a use for it actually arises. Tested-by: Heikki Krogerus Signed-off-by: Hans de Goede --- drivers/gpu/drm/drm_connector.c | 27 +++ include/drm/drm_connector.h | 9 + 2 files changed, 36 insertions(+) diff --git a/drivers/gpu/drm/drm_connector.c b/drivers/gpu/drm/drm_connector.c index 7d72bcefa4d6..e0a30e0ee86a 100644 --- a/drivers/gpu/drm/drm_connector.c +++ b/drivers/gpu/drm/drm_connector.c @@ -2595,6 +2595,33 @@ struct drm_connector *drm_connector_find_by_fwnode(struct fwnode_handle *fwnode) return found; } +/** + * drm_connector_oob_hotplug_event - Report out-of-band hotplug event to connector + * @connector: connector to report the event on + * + * On some hardware a hotplug event notification may come from outside the display + * driver / device. An example of this is some USB Type-C setups where the hardware + * muxes the DisplayPort data and aux-lines but does not pass the altmode HPD + * status bit to the GPU's DP HPD pin. + * + * This function can be used to report these out-of-band events after obtaining + * a drm_connector reference through calling drm_connector_find_by_fwnode(). + */ +void drm_connector_oob_hotplug_event(struct fwnode_handle *connector_fwnode) +{ + struct drm_connector *connector; + + connector = drm_connector_find_by_fwnode(connector_fwnode); + if (IS_ERR(connector)) + return; + + if (connector->funcs->oob_hotplug_event) + connector->funcs->oob_hotplug_event(connector); + + drm_connector_put(connector); +} +EXPORT_SYMBOL(drm_connector_oob_hotplug_event); + /** * DOC: Tile group diff --git a/include/drm/drm_connector.h b/include/drm/drm_connector.h index 8132c48b56ae..79fa34e5ccdb 100644 --- a/include/drm/drm_connector.h +++ b/include/drm/drm_connector.h @@ -1084,6 +1084,14 @@ struct drm_connector_funcs { */ void (*atomic_print_state)(struct drm_printer *p, const struct drm_connector_state *state); + + /** +* @oob_hotplug_event: +* +* This will get called when a hotplug-event for a drm-connector +* has been received from a source outside the display driver / device. +*/ + void (*oob_hotplug_event)(struct drm_connector *connector); }; /** @@ -1666,6 +1674,7 @@ drm_connector_is_unregistered(struct drm_connector *connector) DRM_CONNECTOR_UNREGISTERED; } +void drm_connector_oob_hotplug_event(struct fwnode_handle *connector_fwnode); const char *drm_get_connector_type_name(unsigned int connector_type); const char *drm_get_connector_status_name(enum drm_connector_status status); const char *drm_get_subpixel_order_name(enum subpixel_order order); -- 2.31.1
[PATCH 5/8] drm/i915: Associate ACPI connector nodes with connector entries (v2)
From: Heikki Krogerus On Intel platforms we know that the ACPI connector device node order will follow the order the driver (i915) decides. The decision is made using the custom Intel ACPI OpRegion (intel_opregion.c), though the driver does not actually know that the values it sends to ACPI there are used for associating a device node for the connectors, and assigning address for them. In reality that custom Intel ACPI OpRegion actually violates ACPI specification (we supply dynamic information to objects that are defined static, for example _ADR), however, it makes assigning correct connector node for a connector entry straightforward (it's one-on-one mapping). Changes in v2 (Hans de goede): - Take a reference on the fwnode which we assign to the connector, for ACPI nodes this is a no-op but in the future we may see software-fwnodes assigned to connectors which are ref-counted. Signed-off-by: Heikki Krogerus Tested-by: Heikki Krogerus Signed-off-by: Hans de Goede --- drivers/gpu/drm/i915/display/intel_acpi.c| 46 drivers/gpu/drm/i915/display/intel_acpi.h| 3 ++ drivers/gpu/drm/i915/display/intel_display.c | 1 + 3 files changed, 50 insertions(+) diff --git a/drivers/gpu/drm/i915/display/intel_acpi.c b/drivers/gpu/drm/i915/display/intel_acpi.c index 7cfe91fc05f2..72cac55c0f0f 100644 --- a/drivers/gpu/drm/i915/display/intel_acpi.c +++ b/drivers/gpu/drm/i915/display/intel_acpi.c @@ -282,3 +282,49 @@ void intel_acpi_device_id_update(struct drm_i915_private *dev_priv) } drm_connector_list_iter_end(&conn_iter); } + +/* NOTE: The connector order must be final before this is called. */ +void intel_acpi_assign_connector_fwnodes(struct drm_i915_private *i915) +{ + struct drm_connector_list_iter conn_iter; + struct drm_device *drm_dev = &i915->drm; + struct fwnode_handle *fwnode = NULL; + struct drm_connector *connector; + struct acpi_device *adev; + + drm_connector_list_iter_begin(drm_dev, &conn_iter); + drm_for_each_connector_iter(connector, &conn_iter) { + /* Always getting the next, even when the last was not used. */ + fwnode = device_get_next_child_node(drm_dev->dev, fwnode); + if (!fwnode) + break; + + switch (connector->connector_type) { + case DRM_MODE_CONNECTOR_LVDS: + case DRM_MODE_CONNECTOR_eDP: + case DRM_MODE_CONNECTOR_DSI: + /* +* Integrated displays have a specific address 0x1f on +* most Intel platforms, but not on all of them. +*/ + adev = acpi_find_child_device(ACPI_COMPANION(drm_dev->dev), + 0x1f, 0); + if (adev) { + connector->fwnode = + fwnode_handle_get(acpi_fwnode_handle(adev)); + break; + } + fallthrough; + default: + connector->fwnode = fwnode_handle_get(fwnode); + break; + } + } + drm_connector_list_iter_end(&conn_iter); + /* +* device_get_next_child_node() takes a reference on the fwnode, if +* we stopped iterating because we are out of connectors we need to +* put this, otherwise fwnode is NULL and the put is a no-op. +*/ + fwnode_handle_put(fwnode); +} diff --git a/drivers/gpu/drm/i915/display/intel_acpi.h b/drivers/gpu/drm/i915/display/intel_acpi.h index 9f197401c313..4a760a2baed9 100644 --- a/drivers/gpu/drm/i915/display/intel_acpi.h +++ b/drivers/gpu/drm/i915/display/intel_acpi.h @@ -13,6 +13,7 @@ void intel_register_dsm_handler(void); void intel_unregister_dsm_handler(void); void intel_dsm_get_bios_data_funcs_supported(struct drm_i915_private *i915); void intel_acpi_device_id_update(struct drm_i915_private *i915); +void intel_acpi_assign_connector_fwnodes(struct drm_i915_private *i915); #else static inline void intel_register_dsm_handler(void) { return; } static inline void intel_unregister_dsm_handler(void) { return; } @@ -20,6 +21,8 @@ static inline void intel_dsm_get_bios_data_funcs_supported(struct drm_i915_private *i915) { return; } static inline void intel_acpi_device_id_update(struct drm_i915_private *i915) { return; } +static inline +void intel_acpi_assign_connector_fwnodes(struct drm_i915_private *i915) { return; } #endif /* CONFIG_ACPI */ #endif /* __INTEL_ACPI_H__ */ diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index a257e5dc381c..88e5fff64b8c 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -12561,6 +125
[PATCH 6/8] drm/i915/dp: Add support for out-of-bound hotplug events
On some Cherry Trail devices, DisplayPort over Type-C is supported through a USB-PD microcontroller (e.g. a fusb302) + a mux to switch the superspeed datalines between USB-3 and DP (e.g. a pi3usb30532). The kernel in this case does the PD/alt-mode negotiation itself, rather then everything being handled in firmware. So the kernel itself picks an alt-mode, tells the Type-C "dongle" to switch to DP mode and sets the mux accordingly. In this setup the HPD pin is not connected, so the i915 driver needs to respond to a software event and scan the DP port for changes manually. This commit adds support for this. Together with the recent addition of DP alt-mode support to the Type-C subsystem this makes DP over Type-C work on these devices. Tested-by: Heikki Krogerus Signed-off-by: Hans de Goede --- drivers/gpu/drm/i915/display/intel_dp.c | 12 1 file changed, 12 insertions(+) diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c index 75d4ebc66941..e807ffc2d782 100644 --- a/drivers/gpu/drm/i915/display/intel_dp.c +++ b/drivers/gpu/drm/i915/display/intel_dp.c @@ -4590,6 +4590,17 @@ static int intel_dp_connector_atomic_check(struct drm_connector *conn, return intel_modeset_synced_crtcs(state, conn); } +static void intel_dp_oob_hotplug_event(struct drm_connector *connector) +{ + struct intel_encoder *encoder = intel_attached_encoder(to_intel_connector(connector)); + struct drm_i915_private *i915 = to_i915(connector->dev); + + spin_lock_irq(&i915->irq_lock); + i915->hotplug.event_bits |= BIT(encoder->hpd_pin); + spin_unlock_irq(&i915->irq_lock); + queue_delayed_work(system_wq, &i915->hotplug.hotplug_work, 0); +} + static const struct drm_connector_funcs intel_dp_connector_funcs = { .force = intel_dp_force, .fill_modes = drm_helper_probe_single_connector_modes, @@ -4600,6 +4611,7 @@ static const struct drm_connector_funcs intel_dp_connector_funcs = { .destroy = intel_connector_destroy, .atomic_destroy_state = drm_atomic_helper_connector_destroy_state, .atomic_duplicate_state = intel_digital_connector_duplicate_state, + .oob_hotplug_event = intel_dp_oob_hotplug_event, }; static const struct drm_connector_helper_funcs intel_dp_connector_helper_funcs = { -- 2.31.1
[PATCH 7/8] usb: typec: altmodes/displayport: Make dp_altmode_notify() more generic
Make dp_altmode_notify() handle the dp->data.conf == 0 case too, rather then having separate code-paths for this in various places which call it. Reviewed-by: Heikki Krogerus Tested-by: Heikki Krogerus Signed-off-by: Hans de Goede --- drivers/usb/typec/altmodes/displayport.c | 35 +--- 1 file changed, 13 insertions(+), 22 deletions(-) diff --git a/drivers/usb/typec/altmodes/displayport.c b/drivers/usb/typec/altmodes/displayport.c index b7f094435b00..aa669b9cf70e 100644 --- a/drivers/usb/typec/altmodes/displayport.c +++ b/drivers/usb/typec/altmodes/displayport.c @@ -66,10 +66,17 @@ struct dp_altmode { static int dp_altmode_notify(struct dp_altmode *dp) { - u8 state = get_count_order(DP_CONF_GET_PIN_ASSIGN(dp->data.conf)); + unsigned long conf; + u8 state; + + if (dp->data.conf) { + state = get_count_order(DP_CONF_GET_PIN_ASSIGN(dp->data.conf)); + conf = TYPEC_MODAL_STATE(state); + } else { + conf = TYPEC_STATE_USB; + } - return typec_altmode_notify(dp->alt, TYPEC_MODAL_STATE(state), - &dp->data); + return typec_altmode_notify(dp->alt, conf, &dp->data); } static int dp_altmode_configure(struct dp_altmode *dp, u8 con) @@ -137,21 +144,10 @@ static int dp_altmode_status_update(struct dp_altmode *dp) static int dp_altmode_configured(struct dp_altmode *dp) { - int ret; - sysfs_notify(&dp->alt->dev.kobj, "displayport", "configuration"); - - if (!dp->data.conf) - return typec_altmode_notify(dp->alt, TYPEC_STATE_USB, - &dp->data); - - ret = dp_altmode_notify(dp); - if (ret) - return ret; - sysfs_notify(&dp->alt->dev.kobj, "displayport", "pin_assignment"); - return 0; + return dp_altmode_notify(dp); } static int dp_altmode_configure_vdm(struct dp_altmode *dp, u32 conf) @@ -172,13 +168,8 @@ static int dp_altmode_configure_vdm(struct dp_altmode *dp, u32 conf) } ret = typec_altmode_vdm(dp->alt, header, &conf, 2); - if (ret) { - if (DP_CONF_GET_PIN_ASSIGN(dp->data.conf)) - dp_altmode_notify(dp); - else - typec_altmode_notify(dp->alt, TYPEC_STATE_USB, -&dp->data); - } + if (ret) + dp_altmode_notify(dp); return ret; } -- 2.31.1
[PATCH 8/8] usb: typec: altmodes/displayport: Notify drm subsys of hotplug events
Use the new drm_connector_oob_hotplug_event() functions to let drm/kms drivers know about DisplayPort over Type-C hotplug events. Reviewed-by: Heikki Krogerus Tested-by: Heikki Krogerus Signed-off-by: Hans de Goede --- Changes in v3: - Only call drm_connector_oob_hotplug_event() on hpd status bit change - Adjust for drm_connector_oob_hotplug_event() no longer having a data argument 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 | 23 +++ 2 files changed, 24 insertions(+) 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..c1d8c23baa39 100644 --- a/drivers/usb/typec/altmodes/displayport.c +++ b/drivers/usb/typec/altmodes/displayport.c @@ -11,8 +11,10 @@ #include #include #include +#include #include #include +#include #include "displayport.h" #define DP_HEADER(_dp, ver, cmd) (VDO((_dp)->alt->svid, 1, ver, cmd) \ @@ -57,11 +59,13 @@ struct dp_altmode { struct typec_displayport_data data; enum dp_state state; + bool hpd; struct mutex lock; /* device lock */ struct work_struct work; struct typec_altmode *alt; const struct typec_altmode *port; + struct fwnode_handle *connector_fwnode; }; static int dp_altmode_notify(struct dp_altmode *dp) @@ -125,6 +129,7 @@ static int dp_altmode_configure(struct dp_altmode *dp, u8 con) static int dp_altmode_status_update(struct dp_altmode *dp) { bool configured = !!DP_CONF_GET_PIN_ASSIGN(dp->data.conf); + bool hpd = !!(dp->data.status & DP_STATUS_HPD_STATE); u8 con = DP_STATUS_CONNECTION(dp->data.status); int ret = 0; @@ -137,6 +142,11 @@ static int dp_altmode_status_update(struct dp_altmode *dp) ret = dp_altmode_configure(dp, con); if (!ret) dp->state = DP_STATE_CONFIGURE; + } else { + if (dp->hpd != hpd) { + drm_connector_oob_hotplug_event(dp->connector_fwnode); + dp->hpd = hpd; + } } return ret; @@ -512,6 +522,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 +551,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 +571,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) { + if (dp->hpd) + drm_connector_oob_hotplug_event(dp->connector_fwnode); + + fwnode_handle_put(dp->connector_fwnode); + } } EXPORT_SYMBOL_GPL(dp_altmode_remove); -- 2.31.1
[GIT PULL] drm-misc + drm-intel: Add support for out-of-band hotplug notification
Hello drm-misc and drm-intel maintainers, My "Add support for out-of-band hotplug notification" patchset: https://patchwork.freedesktop.org/series/93763/ Is ready for merging now, as discussed on IRC I based this series on top drm-tip and when trying to apply the i915 parts on top of drm-misc this fails due to conflict. So as Jani suggested here is a pull-req for a topic-branch with the entire set, minus the troublesome i915 bits. Once this has been merged into both drm-misc-next and drm-intel-next I can push the 2 i915 patch do drm-intel-next on top of the merge. Note there are also 2 drivers/usb/typec patches in here these have Greg KH's Reviewed-by for merging through the drm tree, Since this USB code does not change all that much. I also checked and the drm-misc-next-2021-08-12 base of this tree contains the same last commit to the modified file as usb-next. Daniel Vetter mentioned on IRC that it might be better for you to simply pick-up the series directly from patchwork, that is fine too in that case don't forget to add: Reviewed-by: Lyude Paul To the entire series (given in a reply to the cover-letter) And: Reviewed-by: Greg Kroah-Hartman To the usb/typec patches (patch 7/8), this was given in reply to a previous posting of the series and I forgot to add this in the resend. Regards, Hans The following changes since commit c7782443a88926a4f938f0193041616328cf2db2: drm/bridge: ti-sn65dsi86: Avoid creating multiple connectors (2021-08-12 09:56:09 -0700) are available in the Git repository at: git://git.kernel.org/pub/scm/linux/kernel/git/hansg/linux.git drm-misc-intel-oob-hotplug-v1 for you to fetch changes up to 7f811394878535ed9a6849717de8c2959ae38899: usb: typec: altmodes/displayport: Notify drm subsys of hotplug events (2021-08-20 12:35:59 +0200) Topic branch for drm-misc / drm-intel for OOB hotplug support for Type-C connectors -------- Hans de Goede (6): drm/connector: Give connector sysfs devices there own device_type drm/connector: Add a fwnode pointer to drm_connector and register with ACPI (v2) drm/connector: Add drm_connector_find_by_fwnode() function (v3) drm/connector: Add support for out-of-band hotplug notification (v3) usb: typec: altmodes/displayport: Make dp_altmode_notify() more generic usb: typec: altmodes/displayport: Notify drm subsys of hotplug events drivers/gpu/drm/drm_connector.c | 79 + drivers/gpu/drm/drm_crtc_internal.h | 2 + drivers/gpu/drm/drm_sysfs.c | 87 +++- drivers/usb/typec/altmodes/Kconfig | 1 + drivers/usb/typec/altmodes/displayport.c | 58 + include/drm/drm_connector.h | 25 + 6 files changed, 217 insertions(+), 35 deletions(-)
Re: [GIT PULL] drm-misc + drm-intel: Add support for out-of-band hotplug notification
Hi, On 8/24/21 10:45 AM, Jani Nikula wrote: > On Fri, 20 Aug 2021, Hans de Goede wrote: >> Hello drm-misc and drm-intel maintainers, >> >> My "Add support for out-of-band hotplug notification" patchset: >> https://patchwork.freedesktop.org/series/93763/ >> >> Is ready for merging now, as discussed on IRC I based this series >> on top drm-tip and when trying to apply the i915 parts on top >> of drm-misc this fails due to conflict. >> >> So as Jani suggested here is a pull-req for a topic-branch with the >> entire set, minus the troublesome i915 bits. Once this has been merged >> into both drm-misc-next and drm-intel-next I can push the 2 i915 >> patch do drm-intel-next on top of the merge. >> >> Note there are also 2 drivers/usb/typec patches in here these >> have Greg KH's Reviewed-by for merging through the drm tree, >> Since this USB code does not change all that much. I also checked >> and the drm-misc-next-2021-08-12 base of this tree contains the >> same last commit to the modified file as usb-next. >> >> Daniel Vetter mentioned on IRC that it might be better for you to simply >> pick-up the series directly from patchwork, that is fine too in that >> case don't forget to add: >> >> Reviewed-by: Lyude Paul >> >> To the entire series (given in a reply to the cover-letter) >> >> And: >> >> Reviewed-by: Greg Kroah-Hartman >> >> To the usb/typec patches (patch 7/8), this was given in reply >> to a previous posting of the series and I forgot to add this >> in the resend. > > Since this is mostly touching drm core, I think it should be merged to > drm-misc-next first, and drm-intel-next after. Please let us know. I agree this should go to drm-misc-next first. (I was planning on pushing this to drm-misc-next myself, but then ended up going with the topic branch because of the conflict in the i915 bits.) Regards, Hans >> The following changes since commit c7782443a88926a4f938f0193041616328cf2db2: >> >> drm/bridge: ti-sn65dsi86: Avoid creating multiple connectors (2021-08-12 >> 09:56:09 -0700) >> >> are available in the Git repository at: >> >> git://git.kernel.org/pub/scm/linux/kernel/git/hansg/linux.git >> drm-misc-intel-oob-hotplug-v1 >> >> for you to fetch changes up to 7f811394878535ed9a6849717de8c2959ae38899: >> >> usb: typec: altmodes/displayport: Notify drm subsys of hotplug events >> (2021-08-20 12:35:59 +0200) >> >> >> Topic branch for drm-misc / drm-intel for OOB hotplug support for Type-C >> connectors >> >> >> Hans de Goede (6): >> drm/connector: Give connector sysfs devices there own device_type >> drm/connector: Add a fwnode pointer to drm_connector and register with >> ACPI (v2) >> drm/connector: Add drm_connector_find_by_fwnode() function (v3) >> drm/connector: Add support for out-of-band hotplug notification (v3) >> usb: typec: altmodes/displayport: Make dp_altmode_notify() more generic >> usb: typec: altmodes/displayport: Notify drm subsys of hotplug events >> >> drivers/gpu/drm/drm_connector.c | 79 + >> drivers/gpu/drm/drm_crtc_internal.h | 2 + >> drivers/gpu/drm/drm_sysfs.c | 87 >> +++- >> drivers/usb/typec/altmodes/Kconfig | 1 + >> drivers/usb/typec/altmodes/displayport.c | 58 + >> include/drm/drm_connector.h | 25 + >> 6 files changed, 217 insertions(+), 35 deletions(-) >> >
Re: [PATCH] drm/i915/display/vlv_dsi: Do no shut down displays on reboot if a DSI panel is used
Hi, On 3/1/21 4:43 PM, Hans de Goede wrote: > After the recently added commit fe0f1e3bfdfe ("drm/i915: Shut down > displays gracefully on reboot"), the DSI panel on a Cherry Trail based > Predia Basic tablet would no longer properly light up after reboot. > > The backlight still turns back on after reboot, but the LCD shows an > all black display. The display is also all black during the time that > EFI / the GOP is managing it, so e.g. the grub menu also is not visible. > > In this scenario the panel is initialized so that it appears to be working > and the fastboot code skips doing a modeset. Forcing a modeset by doing a > chvt to a text-console over ssh followed by echo-ing 1 and then 0 to > /sys/class/graphics/fb0/blank causes the panel to work again. > > Add a QUIRK_SKIP_SHUTDOWN quirk which turns i915_driver_shutdown() into > a no-op when set; and set this on vlv/chv devices when a DSI panel is > detected, to work around this. > > Admittedly this is a bit of a big hammer, but these platforms have been > around for quite some time now and they have always worked fine without > the new behavior to shutdown everything on shutdown/reboot. This approach > simply disables the recently introduced new shutdown behavior in this > specific case where it is known to cause problems. Which is a nice and > simple way to deal with this. > > Signed-off-by: Hans de Goede Ping? Since sending this patch I've been seeing the issue addressed by this on variour other CHT based devices too. So we have various devices suffering from a black screen after reboot now. This is pretty serious usability regression. As such it would be good to get this reviewed, or another fix proposed. Regards, Hans > --- > drivers/gpu/drm/i915/display/vlv_dsi.c | 3 +++ > drivers/gpu/drm/i915/i915_drv.c| 3 +++ > drivers/gpu/drm/i915/i915_drv.h| 1 + > 3 files changed, 7 insertions(+) > > diff --git a/drivers/gpu/drm/i915/display/vlv_dsi.c > b/drivers/gpu/drm/i915/display/vlv_dsi.c > index f94025ec603a..792ef868b6af 100644 > --- a/drivers/gpu/drm/i915/display/vlv_dsi.c > +++ b/drivers/gpu/drm/i915/display/vlv_dsi.c > @@ -1949,6 +1949,9 @@ void vlv_dsi_init(struct drm_i915_private *dev_priv) > > vlv_dsi_add_properties(intel_connector); > > + /* Some BIOS-es fail to re-init the DSI panel on reboot if we turn it > off */ > + dev_priv->quirks |= QUIRK_SKIP_SHUTDOWN; > + > return; > > err_cleanup_connector: > diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c > index 8e9cb44e66e5..92f2af55af6d 100644 > --- a/drivers/gpu/drm/i915/i915_drv.c > +++ b/drivers/gpu/drm/i915/i915_drv.c > @@ -1048,6 +1048,9 @@ static void intel_shutdown_encoders(struct > drm_i915_private *dev_priv) > > void i915_driver_shutdown(struct drm_i915_private *i915) > { > + if (i915->quirks & QUIRK_SKIP_SHUTDOWN) > + return; > + > disable_rpm_wakeref_asserts(&i915->runtime_pm); > > i915_gem_suspend(i915); > diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h > index 26d69d06aa6d..272cd7cb22d4 100644 > --- a/drivers/gpu/drm/i915/i915_drv.h > +++ b/drivers/gpu/drm/i915/i915_drv.h > @@ -517,6 +517,7 @@ struct i915_psr { > #define QUIRK_PIN_SWIZZLED_PAGES (1<<5) > #define QUIRK_INCREASE_T12_DELAY (1<<6) > #define QUIRK_INCREASE_DDI_DISABLED_TIME (1<<7) > +#define QUIRK_SKIP_SHUTDOWN (1<<8) > > struct intel_fbdev; > struct intel_fbc_work; > ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
Re: [Intel-gfx] [PATCH] drm/i915/display/vlv_dsi: Do no shut down displays on reboot if a DSI panel is used
Hi, On 3/22/21 9:59 PM, Ville Syrjälä wrote: > On Mon, Mar 22, 2021 at 04:51:47PM -0400, Rodrigo Vivi wrote: >> On Fri, Mar 19, 2021 at 04:45:32PM +0100, Hans de Goede wrote: >>> Hi, >>> >>> On 3/1/21 4:43 PM, Hans de Goede wrote: >>>> After the recently added commit fe0f1e3bfdfe ("drm/i915: Shut down >>>> displays gracefully on reboot"), the DSI panel on a Cherry Trail based >>>> Predia Basic tablet would no longer properly light up after reboot. >>>> >>>> The backlight still turns back on after reboot, but the LCD shows an >>>> all black display. The display is also all black during the time that >>>> EFI / the GOP is managing it, so e.g. the grub menu also is not visible. >>>> >>>> In this scenario the panel is initialized so that it appears to be working >>>> and the fastboot code skips doing a modeset. Forcing a modeset by doing a >>>> chvt to a text-console over ssh followed by echo-ing 1 and then 0 to >>>> /sys/class/graphics/fb0/blank causes the panel to work again. >>>> >>>> Add a QUIRK_SKIP_SHUTDOWN quirk which turns i915_driver_shutdown() into >>>> a no-op when set; and set this on vlv/chv devices when a DSI panel is >>>> detected, to work around this. >>>> >>>> Admittedly this is a bit of a big hammer, but these platforms have been >>>> around for quite some time now and they have always worked fine without >>>> the new behavior to shutdown everything on shutdown/reboot. This approach >>>> simply disables the recently introduced new shutdown behavior in this >>>> specific case where it is known to cause problems. Which is a nice and >>>> simple way to deal with this. >>>> >>>> Signed-off-by: Hans de Goede >>> >>> Ping? Since sending this patch I've been seeing the issue addressed by >>> this on variour other CHT based devices too. >>> >>> So we have various devices suffering from a black screen after reboot >>> now. This is pretty serious usability regression. >>> >>> As such it would be good to get this reviewed, or another fix proposed. >> >> For the quirks we try to limit them to very specific vendor and model ids, >> so I wonder if it would be possible to get this information in here instead >> to all the vlv with dsi... >> >> Or avoid the quirk "infra" and skip to all vlv with active dsi?! >> >> Jani? >> Ville? > > We need to figure out why the panel doesn't start up again. Note it is the GOP which fails to light it up again. I think we turn something off, which after a power-on-reset is on, so the GOP expects it to be on. > If it has > problems with this then surely it also fails if we just happen to reboot > with the panel already off? I would assume so, yes, but that only happens on say a "reboot --force" over ssh, while the screen is off. Which are rather exceptional circumstances. Where as just a regular reboot is quite normal and now results in a black screen. And recovery of this condition by a normal user involves a power-cycle by pressing the power-button for 10 seconds (these are tablets so the force-power-off time is quite long), which most users don't even know they can do... > Oh a modeset fixes it? Then I guess it's just fastboot fail due to DSI > code being crap? This is not a fastboot issue, if I make the grub menu show every boot, the grub-menu is also all black, as the GOP fails to properly initialize the panel when this happens fastboot just inherits this condition. Assuming that we want to have the EFI gfx/console work on reboot (for say the grub menu), then disabling fastboot is not going to help. Also note that the Windows boot-splash with the circling dots uses the efifb, so rebooting into Windows also leads to a blackscreen at least until Windows has booted all the way. Note I have not tried Windows, so I don't know if Windows will recover from the black screen once its gfx driver loads, or if it stays black then too. > If no one is willing to fix it then I guess we just > need to disable fastboot for DSI somehow. See above, this is a GOP issue, so there is nothing for us to fix, what we need to do is stop leaving the hw in a state which the GOP cannot deal with. Which leads me to believe that we just need to disable the "graceful shutdown" on the combination of DSI + BYT/CHT. Regards, Hans ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
Re: [Intel-gfx] [PATCH resend 2/2] drm/i915/display: Make vlv_find_free_pps() skip pipes which are in use for non DP purposes
Hi, On 3/2/21 3:51 PM, Ville Syrjälä wrote: > On Tue, Mar 02, 2021 at 01:00:40PM +0100, Hans de Goede wrote: >> As explained by a long comment block, on VLV intel_setup_outputs() >> sometimes thinks there might be an eDP panel connected while there is none. >> In this case intel_setup_outputs() will call intel_dp_init() to check. >> >> In this scenario vlv_find_free_pps() ends up selecting pipe A for the pps, >> even though this might be in use for non DP purposes. When this is the case >> then the assert_pipe() in vlv_force_pll_on() will fail when called from >> vlv_power_sequencer_kick(). > > The idea is that you *can* select a PPS from a pipe used for a non-DP > port since those don't care about the PPS stuff. So this doesn't seem > correct. They may not care about the PPS stuff, but as the WARN / backtrace shows if the DPLL_VCO_ENABLE bit is not already set for the pipe, while the pipe is "otherwise" in use then vlv_force_pll_on() becomes unhappy triggering the WARN. > a) I would like to see the VBT for this machine https://fedorapeople.org/~jwrdegoede/voyo-winpad-a15-vbt > b) I wonder if the DSI PLL is sufficient for getting the PPS going? I have no idea, I just noticed the WARN / backtrace and this seemed like a reasonably way to deal with it. With that said I'm fine with fixing this a different way. > c) If we do need the normal DPLL is there any harm to DSI in enabling it? I would assume this increases power-consumption and DSI panels are almost always used in battery powered devices. Also this would impact all BYT/CHT devices, possible triggering unwanted side-effects. Where as the proposed fix below is much more narrowly targeted at the problem. It might not be the most pretty fix but AFAICT it has a low risk of causing regressions. Regards, Hans > >> >> This happens on a Voyo winpad A15, leading to the following WARN/backtrace: >> >> [8.661531] [ cut here ] >> [8.661590] transcoder A assertion failure (expected off, current on) >> [8.661647] WARNING: CPU: 2 PID: 243 at >> drivers/gpu/drm/i915/display/intel_display.c:1288 assert_pipe+0x125/0xc20 >> [i915] >> [8.661822] Modules linked in: i915(E+) mmc_block crct10dif_pclmul >> crc32_pclmul crc32c_intel ghash_clmulni_intel i2c_algo_bit drm_kms_helper >> cec drm drm_privacy_screen_helper video(E) sdhci_acpi sdhci i2c_hid >> pwm_lpss_platform pwm_lpss mmc_core i2c_dev fuse >> [8.661944] CPU: 2 PID: 243 Comm: systemd-udevd Tainted: GE >> 5.11.0-rc5+ #228 >> [8.661954] Hardware name: To be filled by O.E.M. To be filled by >> O.E.M./Aptio CRB, BIOS 5.6.5 11/20/2014 >> [8.661961] RIP: 0010:assert_pipe+0x125/0xc20 [i915] >> [8.662050] Code: c7 c2 e5 39 4a c0 74 c9 48 c7 c6 53 3b 4a c0 83 fb 06 >> 77 0a 89 db 48 8b 34 dd 80 38 45 c0 48 c7 c7 c8 ff 47 c0 e8 13 6c 8f df <0f> >> 0b e9 1d ff ff ff 89 db 48 8b 34 dd 80 38 45 c0 eb a0 48 c7 c2 >> [8.662058] RSP: 0018:a939c0557690 EFLAGS: 00010286 >> [8.662071] RAX: 0039 RBX: RCX: >> 89c67bd19058 >> [8.662078] RDX: ffd8 RSI: 0027 RDI: >> 89c67bd19050 >> [8.662085] RBP: 89c64a3c R08: 0001 R09: >> 0001 >> [8.662091] R10: a939c05574c0 R11: a0961248 R12: >> 0009 >> [8.662098] R13: R14: e000 R15: >> 89c64a3c >> [8.662105] FS: 7fe824e42380() GS:89c67bd0() >> knlGS: >> [8.662113] CS: 0010 DS: ES: CR0: 80050033 >> [8.662120] CR2: 7fffdc770558 CR3: 000106ab8000 CR4: >> 001006e0 >> [8.662127] Call Trace: >> [8.662148] assert_pipe+0xa9e/0xc20 [i915] >> [8.662252] vlv_force_pll_on+0xfb/0x1b0 [i915] >> [8.662344] intel_dp_sync_state+0xd92/0x2e70 [i915] >> [8.662448] intel_dp_sync_state+0x1908/0x2e70 [i915] >> [8.662541] intel_dp_sync_state+0x1a3e/0x2e70 [i915] >> [8.662620] ? recalibrate_cpu_khz+0x10/0x10 >> [8.662633] ? ktime_get_with_offset+0xad/0x160 >> [8.662658] intel_dp_sync_state+0x1f21/0x2e70 [i915] >> [8.662788] intel_dp_encoder_suspend+0x41f/0x14b0 [i915] >> [8.662875] ? drm_dp_dpcd_access+0x50/0xf0 [drm_kms_helper] >> [8.662940] ? __mutex_lock+0x7e/0x7a0 >> [8.662950] ? drm_dp_dpcd_access+0x50/0xf0 [drm_kms_helper] >> [8.662982] ? drm_dp_dpcd_access+0x50/0xf0 [drm_kms_helper] >> [8.663025] intel_dp_encoder_suspend+0xdf3/0x14b0 [i915] >> [8.663112] ?
Re: [Intel-gfx] [PATCH] drm/i915/display/vlv_dsi: Do no shut down displays on reboot if a DSI panel is used
Hi, On 3/22/21 10:47 PM, Ville Syrjälä wrote: > On Mon, Mar 22, 2021 at 10:28:06PM +0100, Hans de Goede wrote: >> Hi, >> >> On 3/22/21 9:59 PM, Ville Syrjälä wrote: >>> On Mon, Mar 22, 2021 at 04:51:47PM -0400, Rodrigo Vivi wrote: >>>> On Fri, Mar 19, 2021 at 04:45:32PM +0100, Hans de Goede wrote: >>>>> Hi, >>>>> >>>>> On 3/1/21 4:43 PM, Hans de Goede wrote: >>>>>> After the recently added commit fe0f1e3bfdfe ("drm/i915: Shut down >>>>>> displays gracefully on reboot"), the DSI panel on a Cherry Trail based >>>>>> Predia Basic tablet would no longer properly light up after reboot. >>>>>> >>>>>> The backlight still turns back on after reboot, but the LCD shows an >>>>>> all black display. The display is also all black during the time that >>>>>> EFI / the GOP is managing it, so e.g. the grub menu also is not visible. >>>>>> >>>>>> In this scenario the panel is initialized so that it appears to be >>>>>> working >>>>>> and the fastboot code skips doing a modeset. Forcing a modeset by doing a >>>>>> chvt to a text-console over ssh followed by echo-ing 1 and then 0 to >>>>>> /sys/class/graphics/fb0/blank causes the panel to work again. >>>>>> >>>>>> Add a QUIRK_SKIP_SHUTDOWN quirk which turns i915_driver_shutdown() into >>>>>> a no-op when set; and set this on vlv/chv devices when a DSI panel is >>>>>> detected, to work around this. >>>>>> >>>>>> Admittedly this is a bit of a big hammer, but these platforms have been >>>>>> around for quite some time now and they have always worked fine without >>>>>> the new behavior to shutdown everything on shutdown/reboot. This approach >>>>>> simply disables the recently introduced new shutdown behavior in this >>>>>> specific case where it is known to cause problems. Which is a nice and >>>>>> simple way to deal with this. >>>>>> >>>>>> Signed-off-by: Hans de Goede >>>>> >>>>> Ping? Since sending this patch I've been seeing the issue addressed by >>>>> this on variour other CHT based devices too. >>>>> >>>>> So we have various devices suffering from a black screen after reboot >>>>> now. This is pretty serious usability regression. >>>>> >>>>> As such it would be good to get this reviewed, or another fix proposed. >>>> >>>> For the quirks we try to limit them to very specific vendor and model ids, >>>> so I wonder if it would be possible to get this information in here instead >>>> to all the vlv with dsi... >>>> >>>> Or avoid the quirk "infra" and skip to all vlv with active dsi?! >>>> >>>> Jani? >>>> Ville? >>> >>> We need to figure out why the panel doesn't start up again. >> >> Note it is the GOP which fails to light it up again. I think we turn >> something >> off, which after a power-on-reset is on, so the GOP expects it to be on. > > Hmm. Do any of the reboot=warm|cold|whatever knobs make a difference? > Are there any fast vs. slow boot settings in the BIOS setup? Ok, so I was running the tests which you requested and during this I managed to find the real problem. What happens on reboot is a really quick panel off/on cycle and that is causing the issue. I can reproduce this by doing: chvt 3; echo 1 > /sys/class/graphics/fb0/blank; echo 0 > /sys/class/graphics/fb0/blank The problem is that we're not honoring panel_pwr_cycle_delay because intel_dsi_msleep() is a no-op on devices with a MIPI-sequences version >= 3, because those sequences already contain the necessary delays, at least for most of the steps during the on/off sequences. It seems that the pwr-cycle delay is not handled by those v3+ sequences. So fixing this is as simple as switching to a regular msleep for the intel_dsi->panel_pwr_cycle_delay. Once we do that it would be good (for e.g. suspend/resume speed) to fix: /* * FIXME As we do with eDP, just make a note of the time here * and perform the wait before the next panel power on. */ Which sits right above that msleep. Since I have a reproducer now which shows when the sleep is too short, it should now be easy ti fix the FIXME and test that the fix works. I'll do this in a separate patch and send a patch-set with both patches replacing this patch. Regards, Hans ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
Re: [Intel-gfx] [PATCH] drm/i915/display/vlv_dsi: Do no shut down displays on reboot if a DSI panel is used
Hi, On 3/23/21 6:51 PM, Ville Syrjälä wrote: > On Tue, Mar 23, 2021 at 06:29:53PM +0100, Hans de Goede wrote: >> Hi, >> >> On 3/22/21 10:47 PM, Ville Syrjälä wrote: >>> On Mon, Mar 22, 2021 at 10:28:06PM +0100, Hans de Goede wrote: >>>> Hi, >>>> >>>> On 3/22/21 9:59 PM, Ville Syrjälä wrote: >>>>> On Mon, Mar 22, 2021 at 04:51:47PM -0400, Rodrigo Vivi wrote: >>>>>> On Fri, Mar 19, 2021 at 04:45:32PM +0100, Hans de Goede wrote: >>>>>>> Hi, >>>>>>> >>>>>>> On 3/1/21 4:43 PM, Hans de Goede wrote: >>>>>>>> After the recently added commit fe0f1e3bfdfe ("drm/i915: Shut down >>>>>>>> displays gracefully on reboot"), the DSI panel on a Cherry Trail based >>>>>>>> Predia Basic tablet would no longer properly light up after reboot. >>>>>>>> >>>>>>>> The backlight still turns back on after reboot, but the LCD shows an >>>>>>>> all black display. The display is also all black during the time that >>>>>>>> EFI / the GOP is managing it, so e.g. the grub menu also is not >>>>>>>> visible. >>>>>>>> >>>>>>>> In this scenario the panel is initialized so that it appears to be >>>>>>>> working >>>>>>>> and the fastboot code skips doing a modeset. Forcing a modeset by >>>>>>>> doing a >>>>>>>> chvt to a text-console over ssh followed by echo-ing 1 and then 0 to >>>>>>>> /sys/class/graphics/fb0/blank causes the panel to work again. >>>>>>>> >>>>>>>> Add a QUIRK_SKIP_SHUTDOWN quirk which turns i915_driver_shutdown() into >>>>>>>> a no-op when set; and set this on vlv/chv devices when a DSI panel is >>>>>>>> detected, to work around this. >>>>>>>> >>>>>>>> Admittedly this is a bit of a big hammer, but these platforms have been >>>>>>>> around for quite some time now and they have always worked fine without >>>>>>>> the new behavior to shutdown everything on shutdown/reboot. This >>>>>>>> approach >>>>>>>> simply disables the recently introduced new shutdown behavior in this >>>>>>>> specific case where it is known to cause problems. Which is a nice and >>>>>>>> simple way to deal with this. >>>>>>>> >>>>>>>> Signed-off-by: Hans de Goede >>>>>>> >>>>>>> Ping? Since sending this patch I've been seeing the issue addressed by >>>>>>> this on variour other CHT based devices too. >>>>>>> >>>>>>> So we have various devices suffering from a black screen after reboot >>>>>>> now. This is pretty serious usability regression. >>>>>>> >>>>>>> As such it would be good to get this reviewed, or another fix proposed. >>>>>> >>>>>> For the quirks we try to limit them to very specific vendor and model >>>>>> ids, >>>>>> so I wonder if it would be possible to get this information in here >>>>>> instead >>>>>> to all the vlv with dsi... >>>>>> >>>>>> Or avoid the quirk "infra" and skip to all vlv with active dsi?! >>>>>> >>>>>> Jani? >>>>>> Ville? >>>>> >>>>> We need to figure out why the panel doesn't start up again. >>>> >>>> Note it is the GOP which fails to light it up again. I think we turn >>>> something >>>> off, which after a power-on-reset is on, so the GOP expects it to be on. >>> >>> Hmm. Do any of the reboot=warm|cold|whatever knobs make a difference? >>> Are there any fast vs. slow boot settings in the BIOS setup? >> >> Ok, so I was running the tests which you requested and during this >> I managed to find the real problem. >> >> What happens on reboot is a really quick panel off/on cycle and that is >> causing the issue. >> >> I can reproduce this by doing: >> >> chvt 3; echo 1 > /sys/class/graphics/fb0/blank; echo 0 > >> /sys/class/graphics/fb0/blank >> >> The problem is that we're not honoring panel_pwr_
Re: [Intel-gfx] [PATCH] drm/i915/display/vlv_dsi: Do no shut down displays on reboot if a DSI panel is used
HI, On 3/23/21 8:13 PM, Hans de Goede wrote: > Hi, > > On 3/23/21 6:51 PM, Ville Syrjälä wrote: >> On Tue, Mar 23, 2021 at 06:29:53PM +0100, Hans de Goede wrote: >>> Hi, >>> >>> On 3/22/21 10:47 PM, Ville Syrjälä wrote: >>>> On Mon, Mar 22, 2021 at 10:28:06PM +0100, Hans de Goede wrote: >>>>> Hi, >>>>> >>>>> On 3/22/21 9:59 PM, Ville Syrjälä wrote: >>>>>> On Mon, Mar 22, 2021 at 04:51:47PM -0400, Rodrigo Vivi wrote: >>>>>>> On Fri, Mar 19, 2021 at 04:45:32PM +0100, Hans de Goede wrote: >>>>>>>> Hi, >>>>>>>> >>>>>>>> On 3/1/21 4:43 PM, Hans de Goede wrote: >>>>>>>>> After the recently added commit fe0f1e3bfdfe ("drm/i915: Shut down >>>>>>>>> displays gracefully on reboot"), the DSI panel on a Cherry Trail based >>>>>>>>> Predia Basic tablet would no longer properly light up after reboot. >>>>>>>>> >>>>>>>>> The backlight still turns back on after reboot, but the LCD shows an >>>>>>>>> all black display. The display is also all black during the time that >>>>>>>>> EFI / the GOP is managing it, so e.g. the grub menu also is not >>>>>>>>> visible. >>>>>>>>> >>>>>>>>> In this scenario the panel is initialized so that it appears to be >>>>>>>>> working >>>>>>>>> and the fastboot code skips doing a modeset. Forcing a modeset by >>>>>>>>> doing a >>>>>>>>> chvt to a text-console over ssh followed by echo-ing 1 and then 0 to >>>>>>>>> /sys/class/graphics/fb0/blank causes the panel to work again. >>>>>>>>> >>>>>>>>> Add a QUIRK_SKIP_SHUTDOWN quirk which turns i915_driver_shutdown() >>>>>>>>> into >>>>>>>>> a no-op when set; and set this on vlv/chv devices when a DSI panel is >>>>>>>>> detected, to work around this. >>>>>>>>> >>>>>>>>> Admittedly this is a bit of a big hammer, but these platforms have >>>>>>>>> been >>>>>>>>> around for quite some time now and they have always worked fine >>>>>>>>> without >>>>>>>>> the new behavior to shutdown everything on shutdown/reboot. This >>>>>>>>> approach >>>>>>>>> simply disables the recently introduced new shutdown behavior in this >>>>>>>>> specific case where it is known to cause problems. Which is a nice and >>>>>>>>> simple way to deal with this. >>>>>>>>> >>>>>>>>> Signed-off-by: Hans de Goede >>>>>>>> >>>>>>>> Ping? Since sending this patch I've been seeing the issue addressed by >>>>>>>> this on variour other CHT based devices too. >>>>>>>> >>>>>>>> So we have various devices suffering from a black screen after reboot >>>>>>>> now. This is pretty serious usability regression. >>>>>>>> >>>>>>>> As such it would be good to get this reviewed, or another fix proposed. >>>>>>> >>>>>>> For the quirks we try to limit them to very specific vendor and model >>>>>>> ids, >>>>>>> so I wonder if it would be possible to get this information in here >>>>>>> instead >>>>>>> to all the vlv with dsi... >>>>>>> >>>>>>> Or avoid the quirk "infra" and skip to all vlv with active dsi?! >>>>>>> >>>>>>> Jani? >>>>>>> Ville? >>>>>> >>>>>> We need to figure out why the panel doesn't start up again. >>>>> >>>>> Note it is the GOP which fails to light it up again. I think we turn >>>>> something >>>>> off, which after a power-on-reset is on, so the GOP expects it to be on. >>>> >>>> Hmm. Do any of the reboot=warm|cold|whatever knobs make a difference? >>>> Are there any fast vs. slow boot settings in the BIOS setup? >>> >>> Ok, so I
Re: [Intel-gfx] [PATCH resend 2/2] drm/i915/display: Make vlv_find_free_pps() skip pipes which are in use for non DP purposes
Hi, On 3/24/21 3:02 PM, Ville Syrjälä wrote: > On Tue, Mar 23, 2021 at 11:39:09AM +0100, Hans de Goede wrote: >> Hi, >> >> On 3/2/21 3:51 PM, Ville Syrjälä wrote: >>> On Tue, Mar 02, 2021 at 01:00:40PM +0100, Hans de Goede wrote: >>>> As explained by a long comment block, on VLV intel_setup_outputs() >>>> sometimes thinks there might be an eDP panel connected while there is none. >>>> In this case intel_setup_outputs() will call intel_dp_init() to check. >>>> >>>> In this scenario vlv_find_free_pps() ends up selecting pipe A for the pps, >>>> even though this might be in use for non DP purposes. When this is the case >>>> then the assert_pipe() in vlv_force_pll_on() will fail when called from >>>> vlv_power_sequencer_kick(). >>> >>> The idea is that you *can* select a PPS from a pipe used for a non-DP >>> port since those don't care about the PPS stuff. So this doesn't seem >>> correct. >> >> They may not care about the PPS stuff, but as the WARN / backtrace >> shows if the DPLL_VCO_ENABLE bit is not already set for the pipe, while >> the pipe is "otherwise" in use then vlv_force_pll_on() becomes unhappy >> triggering the WARN.DPLL_VCO_ENABLE bit is not >> >>> a) I would like to see the VBT for this machine >> >> https://fedorapeople.org/~jwrdegoede/voyo-winpad-a15-vbt >> >>> b) I wonder if the DSI PLL is sufficient for getting the PPS going? >> >> I have no idea, I just noticed the WARN / backtrace and this seemed >> like a reasonably way to deal with it. With that said I'm fine with fixing >> this a different way. >> >>> c) If we do need the normal DPLL is there any harm to DSI in enabling it? >> >> I would assume this increases power-consumption and DSI panels are almost >> always used in battery powered devices. > > This is just used while probing the panel, so power consumption is > not a concern. Sorry I misinterpreted what you wrote, I interpreted it as have the DSI code enable it to avoid this problem. I see now that that is now what you meant. >> Also this would impact all BYT/CHT devices, possible triggering unwanted >> side-effects. Where as the proposed fix below is much more narrowly targeted >> at the problem. It might not be the most pretty fix but AFAICT it has a low >> risk of causing regressions. > > It rather significantly changes the logic of the workaround, potentially > causing us to not find a free PPS at all. Eg. if you were to boot with > a VLV with pipe A -> eDP B + eDP C inactive + pipe B -> VGA then your > change would cause us to not find the free pipe B PPS for probing eDP C, > and in the end we'd get a WARN and fall back to pipe A PPS which would > clobber the actually in use pipe A PPS. I would welcome, and will happily test, another fix for this. ATM we have a WARN triggering on actual hardware (and not just in a hypothetical example) and I would like to see that WARN fixed. If you can come up with a better fix I would be happy to test. Regards, Hans ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
Re: [PATCH v2 00/10] drm: Support simple-framebuffer devices and firmware fbs
Hi, On 3/18/21 11:29 AM, Thomas Zimmermann wrote: > This patchset adds support for simple-framebuffer platform devices and > a handover mechanism for native drivers to take-over control of the > hardware. > > The new driver, called simpledrm, binds to a simple-frambuffer platform > device. The kernel's boot code creates such devices for firmware-provided > framebuffers, such as EFI-GOP or VESA. Typically the BIOS, UEFI or boot > loader sets up the framebuffers. Description via device tree is also an > option. > > Simpledrm is small enough to be linked into the kernel. The driver's main > purpose is to provide graphical output during the early phases of the boot > process, before the native DRM drivers are available. Native drivers are > typically loaded from an initrd ram disk. Occationally simpledrm can also > serve as interim solution on graphics hardware without native DRM driver. > > So far distributions rely on fbdev drivers, such as efifb, vesafb or > simplefb, for early-boot graphical output. However fbdev is deprecated and > the drivers do not provide DRM interfaces for modern userspace. > > Patches 1 and 2 prepare the DRM format helpers for simpledrm. > > Patches 3 and 4 add a hand-over mechanism. Simpledrm acquires it's > framebuffer's I/O-memory range and provides a callback function to be > removed by a native driver. The native driver will remove simpledrm before > taking over the hardware. The removal is integrated into existing helpers, > so drivers use it automatically. > > Patches 5 to 10 add the simpledrm driver. It's build on simple DRM helpers > and SHMEM. It supports 16-bit, 24-bit and 32-bit RGB framebuffers. During > pageflips, SHMEM buffers are copied into the framebuffer memory, similar > to cirrus or mgag200. The code in patches 8 and 9 handles clocks and > regulators. It's based on the simplefb drivers, but has been modified for > DRM. Thank you for your work on this, this is very interesting. > I've also been working on fastboot support (i.e., flicker-free booting). > This requires state-readout from simpledrm via generic interfaces, as > outlined in [1]. I do have some prototype code, but it will take a while > to get this ready. Simpledrm will then support it. > > I've tested simpledrm with x86 EFI and VESA framebuffers, which both work > reliably. The fbdev console and Weston work automatically. Xorg requires > manual configuration of the device. Xorgs current modesetting driver does > not work with both, platform and PCI device, for the same physical > hardware. Once configured, X11 works. I looked into X11, but couldn't see > an easy way of fixing the problem. With the push towards Wayland+Xwayland > I expect the problem to become a non-issue soon. Additional testing has > been reported at [2]. > > One cosmetical issue is that simpledrm's device file is card0 and the > native driver's device file is card1. After simpledrm has been kicked out, > only card1 is left. This does not seem to be a practical problem however. > > TODO/IDEAS: > > * provide deferred takeover I'm not sure what you mean with this ? Currently deferred-takeover is handled in the fbcon code. Current flickerfree boot works like this (assuming a single LCD panel in a laptop): 1. EFI/GOP sets up the framebuffer, draws a vendor logo 2. The bootloader runs in silent mode and does not touch anything gfx related 3. kernel boots, with a loglevel of 3 so only CRIT/EMERG messages are shown 2. efifb loads; and tells fbcon that a framebuffer is now available for it to "bind" to. Since CONFIG_FRAMEBUFFER_CONSOLE_DEFERRED_TAKEOVER=y fbcon defers taking over the console and leaves the dummy-console driver in place (unless there have already been kernel messages logged, which there shouldn't because loglevel=3) 3. i915 loads, reads out the hw state compares this to the preferred-mode for the panel which it would set, they match, nothing happens. i915 takes ownership of the scanout-buffer set up by the GOP, but leaves it in place. i915 also removes the efifb /dev/fb0 and installs its own /dev/fb0 fbdev compat device, fbcon is notified of this, but is still deferred and leaves the dummy console driver in place as console driver. 4. Plymouth loads, allocates a new scan-out buffer at the panel's preferred resolution, plymouth reads the vendor-logo through the BGRT ACPI interface and fills the scanout-buffer with the vendor-logo + a spinner. Then plymouth installs the new scanout-buffer on the crtc, this is done atomically during vsync, so the user sees no changes, other then the spinner appearing (note the active VT is now in graphical mode) 5. From here on not flickering is a userspace problem AFAICT this should work fine with simplekms too, unless it clears the screen to black when it binds. An addition to the above sequence, if at any time either the kernel or userspace prints a message to the console; and at that time a fbdev is registered then fbcon w
[PATCH 1/2] drm/i915/display/vlv_dsi: Do not skip panel_pwr_cycle_delay when disabling the panel
After the recently added commit fe0f1e3bfdfe ("drm/i915: Shut down displays gracefully on reboot"), the DSI panel on a Cherry Trail based Predia Basic tablet would no longer properly light up after reboot. I've managed to reproduce this without rebooting by doing: chvt 3; echo 1 > /sys/class/graphics/fb0/blank;\ echo 0 > /sys/class/graphics/fb0/blank Which rapidly turns the panel off and back on again. The vlv_dsi.c code uses an intel_dsi_msleep() helper for the various delays used for panel on/off, since starting with MIPI-sequences version >= 3 the delays are already included inside the MIPI-sequences. The problems exposed by the "Shut down displays gracefully on reboot" change, show that using this helper for the panel_pwr_cycle_delay is not the right thing to do. This has not been noticed until now because normally the panel never is cycled off and directly on again in quick succession. Change the msleep for the panel_pwr_cycle_delay to a normal msleep() call to avoid the panel staying black after a quick off + on cycle. Cc: Ville Syrjälä Fixes: fe0f1e3bfdfe ("drm/i915: Shut down displays gracefully on reboot") Signed-off-by: Hans de Goede --- drivers/gpu/drm/i915/display/vlv_dsi.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/display/vlv_dsi.c b/drivers/gpu/drm/i915/display/vlv_dsi.c index d5a3f69c5df3..38d5a1f3ded5 100644 --- a/drivers/gpu/drm/i915/display/vlv_dsi.c +++ b/drivers/gpu/drm/i915/display/vlv_dsi.c @@ -996,14 +996,14 @@ static void intel_dsi_post_disable(struct intel_atomic_state *state, * FIXME As we do with eDP, just make a note of the time here * and perform the wait before the next panel power on. */ - intel_dsi_msleep(intel_dsi, intel_dsi->panel_pwr_cycle_delay); + msleep(intel_dsi->panel_pwr_cycle_delay); } static void intel_dsi_shutdown(struct intel_encoder *encoder) { struct intel_dsi *intel_dsi = enc_to_intel_dsi(encoder); - intel_dsi_msleep(intel_dsi, intel_dsi->panel_pwr_cycle_delay); + msleep(intel_dsi->panel_pwr_cycle_delay); } static bool intel_dsi_get_hw_state(struct intel_encoder *encoder, -- 2.30.2 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH 2/2] drm/i915/display/vlv_dsi: Move panel_pwr_cycle_delay to next panel-on
Instead of sleeping panel_pwr_cycle_delay ms when turning the panel off, record the time it is turned off and if necessary wait any (remaining) time when the panel is turned on again. Also sleep the remaining time on shutdown, because on reboot the GOP will immediately turn on the panel again. Cc: Ville Syrjälä Signed-off-by: Hans de Goede --- drivers/gpu/drm/i915/display/intel_dsi.h | 1 + drivers/gpu/drm/i915/display/vlv_dsi.c | 25 ++-- 2 files changed, 20 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_dsi.h b/drivers/gpu/drm/i915/display/intel_dsi.h index 625f2f1ae061..50d6da0b2419 100644 --- a/drivers/gpu/drm/i915/display/intel_dsi.h +++ b/drivers/gpu/drm/i915/display/intel_dsi.h @@ -124,6 +124,7 @@ struct intel_dsi { u16 panel_on_delay; u16 panel_off_delay; u16 panel_pwr_cycle_delay; + ktime_t panel_power_off_time; }; struct intel_dsi_host { diff --git a/drivers/gpu/drm/i915/display/vlv_dsi.c b/drivers/gpu/drm/i915/display/vlv_dsi.c index 38d5a1f3ded5..3ede55cb3f43 100644 --- a/drivers/gpu/drm/i915/display/vlv_dsi.c +++ b/drivers/gpu/drm/i915/display/vlv_dsi.c @@ -717,6 +717,19 @@ static void intel_dsi_port_disable(struct intel_encoder *encoder) } } +static void intel_dsi_wait_panel_power_cycle(struct intel_dsi *intel_dsi) +{ + ktime_t panel_power_on_time; + s64 panel_power_off_duration; + + panel_power_on_time = ktime_get_boottime(); + panel_power_off_duration = ktime_ms_delta(panel_power_on_time, + intel_dsi->panel_power_off_time); + + if (panel_power_off_duration < (s64)intel_dsi->panel_pwr_cycle_delay) + msleep(intel_dsi->panel_pwr_cycle_delay - panel_power_off_duration); +} + static void intel_dsi_prepare(struct intel_encoder *intel_encoder, const struct intel_crtc_state *pipe_config); static void intel_dsi_unprepare(struct intel_encoder *encoder); @@ -778,6 +791,8 @@ static void intel_dsi_pre_enable(struct intel_atomic_state *state, drm_dbg_kms(&dev_priv->drm, "\n"); + intel_dsi_wait_panel_power_cycle(intel_dsi); + intel_set_cpu_fifo_underrun_reporting(dev_priv, pipe, true); /* @@ -992,18 +1007,14 @@ static void intel_dsi_post_disable(struct intel_atomic_state *state, intel_dsi_msleep(intel_dsi, intel_dsi->panel_off_delay); intel_dsi_vbt_exec_sequence(intel_dsi, MIPI_SEQ_POWER_OFF); - /* -* FIXME As we do with eDP, just make a note of the time here -* and perform the wait before the next panel power on. -*/ - msleep(intel_dsi->panel_pwr_cycle_delay); + intel_dsi->panel_power_off_time = ktime_get_boottime(); } static void intel_dsi_shutdown(struct intel_encoder *encoder) { struct intel_dsi *intel_dsi = enc_to_intel_dsi(encoder); - msleep(intel_dsi->panel_pwr_cycle_delay); + intel_dsi_wait_panel_power_cycle(intel_dsi); } static bool intel_dsi_get_hw_state(struct intel_encoder *encoder, @@ -1884,6 +1895,8 @@ void vlv_dsi_init(struct drm_i915_private *dev_priv) else intel_encoder->pipe_mask = BIT(PIPE_B); + intel_dsi->panel_power_off_time = ktime_get_boottime(); + if (dev_priv->vbt.dsi.config->dual_link) intel_dsi->ports = BIT(PORT_A) | BIT(PORT_C); else -- 2.30.2 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
Re: [PATCH v2 00/10] drm: Support simple-framebuffer devices and firmware fbs
Hi, On 3/29/21 2:31 PM, Thomas Zimmermann wrote: > Hi > > Am 25.03.21 um 12:29 schrieb Hans de Goede: >> Hi, >> >> On 3/18/21 11:29 AM, Thomas Zimmermann wrote: >>> This patchset adds support for simple-framebuffer platform devices and >>> a handover mechanism for native drivers to take-over control of the >>> hardware. >>> >>> The new driver, called simpledrm, binds to a simple-frambuffer platform >>> device. The kernel's boot code creates such devices for firmware-provided >>> framebuffers, such as EFI-GOP or VESA. Typically the BIOS, UEFI or boot >>> loader sets up the framebuffers. Description via device tree is also an >>> option. >>> >>> Simpledrm is small enough to be linked into the kernel. The driver's main >>> purpose is to provide graphical output during the early phases of the boot >>> process, before the native DRM drivers are available. Native drivers are >>> typically loaded from an initrd ram disk. Occationally simpledrm can also >>> serve as interim solution on graphics hardware without native DRM driver. >>> >>> So far distributions rely on fbdev drivers, such as efifb, vesafb or >>> simplefb, for early-boot graphical output. However fbdev is deprecated and >>> the drivers do not provide DRM interfaces for modern userspace. >>> >>> Patches 1 and 2 prepare the DRM format helpers for simpledrm. >>> >>> Patches 3 and 4 add a hand-over mechanism. Simpledrm acquires it's >>> framebuffer's I/O-memory range and provides a callback function to be >>> removed by a native driver. The native driver will remove simpledrm before >>> taking over the hardware. The removal is integrated into existing helpers, >>> so drivers use it automatically. >>> >>> Patches 5 to 10 add the simpledrm driver. It's build on simple DRM helpers >>> and SHMEM. It supports 16-bit, 24-bit and 32-bit RGB framebuffers. During >>> pageflips, SHMEM buffers are copied into the framebuffer memory, similar >>> to cirrus or mgag200. The code in patches 8 and 9 handles clocks and >>> regulators. It's based on the simplefb drivers, but has been modified for >>> DRM. >> >> Thank you for your work on this, this is very interesting. >> >>> I've also been working on fastboot support (i.e., flicker-free booting). >>> This requires state-readout from simpledrm via generic interfaces, as >>> outlined in [1]. I do have some prototype code, but it will take a while >>> to get this ready. Simpledrm will then support it. >>> >>> I've tested simpledrm with x86 EFI and VESA framebuffers, which both work >>> reliably. The fbdev console and Weston work automatically. Xorg requires >>> manual configuration of the device. Xorgs current modesetting driver does >>> not work with both, platform and PCI device, for the same physical >>> hardware. Once configured, X11 works. I looked into X11, but couldn't see >>> an easy way of fixing the problem. With the push towards Wayland+Xwayland >>> I expect the problem to become a non-issue soon. Additional testing has >>> been reported at [2]. >>> >>> One cosmetical issue is that simpledrm's device file is card0 and the >>> native driver's device file is card1. After simpledrm has been kicked out, >>> only card1 is left. This does not seem to be a practical problem however. >>> >>> TODO/IDEAS: >>> >>> * provide deferred takeover >> >> I'm not sure what you mean with this ? Currently deferred-takeover is >> handled in the fbcon code. Current flickerfree boot works like this >> (assuming a single LCD panel in a laptop): >> >> 1. EFI/GOP sets up the framebuffer, draws a vendor logo >> 2. The bootloader runs in silent mode and does not touch anything gfx related >> 3. kernel boots, with a loglevel of 3 so only CRIT/EMERG messages are shown >> 2. efifb loads; and tells fbcon that a framebuffer is now available for it >> to "bind" >> to. Since CONFIG_FRAMEBUFFER_CONSOLE_DEFERRED_TAKEOVER=y fbcon defers >> taking over >> the console and leaves the dummy-console driver in place (unless there >> have already >> been kernel messages logged, which there shouldn't because loglevel=3) >> 3. i915 loads, reads out the hw state compares this to the preferred-mode >> for the >> panel which it would set, they match, nothing happens. i915 takes >> ownership >> of the scanout-b
Re: [PATCH v2 00/10] drm: Support simple-framebuffer devices and firmware fbs
Hi, On 3/30/21 9:09 AM, Thomas Zimmermann wrote: > Hi > > Am 29.03.21 um 16:50 schrieb Hans de Goede: >> Hi, >> >> On 3/29/21 2:31 PM, Thomas Zimmermann wrote: >>> Hi >>> >>> Am 25.03.21 um 12:29 schrieb Hans de Goede: >>>> Hi, >>>> >>>> On 3/18/21 11:29 AM, Thomas Zimmermann wrote: >>>>> This patchset adds support for simple-framebuffer platform devices and >>>>> a handover mechanism for native drivers to take-over control of the >>>>> hardware. >>>>> >>>>> The new driver, called simpledrm, binds to a simple-frambuffer platform >>>>> device. The kernel's boot code creates such devices for firmware-provided >>>>> framebuffers, such as EFI-GOP or VESA. Typically the BIOS, UEFI or boot >>>>> loader sets up the framebuffers. Description via device tree is also an >>>>> option. >>>>> >>>>> Simpledrm is small enough to be linked into the kernel. The driver's main >>>>> purpose is to provide graphical output during the early phases of the boot >>>>> process, before the native DRM drivers are available. Native drivers are >>>>> typically loaded from an initrd ram disk. Occationally simpledrm can also >>>>> serve as interim solution on graphics hardware without native DRM driver. >>>>> >>>>> So far distributions rely on fbdev drivers, such as efifb, vesafb or >>>>> simplefb, for early-boot graphical output. However fbdev is deprecated and >>>>> the drivers do not provide DRM interfaces for modern userspace. >>>>> >>>>> Patches 1 and 2 prepare the DRM format helpers for simpledrm. >>>>> >>>>> Patches 3 and 4 add a hand-over mechanism. Simpledrm acquires it's >>>>> framebuffer's I/O-memory range and provides a callback function to be >>>>> removed by a native driver. The native driver will remove simpledrm before >>>>> taking over the hardware. The removal is integrated into existing helpers, >>>>> so drivers use it automatically. >>>>> >>>>> Patches 5 to 10 add the simpledrm driver. It's build on simple DRM helpers >>>>> and SHMEM. It supports 16-bit, 24-bit and 32-bit RGB framebuffers. During >>>>> pageflips, SHMEM buffers are copied into the framebuffer memory, similar >>>>> to cirrus or mgag200. The code in patches 8 and 9 handles clocks and >>>>> regulators. It's based on the simplefb drivers, but has been modified for >>>>> DRM. >>>> >>>> Thank you for your work on this, this is very interesting. >>>> >>>>> I've also been working on fastboot support (i.e., flicker-free booting). >>>>> This requires state-readout from simpledrm via generic interfaces, as >>>>> outlined in [1]. I do have some prototype code, but it will take a while >>>>> to get this ready. Simpledrm will then support it. >>>>> >>>>> I've tested simpledrm with x86 EFI and VESA framebuffers, which both work >>>>> reliably. The fbdev console and Weston work automatically. Xorg requires >>>>> manual configuration of the device. Xorgs current modesetting driver does >>>>> not work with both, platform and PCI device, for the same physical >>>>> hardware. Once configured, X11 works. I looked into X11, but couldn't see >>>>> an easy way of fixing the problem. With the push towards Wayland+Xwayland >>>>> I expect the problem to become a non-issue soon. Additional testing has >>>>> been reported at [2]. >>>>> >>>>> One cosmetical issue is that simpledrm's device file is card0 and the >>>>> native driver's device file is card1. After simpledrm has been kicked out, >>>>> only card1 is left. This does not seem to be a practical problem however. >>>>> >>>>> TODO/IDEAS: >>>>> >>>>> * provide deferred takeover >>>> >>>> I'm not sure what you mean with this ? Currently deferred-takeover is >>>> handled in the fbcon code. Current flickerfree boot works like this >>>> (assuming a single LCD panel in a laptop): >>>> >>>> 1. EFI/GOP sets up the framebuffer, draws a vendor logo >>>> 2. The bootloader runs in silent mode and does not touch anything gfx >>>> related >
Re: [PATCH 11/11] [RFC] drm/i915/dp: fix array overflow warning
Hi, On 3/22/21 5:02 PM, Arnd Bergmann wrote: > From: Arnd Bergmann > > gcc-11 warns that intel_dp_check_mst_status() has a local array of > fourteen bytes and passes the last four bytes into a function that > expects a six-byte array: > > drivers/gpu/drm/i915/display/intel_dp.c: In function > ‘intel_dp_check_mst_status’: > drivers/gpu/drm/i915/display/intel_dp.c:4556:22: error: > ‘drm_dp_channel_eq_ok’ reading 6 bytes from a region of size 4 > [-Werror=stringop-overread] > 4556 | !drm_dp_channel_eq_ok(&esi[10], > intel_dp->lane_count)) { > | > ^~~~ > drivers/gpu/drm/i915/display/intel_dp.c:4556:22: note: referencing argument 1 > of type ‘const u8 *’ {aka ‘const unsigned char *’} > In file included from drivers/gpu/drm/i915/display/intel_dp.c:38: > include/drm/drm_dp_helper.h:1459:6: note: in a call to function > ‘drm_dp_channel_eq_ok’ > 1459 | bool drm_dp_channel_eq_ok(const u8 link_status[DP_LINK_STATUS_SIZE], > | ^~~~ > > Clearly something is wrong here, but I can't quite figure out what. > Changing the array size to 16 bytes avoids the warning, but is > probably the wrong solution here. The drm displayport-helpers indeed expect a 6 bytes buffer, but they usually only consume 4 bytes. I don't think that changing the DP_DPRX_ESI_LEN is a good fix here, since it is used in multiple places, but the esi array already gets zero-ed out by its initializer, so we can just pass 2 extra 0 bytes to give drm_dp_channel_eq_ok() call the 6 byte buffer its prototype specifies by doing this: diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c index 897711d9d7d3..147962d4ad06 100644 --- a/drivers/gpu/drm/i915/display/intel_dp.c +++ b/drivers/gpu/drm/i915/display/intel_dp.c @@ -4538,7 +4538,11 @@ intel_dp_check_mst_status(struct intel_dp *intel_dp) drm_WARN_ON_ONCE(&i915->drm, intel_dp->active_mst_links < 0); for (;;) { - u8 esi[DP_DPRX_ESI_LEN] = {}; + /* +* drm_dp_channel_eq_ok() expects a 6 byte large buffer, but +* the ESI info only contains 4 bytes, pass 2 extra 0 bytes. +*/ + u8 esi[DP_DPRX_ESI_LEN + 2] = {}; bool handled; int retry; So i915 devs, would such a fix be acceptable ? Regards, Hans > > Signed-off-by: Arnd Bergmann > --- > drivers/gpu/drm/i915/display/intel_dp.c | 2 +- > 1 file changed, 1 insertion(+), 1 deletion(-) > > diff --git a/drivers/gpu/drm/i915/display/intel_dp.c > b/drivers/gpu/drm/i915/display/intel_dp.c > index 8c12d5375607..830e2515f119 100644 > --- a/drivers/gpu/drm/i915/display/intel_dp.c > +++ b/drivers/gpu/drm/i915/display/intel_dp.c > @@ -65,7 +65,7 @@ > #include "intel_vdsc.h" > #include "intel_vrr.h" > > -#define DP_DPRX_ESI_LEN 14 > +#define DP_DPRX_ESI_LEN 16 > > /* DP DSC throughput values used for slice count calculations KPixels/s */ > #define DP_DSC_PEAK_PIXEL_RATE 272 > ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
Re: [PATCH 1/2] drm/i915/display/vlv_dsi: Do not skip panel_pwr_cycle_delay when disabling the panel
Hi, On 3/25/21 12:48 PM, Hans de Goede wrote: > After the recently added commit fe0f1e3bfdfe ("drm/i915: Shut down > displays gracefully on reboot"), the DSI panel on a Cherry Trail based > Predia Basic tablet would no longer properly light up after reboot. > > I've managed to reproduce this without rebooting by doing: > chvt 3; echo 1 > /sys/class/graphics/fb0/blank;\ > echo 0 > /sys/class/graphics/fb0/blank > > Which rapidly turns the panel off and back on again. > > The vlv_dsi.c code uses an intel_dsi_msleep() helper for the various delays > used for panel on/off, since starting with MIPI-sequences version >= 3 the > delays are already included inside the MIPI-sequences. > > The problems exposed by the "Shut down displays gracefully on reboot" > change, show that using this helper for the panel_pwr_cycle_delay is > not the right thing to do. This has not been noticed until now because > normally the panel never is cycled off and directly on again in quick > succession. > > Change the msleep for the panel_pwr_cycle_delay to a normal msleep() > call to avoid the panel staying black after a quick off + on cycle. > > Cc: Ville Syrjälä > Fixes: fe0f1e3bfdfe ("drm/i915: Shut down displays gracefully on reboot") > Signed-off-by: Hans de Goede Ping? Ville AFAICT this is ready for merging, can you review this please so that I can push it to drm-intel-next ? Regards, Hans > --- > drivers/gpu/drm/i915/display/vlv_dsi.c | 4 ++-- > 1 file changed, 2 insertions(+), 2 deletions(-) > > diff --git a/drivers/gpu/drm/i915/display/vlv_dsi.c > b/drivers/gpu/drm/i915/display/vlv_dsi.c > index d5a3f69c5df3..38d5a1f3ded5 100644 > --- a/drivers/gpu/drm/i915/display/vlv_dsi.c > +++ b/drivers/gpu/drm/i915/display/vlv_dsi.c > @@ -996,14 +996,14 @@ static void intel_dsi_post_disable(struct > intel_atomic_state *state, >* FIXME As we do with eDP, just make a note of the time here >* and perform the wait before the next panel power on. >*/ > - intel_dsi_msleep(intel_dsi, intel_dsi->panel_pwr_cycle_delay); > + msleep(intel_dsi->panel_pwr_cycle_delay); > } > > static void intel_dsi_shutdown(struct intel_encoder *encoder) > { > struct intel_dsi *intel_dsi = enc_to_intel_dsi(encoder); > > - intel_dsi_msleep(intel_dsi, intel_dsi->panel_pwr_cycle_delay); > + msleep(intel_dsi->panel_pwr_cycle_delay); > } > > static bool intel_dsi_get_hw_state(struct intel_encoder *encoder, > ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
Re: [PATCH] drm/ttm: stop using GFP_TRANSHUGE_LIGHT
Hi, On 1/15/21 1:14 PM, Christian König wrote: > Hans do you have any more comments or a tested-by? Sorry, I've been busy chasing after another 5.11 regression, no comments, also no tested-by, but I do fully expect this to solve the issue. > Otherwise I push it to drm-misc-fixes today. That sounds good to me. Regards, Hans > > Thanks, > Christian. > > Am 13.01.21 um 14:13 schrieb Christian König: >> The only flag we really need is __GFP_NOMEMALLOC, highmem depends on >> dma32 and moveable/compound should never be set in the first place. >> >> Signed-off-by: Christian König >> --- >> drivers/gpu/drm/ttm/ttm_pool.c | 11 ++- >> 1 file changed, 6 insertions(+), 5 deletions(-) >> >> diff --git a/drivers/gpu/drm/ttm/ttm_pool.c b/drivers/gpu/drm/ttm/ttm_pool.c >> index 8cd776adc592..11e0313db0ea 100644 >> --- a/drivers/gpu/drm/ttm/ttm_pool.c >> +++ b/drivers/gpu/drm/ttm/ttm_pool.c >> @@ -79,12 +79,13 @@ static struct page *ttm_pool_alloc_page(struct ttm_pool >> *pool, gfp_t gfp_flags, >> struct page *p; >> void *vaddr; >> - if (order) { >> - gfp_flags |= GFP_TRANSHUGE_LIGHT | __GFP_NORETRY | >> + /* Don't set the __GFP_COMP flag for higher order allocations. >> + * Mapping pages directly into an userspace process and calling >> + * put_page() on a TTM allocated page is illegal. >> + */ >> + if (order) >> + gfp_flags |= __GFP_NOMEMALLOC | __GFP_NORETRY | >> __GFP_KSWAPD_RECLAIM; >> - gfp_flags &= ~__GFP_MOVABLE; >> - gfp_flags &= ~__GFP_COMP; >> - } >> if (!pool->use_dma_alloc) { >> p = alloc_pages(gfp_flags, order); > ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
Re: [PATCH] video: fbdev: simplefb: Fix info message during probe
Hi, On 1/7/21 6:04 PM, Daniel Vetter wrote: > Hi Hans, > > On Tue, Dec 29, 2020 at 02:02:30PM +0100, Hans de Goede wrote: >> Hi, >> >> On 12/28/20 7:39 PM, Peter Robinson wrote: >>> The info message was showing the mapped address for the framebuffer. To >>> avoid >>> security problems, all virtual addresses are converted to __ptrval__, so >>> the message has pointless information: >>> >>> simple-framebuffer 3ea9b000.framebuffer: framebuffer at 0x3ea9b000, >>> 0x12c000 bytes, mapped to 0x(ptrval) >>> >>> Drop the extraneous bits to clean up the message: >>> >>> simple-framebuffer 3ea9b000.framebuffer: framebuffer at 0x3ea9b000, >>> 0x12c000 bytes >>> >>> Signed-off-by: Peter Robinson >> >> Thanks, patch looks good to me: >> >> Reviewed-by: Hans de Goede > > Since you have commit rights for drm-misc I'm assuming you're also going > to push this one? I knew there was some discussion about using drm-misc for drivers/video/fbdev stuff but I missed that it was decided to go ahead with that. Good to know that this is handled through drm-misc now. I've pushed this patch to drm-misc-next. Regards, Hans >>> --- >>> drivers/video/fbdev/simplefb.c | 5 ++--- >>> 1 file changed, 2 insertions(+), 3 deletions(-) >>> >>> diff --git a/drivers/video/fbdev/simplefb.c b/drivers/video/fbdev/simplefb.c >>> index 533a047d07a2..62f0ded70681 100644 >>> --- a/drivers/video/fbdev/simplefb.c >>> +++ b/drivers/video/fbdev/simplefb.c >>> @@ -477,9 +477,8 @@ static int simplefb_probe(struct platform_device *pdev) >>> simplefb_clocks_enable(par, pdev); >>> simplefb_regulators_enable(par, pdev); >>> >>> - dev_info(&pdev->dev, "framebuffer at 0x%lx, 0x%x bytes, mapped to >>> 0x%p\n", >>> -info->fix.smem_start, info->fix.smem_len, >>> -info->screen_base); >>> + dev_info(&pdev->dev, "framebuffer at 0x%lx, 0x%x bytes\n", >>> +info->fix.smem_start, info->fix.smem_len); >>> dev_info(&pdev->dev, "format=%s, mode=%dx%dx%d, linelength=%d\n", >>> params.format->name, >>> info->var.xres, info->var.yres, >>> >> >> ___ >> dri-devel mailing list >> dri-devel@lists.freedesktop.org >> https://lists.freedesktop.org/mailman/listinfo/dri-devel > ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
Re: [PATCH] drm: Added orientation quirk for OneGX1 Pro
Hi, On 1/20/21 9:56 PM, Jared Baldridge wrote: > The OneGX1 Pro has a fairly unique combination of generic strings, > but we additionally match on the BIOS date just to be safe. > > Signed-off-by: Jared Baldridge Thanks, patch looks good to me: Reviewed-by: Hans de Goede I will push this to drm-misc-next right away. Regards, Hans > --- > drivers/gpu/drm/drm_panel_orientation_quirks.c | 14 ++ > 1 file changed, 14 insertions(+) > > diff --git a/drivers/gpu/drm/drm_panel_orientation_quirks.c > b/drivers/gpu/drm/drm_panel_orientation_quirks.c > index 58f5dc2f6dd5..f6bdec7fa925 100644 > --- a/drivers/gpu/drm/drm_panel_orientation_quirks.c > +++ b/drivers/gpu/drm/drm_panel_orientation_quirks.c > @@ -84,6 +84,13 @@ static const struct drm_dmi_panel_orientation_data > itworks_tw891 = { > .orientation = DRM_MODE_PANEL_ORIENTATION_RIGHT_UP, > }; > > +static const struct drm_dmi_panel_orientation_data onegx1_pro = { > + .width = 1200, > + .height = 1920, > + .bios_dates = (const char * const []){ "12/17/2020", NULL }, > + .orientation = DRM_MODE_PANEL_ORIENTATION_RIGHT_UP, > +}; > + > static const struct drm_dmi_panel_orientation_data lcd720x1280_rightside_up > = { > .width = 720, > .height = 1280, > @@ -211,6 +218,13 @@ static const struct dmi_system_id orientation_data[] = { > DMI_EXACT_MATCH(DMI_PRODUCT_VERSION, "Lenovo ideapad > D330-10IGM"), > }, > .driver_data = (void *)&lcd1200x1920_rightside_up, > + }, {/* OneGX1 Pro */ > + .matches = { > + DMI_EXACT_MATCH(DMI_SYS_VENDOR, "SYSTEM_MANUFACTURER"), > + DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "SYSTEM_PRODUCT_NAME"), > + DMI_EXACT_MATCH(DMI_PRODUCT_VERSION, "Default string"), > + }, > + .driver_data = (void *)&onegx1_pro, > }, {/* VIOS LTH17 */ > .matches = { > DMI_EXACT_MATCH(DMI_SYS_VENDOR, "VIOS"), > ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
Re: [PATCH] drm: Added orientation quirk for OneGX1 Pro
Hi, On 1/20/21 10:18 PM, Hans de Goede wrote: > Hi, > > On 1/20/21 9:56 PM, Jared Baldridge wrote: >> The OneGX1 Pro has a fairly unique combination of generic strings, >> but we additionally match on the BIOS date just to be safe. >> >> Signed-off-by: Jared Baldridge > > Thanks, patch looks good to me: > > Reviewed-by: Hans de Goede > > I will push this to drm-misc-next right away. So it looks like your mail client ate all the tabs replacing them with spaces (using tab stops every 8 chars). I've manually fixed this up this time. Next time please use git send-email and do NOT invoke an editor to change e.g. the subject, instead use the command line options to set a patch subject prefix. Regards, Hans >> --- >> drivers/gpu/drm/drm_panel_orientation_quirks.c | 14 ++ >> 1 file changed, 14 insertions(+) >> >> diff --git a/drivers/gpu/drm/drm_panel_orientation_quirks.c >> b/drivers/gpu/drm/drm_panel_orientation_quirks.c >> index 58f5dc2f6dd5..f6bdec7fa925 100644 >> --- a/drivers/gpu/drm/drm_panel_orientation_quirks.c >> +++ b/drivers/gpu/drm/drm_panel_orientation_quirks.c >> @@ -84,6 +84,13 @@ static const struct drm_dmi_panel_orientation_data >> itworks_tw891 = { >> .orientation = DRM_MODE_PANEL_ORIENTATION_RIGHT_UP, >> }; >> >> +static const struct drm_dmi_panel_orientation_data onegx1_pro = { >> + .width = 1200, >> + .height = 1920, >> + .bios_dates = (const char * const []){ "12/17/2020", NULL }, >> + .orientation = DRM_MODE_PANEL_ORIENTATION_RIGHT_UP, >> +}; >> + >> static const struct drm_dmi_panel_orientation_data lcd720x1280_rightside_up >> = { >> .width = 720, >> .height = 1280, >> @@ -211,6 +218,13 @@ static const struct dmi_system_id orientation_data[] = { >> DMI_EXACT_MATCH(DMI_PRODUCT_VERSION, "Lenovo ideapad >> D330-10IGM"), >> }, >> .driver_data = (void *)&lcd1200x1920_rightside_up, >> + }, {/* OneGX1 Pro */ >> + .matches = { >> + DMI_EXACT_MATCH(DMI_SYS_VENDOR, "SYSTEM_MANUFACTURER"), >> + DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "SYSTEM_PRODUCT_NAME"), >> + DMI_EXACT_MATCH(DMI_PRODUCT_VERSION, "Default string"), >> + }, >> + .driver_data = (void *)&onegx1_pro, >> }, {/* VIOS LTH17 */ >> .matches = { >> DMI_EXACT_MATCH(DMI_SYS_VENDOR, "VIOS"), >> ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
Re: [GIT PULL] ib-drm-gpio-pdx86-rtc-wdt-v5.12-1
Hi, On 1/26/21 1:38 PM, Andy Shevchenko wrote: > Hi guys, > > This is first part of Intel MID outdated platforms removal. It's collected > into > immutable branch with a given tag, please pull to yours subsystems. > > (All changes are tagged by the respective maintainers) > > Thanks, > > With Best Regards, > Andy Shevchenko > > The following changes since commit 5c8fe583cce542aa0b84adc939ce85293de36e5e: > > Linux 5.11-rc1 (2020-12-27 15:30:22 -0800) > > are available in the Git repository at: > > git://git.infradead.org/linux-platform-drivers-x86.git > tags/ib-drm-gpio-pdx86-rtc-wdt-v5.12-1 > > for you to fetch changes up to a507e5d90f3d6846a02d9c2c79e6f6395982db92: > > platform/x86: intel_scu_wdt: Get rid of custom x86 model comparison > (2021-01-25 20:05:32 +0200) > > > ib-drm-gpio-pdx86-rtc-wdt for v5.12-1 > > First part of Intel MID outdated platforms removal. > > The following is an automated git shortlog grouped by driver: > > drm/gma500: > - Get rid of duplicate NULL checks > - Convert to use new SCU IPC API > > gpio: > - msic: Remove driver for deprecated platform > - intel-mid: Remove driver for deprecated platform > > intel_mid_powerbtn: > - Remove driver for deprecated platform > > intel_mid_thermal: > - Remove driver for deprecated platform > > intel_scu_wdt: > - Get rid of custom x86 model comparison > - Drop SCU notification > - Move driver from arch/x86 > > rtc: > - mrst: Remove driver for deprecated platform > > watchdog: > - intel-mid_wdt: Postpone IRQ handler registration till SCU is ready > - intel_scu_watchdog: Remove driver for deprecated platform > > > Andy Shevchenko (12): > drm/gma500: Convert to use new SCU IPC API > drm/gma500: Get rid of duplicate NULL checks > gpio: intel-mid: Remove driver for deprecated platform > gpio: msic: Remove driver for deprecated platform > platform/x86: intel_mid_thermal: Remove driver for deprecated platform > platform/x86: intel_mid_powerbtn: Remove driver for deprecated platform Erm, I already have this 2 in platform-drivers-x86/for-next since you said that these 2 could be merged independently. Anyways I just did a test-merge and there is no conflict, so everything is ok. >From my pov this looks good and I plan to merge this into >platform-drivers-x86/for-next before the merge-window. I'm going to hold off on doing that for a bit for now in case one of the other subsys maintainers has any objections. Regards, Hans > rtc: mrst: Remove driver for deprecated platform > watchdog: intel_scu_watchdog: Remove driver for deprecated platform > watchdog: intel-mid_wdt: Postpone IRQ handler registration till SCU is > ready > platform/x86: intel_scu_wdt: Move driver from arch/x86 > platform/x86: intel_scu_wdt: Drop SCU notification > platform/x86: intel_scu_wdt: Get rid of custom x86 model comparison > > MAINTAINERS| 2 - > arch/x86/platform/intel-mid/device_libs/Makefile | 1 - > drivers/gpio/Kconfig | 14 - > drivers/gpio/Makefile | 1 - > drivers/gpio/TODO | 2 +- > drivers/gpio/gpio-intel-mid.c | 414 --- > drivers/gpio/gpio-msic.c | 314 > drivers/gpu/drm/gma500/Kconfig | 1 + > drivers/gpu/drm/gma500/mdfld_device.c | 2 - > drivers/gpu/drm/gma500/mdfld_dsi_output.c | 2 - > drivers/gpu/drm/gma500/mdfld_output.c | 8 +- > drivers/gpu/drm/gma500/oaktrail_device.c | 3 - > drivers/gpu/drm/gma500/psb_drv.h | 3 + > drivers/gpu/drm/gma500/tc35876x-dsi-lvds.c | 30 +- > drivers/platform/x86/Kconfig | 23 +- > drivers/platform/x86/Makefile | 3 +- > drivers/platform/x86/intel_mid_powerbtn.c | 233 - > drivers/platform/x86/intel_mid_thermal.c | 560 > - > .../platform/x86/intel_scu_wdt.c | 41 +- > drivers/rtc/Kconfig| 12 - > drivers/rtc/Makefile | 1 - > drivers/rtc/rtc-mrst.c | 521 --- > drivers/watchdog/Kconfig | 9 - > drivers/watchdog/Makefile | 1 - > drivers/watchdog/intel-mid_wdt.c | 8 +- > drivers/watchdog/intel_scu_watchdog.c | 533 > drivers/watchdog/intel_scu_watchdog.h | 50 -- > 27 files changed, 54 insertions(+), 2738 deletions(-) > delete mode 100644 drivers/gpio/gpio-intel-mid.c > delete mode 100644 drivers/gpio/gpio-msi
Re: [GIT PULL] ib-drm-gpio-pdx86-rtc-wdt-v5.12-1
Hi, On 1/26/21 6:14 PM, Andy Shevchenko wrote: > On Tue, Jan 26, 2021 at 6:55 PM Patrik Jakobsson > wrote: >> On Tue, Jan 26, 2021 at 4:51 PM Andy Shevchenko >> wrote: >>> >>> On Tue, Jan 26, 2021 at 5:25 PM Patrik Jakobsson >>> wrote: On Tue, Jan 26, 2021 at 1:37 PM Andy Shevchenko wrote: > > Hi guys, > > This is first part of Intel MID outdated platforms removal. It's > collected into > immutable branch with a given tag, please pull to yours subsystems. Hi Andy, Do you plan on eventually removing X86_INTEL_MID completely? If so, then I should probably start looking at removing the corresponding parts in GMA500. >>> >>> Nope. It is related to only Medfield / Clovertrail platforms. >>> >>> There are other (MID) platforms that may / might utilize this driver >>> in the future. >> >> Right, there's still Oaktrail / Moorestown with hardware in the wild. > > Actually Moorestown had to be removed a few years ago (kernel won't > boot on them anyway from that date when Alan removed support under > arch/x86 for it). > > I'm talking about Merrifield and Moorefield that can utilize it and > also some other platforms that are not SFI based (Cedar something... > IIRC). Yes at least there are some 64 bit capable SoCs with GMA500 which were used in NAS like devices. These NAS-es actually have a VGA output (and maybe also DVI?) which is attached to the GMA500. I know people are running Fedora on these, so we should at least keep these supported. Regards, Hans ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
Re: [GIT PULL] ib-drm-gpio-pdx86-rtc-wdt-v5.12-1
Hi, On 1/26/21 9:54 PM, Andy Shevchenko wrote: > On Tue, Jan 26, 2021 at 8:33 PM Hans de Goede wrote: >> On 1/26/21 6:14 PM, Andy Shevchenko wrote: >>> On Tue, Jan 26, 2021 at 6:55 PM Patrik Jakobsson >>> wrote: >>>> On Tue, Jan 26, 2021 at 4:51 PM Andy Shevchenko >>>> wrote: >>>>> On Tue, Jan 26, 2021 at 5:25 PM Patrik Jakobsson >>>>> wrote: >>>>>> On Tue, Jan 26, 2021 at 1:37 PM Andy Shevchenko >>>>>> wrote: >>>>>>> >>>>>>> Hi guys, >>>>>>> >>>>>>> This is first part of Intel MID outdated platforms removal. It's >>>>>>> collected into >>>>>>> immutable branch with a given tag, please pull to yours subsystems. >>>>>> >>>>>> Hi Andy, >>>>>> Do you plan on eventually removing X86_INTEL_MID completely? If so, >>>>>> then I should probably start looking at removing the corresponding >>>>>> parts in GMA500. >>>>> >>>>> Nope. It is related to only Medfield / Clovertrail platforms. >>>>> >>>>> There are other (MID) platforms that may / might utilize this driver >>>>> in the future. >>>> >>>> Right, there's still Oaktrail / Moorestown with hardware in the wild. >>> >>> Actually Moorestown had to be removed a few years ago (kernel won't >>> boot on them anyway from that date when Alan removed support under >>> arch/x86 for it). >>> >>> I'm talking about Merrifield and Moorefield that can utilize it and >>> also some other platforms that are not SFI based (Cedar something... >>> IIRC). >> >> Yes at least there are some 64 bit capable SoCs with GMA500 which were >> used in NAS like devices. These NAS-es actually have a VGA output >> (and maybe also DVI?) which is attached to the GMA500. > > Since you are talking about 64-bit, definitely they are *not* > Moorestown, Medfield, Clovertrail since the mentioned never were > 64-bit. But it would be nice to see the CPU model number to be sure. My info on this comes from this bugreport: https://bugzilla.redhat.com/show_bug.cgi?id=1665766 And the machine that bugreport is about is a "Thecus N5550 NAS box (Intel Atom D2550/Cedarview platform)" Regards, Hans ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH 1/2] drm/i915/display: Add a intel_pipe_is_enabled() helper
Factor the code to check if a pipe is currently enabled out of assert_pipe() and put it in a new intel_pipe_is_enabled() helper, so that it can be re-used without copy-pasting it. Signed-off-by: Hans de Goede --- drivers/gpu/drm/i915/display/intel_display.c | 20 ++-- drivers/gpu/drm/i915/display/intel_display.h | 2 ++ 2 files changed, 16 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index 24520f062ff9..f83caceb901b 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -1263,17 +1263,13 @@ void assert_panel_unlocked(struct drm_i915_private *dev_priv, enum pipe pipe) pipe_name(pipe)); } -void assert_pipe(struct drm_i915_private *dev_priv, -enum transcoder cpu_transcoder, bool state) +bool intel_pipe_is_enabled(struct drm_i915_private *dev_priv, + enum transcoder cpu_transcoder) { bool cur_state; enum intel_display_power_domain power_domain; intel_wakeref_t wakeref; - /* we keep both pipes enabled on 830 */ - if (IS_I830(dev_priv)) - state = true; - power_domain = POWER_DOMAIN_TRANSCODER(cpu_transcoder); wakeref = intel_display_power_get_if_enabled(dev_priv, power_domain); if (wakeref) { @@ -1285,6 +1281,18 @@ void assert_pipe(struct drm_i915_private *dev_priv, cur_state = false; } + return cur_state; +} + +void assert_pipe(struct drm_i915_private *dev_priv, +enum transcoder cpu_transcoder, bool state) +{ + bool cur_state = intel_pipe_is_enabled(dev_priv, cpu_transcoder); + + /* we keep both pipes enabled on 830 */ + if (IS_I830(dev_priv)) + state = true; + I915_STATE_WARN(cur_state != state, "transcoder %s assertion failure (expected %s, current %s)\n", transcoder_name(cpu_transcoder), diff --git a/drivers/gpu/drm/i915/display/intel_display.h b/drivers/gpu/drm/i915/display/intel_display.h index 5e0d42d82c11..be28d9570038 100644 --- a/drivers/gpu/drm/i915/display/intel_display.h +++ b/drivers/gpu/drm/i915/display/intel_display.h @@ -523,6 +523,8 @@ void intel_enable_pipe(const struct intel_crtc_state *new_crtc_state); void intel_disable_pipe(const struct intel_crtc_state *old_crtc_state); void i830_enable_pipe(struct drm_i915_private *dev_priv, enum pipe pipe); void i830_disable_pipe(struct drm_i915_private *dev_priv, enum pipe pipe); +bool intel_pipe_is_enabled(struct drm_i915_private *dev_priv, + enum transcoder cpu_transcoder); enum pipe intel_crtc_pch_transcoder(struct intel_crtc *crtc); int vlv_get_hpll_vco(struct drm_i915_private *dev_priv); int vlv_get_cck_clock(struct drm_i915_private *dev_priv, -- 2.29.2 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH 2/2] drm/i915/display: Make vlv_find_free_pps() skip pipes which are in use for non DP purposes
00af [8.664307] RAX: ffda RBX: 5573f0770cf0 RCX: 7fe825d9a6be [8.664314] RDX: 7fe825ed035a RSI: 0052b0a0 RDI: 5573f112ae10 [8.664321] RBP: 5573f112ae10 R08: 5573f112ae10 R09: 7fffdc774f70 [8.664328] R10: 5573f0759010 R11: 0246 R12: 7fe825ed035a [8.664334] R13: 5573f077e1e0 R14: 0007 R15: 5573f077f2d0 [8.664379] irq event stamp: 126913 [8.664385] hardirqs last enabled at (126919): [] console_unlock+0x4e9/0x600 [8.664397] hardirqs last disabled at (126924): [] console_unlock+0x45c/0x600 [8.664406] softirqs last enabled at (126624): [] asm_call_irq_on_stack+0x12/0x20 [8.664416] softirqs last disabled at (126619): [] asm_call_irq_on_stack+0x12/0x20 [8.664426] ---[ end trace 5049606d4dbfaebc ]--- Add a check for the combination of the DPLL not being enabled (indicating that DP is not active on the pipe), while the pipe is enabled; and when both conditions are true don't use the pipe for pps. This fixes the above WARN/backtrace. After this the attempt to detect the non existing eDP panel on port B results in the following 2 info messages: [8.461967] i915 :00:02.0: [drm] Pipe A is used for non DP, not using it for pps [8.675304] i915 :00:02.0: [drm] failed to retrieve link info, disabling eDP Indicating that everything is working as it should. Signed-off-by: Hans de Goede --- drivers/gpu/drm/i915/display/intel_dp.c | 22 ++ 1 file changed, 22 insertions(+) diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c index bbe63381aeea..0872b0d1dbba 100644 --- a/drivers/gpu/drm/i915/display/intel_dp.c +++ b/drivers/gpu/drm/i915/display/intel_dp.c @@ -978,6 +978,7 @@ static enum pipe vlv_find_free_pps(struct drm_i915_private *dev_priv) { struct intel_encoder *encoder; unsigned int pipes = (1 << PIPE_A) | (1 << PIPE_B); + enum pipe pipe; /* * We don't have power sequencer currently. @@ -1003,6 +1004,27 @@ static enum pipe vlv_find_free_pps(struct drm_i915_private *dev_priv) } } + /* +* If the DPLL is not enabled and the pipe is enabled then the pipe is +* in use for non DP uses. In this case we *must* not use it for pps. +* This may happen when PIPE A is used for a DSI panel, yet the VLV code +* in intel_setup_outputs() thinks port B may be used for eDP and calls +* intel_dp_init() to check. +*/ + for (pipe = PIPE_A; pipe <= PIPE_B; pipe++) { + if (!(pipes & (1 << pipe))) + continue; + + if (intel_de_read(dev_priv, DPLL(pipe)) & DPLL_VCO_ENABLE) + continue; + + if (intel_pipe_is_enabled(dev_priv, (enum transcoder)pipe)) { + drm_info(&dev_priv->drm, "Pipe %c is used for non DP, not using it for pps\n", +pipe_name(pipe)); + pipes &= ~(1 << pipe); + } + } + if (pipes == 0) return INVALID_PIPE; -- 2.29.2 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
Re: [GIT PULL] ib-drm-gpio-pdx86-rtc-wdt-v5.12-1
Hi, On 2/3/21 10:54 AM, Andy Shevchenko wrote: > On Tue, Jan 26, 2021 at 4:23 PM Hans de Goede wrote: >> On 1/26/21 1:38 PM, Andy Shevchenko wrote: >>> Hi guys, >>> >>> This is first part of Intel MID outdated platforms removal. It's collected >>> into >>> immutable branch with a given tag, please pull to yours subsystems. >>> >>> (All changes are tagged by the respective maintainers) > >> Erm, I already have this 2 in platform-drivers-x86/for-next since you said >> that >> these 2 could be merged independently. >> >> Anyways I just did a test-merge and there is no conflict, so everything is >> ok. >> >> From my pov this looks good and I plan to merge this into >> platform-drivers-x86/for-next >> before the merge-window. >> >> I'm going to hold off on doing that for a bit for now in case one of the >> other >> subsys maintainers has any objections. > > Any news on this? Have you pulled it somewhere (I don't see it in Linux next)? I was going through all pending pdx86 stuff yesterday to prep for the upcoming merge-window. I was doing so in FIFO order and I ran out of steam just as I got to this pull-req. So today is a new day and after sending out a fixes pull-req for 5.11 this is (was) the first thing on my list. I've merged this into my review-hans now (and I will push it to for-next soon). I did one last check of all the commits after merging, and I found one small issue. The "gpio: msic: Remove driver for deprecated platform" commit forgets to drop the Makefile line for the msic driver: obj-$(CONFIG_GPIO_MSIC) += gpio-msic.o This is not a reason to redo the entire branch, but it would be good if you can do a follow up patch to fix this. Regards, Hans ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
Re: [PATCH] drm/vboxvideo: Vmap/vunmap cursor BO in prepare_fb and cleanup_fb
Hi, On 2/3/21 12:14 PM, Thomas Zimmermann wrote: > Hi > > Am 03.02.21 um 11:44 schrieb Daniel Vetter: >> On Wed, Feb 03, 2021 at 11:34:21AM +0100, Thomas Zimmermann wrote: >>> Hi >>> >>> Am 03.02.21 um 11:29 schrieb Daniel Vetter: On Wed, Jan 27, 2021 at 03:05:03PM +0100, Thomas Zimmermann wrote: > Functions in the atomic commit tail are not allowed to acquire the > dmabuf's reservation lock. So we cannot legally call the GEM object's > vmap functionality in atomic_update. > > Instead vmap the cursor BO in prepare_fb and vunmap it in cleanup_fb. > The cursor plane state stores the mapping's address. The pinning of the > BO is implicitly done by vmap. > > As an extra benefit, there's no source of runtime errors left in > atomic_update. > > Signed-off-by: Thomas Zimmermann Did you test this with my dma_fence_signalling annotations patches? >>> >>> Not with vbox. I did test similar code in my recent ast patchset. But I >>> think there's still a bug here, as there's no custom plane-reset function. >> >> Do right, KASAN should complain when you load the driver because the first >> state is a bit too small. But probably still within the kmalloc'ed block >> by sheer luck. Worth confirming that KASAN can catch this. > > I have KASAN enabled and I might just have missed the error message. I later > saw the error with another driver after I already posted the vbox and ast > patches. > > If you have the time, a look at the first half of the ast patchset might > still be worth it. It removes the cursor-code abstraction and shouldn't be > affected by the issue. I must say I'm not entirely following this thread. If I understand things correctly, there is some memory corruption introduced by this patch, so there will be a v2 fixing this ? The reason why I'm asking is because I always try to test vboxvideo patches inside a vbox vm, but if a v2 is coming, there is not much use in me testing this version, correct ? Regards, Hans > --- > drivers/gpu/drm/vboxvideo/vbox_mode.c | 102 +- > 1 file changed, 82 insertions(+), 20 deletions(-) > > diff --git a/drivers/gpu/drm/vboxvideo/vbox_mode.c > b/drivers/gpu/drm/vboxvideo/vbox_mode.c > index dbc0dd53c69e..b5625a7d6cef 100644 > --- a/drivers/gpu/drm/vboxvideo/vbox_mode.c > +++ b/drivers/gpu/drm/vboxvideo/vbox_mode.c > @@ -324,6 +324,19 @@ static void vbox_primary_atomic_disable(struct > drm_plane *plane, > old_state->src_y >> 16); > } > +struct vbox_cursor_plane_state { > + struct drm_plane_state base; > + > + /* Transitional state - do not export or duplicate */ > + > + struct dma_buf_map map; > +}; > + > +static struct vbox_cursor_plane_state *to_vbox_cursor_plane_state(struct > drm_plane_state *state) > +{ > + return container_of(state, struct vbox_cursor_plane_state, base); > +} > + > static int vbox_cursor_atomic_check(struct drm_plane *plane, > struct drm_plane_state *new_state) > { > @@ -381,14 +394,13 @@ static void vbox_cursor_atomic_update(struct > drm_plane *plane, > container_of(plane->dev, struct vbox_private, ddev); > struct vbox_crtc *vbox_crtc = to_vbox_crtc(plane->state->crtc); > struct drm_framebuffer *fb = plane->state->fb; > - struct drm_gem_vram_object *gbo = drm_gem_vram_of_gem(fb->obj[0]); > u32 width = plane->state->crtc_w; > u32 height = plane->state->crtc_h; > + struct vbox_cursor_plane_state *vbox_state = > to_vbox_cursor_plane_state(plane->state); > + struct dma_buf_map map = vbox_state->map; > + u8 *src = map.vaddr; /* TODO: Use mapping abstraction properly */ > size_t data_size, mask_size; > u32 flags; > - struct dma_buf_map map; > - int ret; > - u8 *src; > /* > * VirtualBox uses the host windowing system to draw the cursor so > @@ -401,17 +413,6 @@ static void vbox_cursor_atomic_update(struct > drm_plane *plane, > vbox_crtc->cursor_enabled = true; > - ret = drm_gem_vram_vmap(gbo, &map); > - if (ret) { > - /* > - * BUG: we should have pinned the BO in prepare_fb(). > - */ > - mutex_unlock(&vbox->hw_mutex); > - DRM_WARN("Could not map cursor bo, skipping update\n"); > - return; > - } > - src = map.vaddr; /* TODO: Use mapping abstraction properly */ > - > /* > * The mask must be calculated based on the alpha > * channel, one bit per ARGB word, and must be 32-bit > @@ -421,7 +422,6 @@ static void vbox_cursor_atomic_update(struct > drm_plane *plane, > data_size = width * height * 4 + mask_size; > copy_cursor_image
Re: [GIT PULL] ib-drm-gpio-pdx86-rtc-wdt-v5.12-1
Hi, On 2/4/21 11:36 AM, Daniel Vetter wrote: > On Thu, Feb 4, 2021 at 11:19 AM Patrik Jakobsson > wrote: >> >> On Wed, Feb 3, 2021 at 1:00 PM Andy Shevchenko >> wrote: >>> >>> On Tue, Jan 26, 2021 at 5:25 PM Patrik Jakobsson >>> wrote: On Tue, Jan 26, 2021 at 1:37 PM Andy Shevchenko wrote: > > Hi guys, > > This is first part of Intel MID outdated platforms removal. It's > collected into > immutable branch with a given tag, please pull to yours subsystems. Hi Andy, Do you plan on eventually removing X86_INTEL_MID completely? If so, then I should probably start looking at removing the corresponding parts in GMA500. >>> >>> I have noticed new commits in DRM against GMA500 and it seems now in a >>> conflict with my immutable branch. Are you sure you don't forget to >>> pull it? >> >> Hi Andy, sorry I missed pulling the immutable branch before taking the >> gma500 medfield removal. I was unsure how to do that through drm-misc >> and it's tools so I got sidetracked. What would be the correct way to >> fix this? > > Imo Linus can resolve this, it's pretty trivial, as long as both pull > requests point it out to him. The removal of older Intel platforms touches a number of subsystem trees, the idea about the IM branch was that all subsystem-trees would merge that. I can certainly point out the problem in the pdx86 pull-req to Linus, but the GPIO pull-req also contains a merge of the IM branch as will the x86/tip and rtc pull-reqs I believe. We can add a remark to all the pull-reqs about the issue I guess ? But it might be better to still merge the branch into drm-misc-next and resolve the conflict there. I think that should avoid Linus seeing it ? Regards, Hans ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
Re: [PATCH v2 0/2] drm/vboxvideo: Use struct drm_shadow_plane_state for cursor plane
Hi, On 2/8/21 2:50 PM, Thomas Zimmermann wrote: > (was: drm/vboxvideo: Vmap/vunmap cursor BO in prepare_fb and cleanup_fb) > > Functions in the atomic commit tail are not allowed to acquire the > dmabuf's reservation lock. So we cannot legally call the GEM object's > vmap functionality in atomic_update. > > But, much better, we can use drm_shadow_plane_state to do all the mapping > for us. Patch 1 exports the helpers for shadow-buffered planes from the > DRM KMS helper library and adds documentation on how to use them. Patch 2 > replaces the vmap code in vbox' cursor update code with a the helpers for > shadow-buffered planes. > > Thomas Zimmermann (2): > drm/gem: Export helpers for shadow-buffered planes > drm/vboxvideo: Implement cursor plane with struct > drm_shadow_plane_state I've given this a test spin in a virtualbox vm using VboxSVGA graphics and I've not found any problems: Tested-by: Hans de Goede Regards, Hans > > drivers/gpu/drm/drm_gem_atomic_helper.c | 148 +++- > drivers/gpu/drm/vboxvideo/vbox_mode.c | 28 ++--- > include/drm/drm_gem_atomic_helper.h | 32 + > 3 files changed, 181 insertions(+), 27 deletions(-) > > -- > 2.30.0 > ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
Re: [PATCH v2 0/2] drm/vboxvideo: Use struct drm_shadow_plane_state for cursor plane
Hi, On 2/9/21 9:13 AM, Thomas Zimmermann wrote: > Hi > > Am 08.02.21 um 18:43 schrieb Hans de Goede: >> Hi, >> >> On 2/8/21 2:50 PM, Thomas Zimmermann wrote: >>> (was: drm/vboxvideo: Vmap/vunmap cursor BO in prepare_fb and cleanup_fb) >>> >>> Functions in the atomic commit tail are not allowed to acquire the >>> dmabuf's reservation lock. So we cannot legally call the GEM object's >>> vmap functionality in atomic_update. >>> >>> But, much better, we can use drm_shadow_plane_state to do all the mapping >>> for us. Patch 1 exports the helpers for shadow-buffered planes from the >>> DRM KMS helper library and adds documentation on how to use them. Patch 2 >>> replaces the vmap code in vbox' cursor update code with a the helpers for >>> shadow-buffered planes. >>> >>> Thomas Zimmermann (2): >>> drm/gem: Export helpers for shadow-buffered planes >>> drm/vboxvideo: Implement cursor plane with struct >>> drm_shadow_plane_state >> >> I've given this a test spin in a virtualbox vm using VboxSVGA graphics >> and I've not found any problems: >> >> Tested-by: Hans de Goede > > Thanks a lot. Can I add your Acked-by as well? Patch 1/2 is a bit outside of my area of expertise, but I see you already have a Reviewed-by from Daniel there, so that one should be good to go. I've just reviewed 2/2 and it looks good to me, so for 2/2 you may add my: Reviewed-by: Hans de Goede Regards, Hans >>> >>> drivers/gpu/drm/drm_gem_atomic_helper.c | 148 +++- >>> drivers/gpu/drm/vboxvideo/vbox_mode.c | 28 ++--- >>> include/drm/drm_gem_atomic_helper.h | 32 + >>> 3 files changed, 181 insertions(+), 27 deletions(-) >>> >>> -- >>> 2.30.0 >>> >> >> ___ >> dri-devel mailing list >> dri-devel@lists.freedesktop.org >> https://lists.freedesktop.org/mailman/listinfo/dri-devel >> > ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH] drm/i915/display/vlv_dsi: Do no shut down displays on reboot if a DSI panel is used
After the recently added commit fe0f1e3bfdfe ("drm/i915: Shut down displays gracefully on reboot"), the DSI panel on a Cherry Trail based Predia Basic tablet would no longer properly light up after reboot. The backlight still turns back on after reboot, but the LCD shows an all black display. The display is also all black during the time that EFI / the GOP is managing it, so e.g. the grub menu also is not visible. In this scenario the panel is initialized so that it appears to be working and the fastboot code skips doing a modeset. Forcing a modeset by doing a chvt to a text-console over ssh followed by echo-ing 1 and then 0 to /sys/class/graphics/fb0/blank causes the panel to work again. Add a QUIRK_SKIP_SHUTDOWN quirk which turns i915_driver_shutdown() into a no-op when set; and set this on vlv/chv devices when a DSI panel is detected, to work around this. Admittedly this is a bit of a big hammer, but these platforms have been around for quite some time now and they have always worked fine without the new behavior to shutdown everything on shutdown/reboot. This approach simply disables the recently introduced new shutdown behavior in this specific case where it is known to cause problems. Which is a nice and simple way to deal with this. Signed-off-by: Hans de Goede --- drivers/gpu/drm/i915/display/vlv_dsi.c | 3 +++ drivers/gpu/drm/i915/i915_drv.c| 3 +++ drivers/gpu/drm/i915/i915_drv.h| 1 + 3 files changed, 7 insertions(+) diff --git a/drivers/gpu/drm/i915/display/vlv_dsi.c b/drivers/gpu/drm/i915/display/vlv_dsi.c index f94025ec603a..792ef868b6af 100644 --- a/drivers/gpu/drm/i915/display/vlv_dsi.c +++ b/drivers/gpu/drm/i915/display/vlv_dsi.c @@ -1949,6 +1949,9 @@ void vlv_dsi_init(struct drm_i915_private *dev_priv) vlv_dsi_add_properties(intel_connector); + /* Some BIOS-es fail to re-init the DSI panel on reboot if we turn it off */ + dev_priv->quirks |= QUIRK_SKIP_SHUTDOWN; + return; err_cleanup_connector: diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index 8e9cb44e66e5..92f2af55af6d 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -1048,6 +1048,9 @@ static void intel_shutdown_encoders(struct drm_i915_private *dev_priv) void i915_driver_shutdown(struct drm_i915_private *i915) { + if (i915->quirks & QUIRK_SKIP_SHUTDOWN) + return; + disable_rpm_wakeref_asserts(&i915->runtime_pm); i915_gem_suspend(i915); diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 26d69d06aa6d..272cd7cb22d4 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -517,6 +517,7 @@ struct i915_psr { #define QUIRK_PIN_SWIZZLED_PAGES (1<<5) #define QUIRK_INCREASE_T12_DELAY (1<<6) #define QUIRK_INCREASE_DDI_DISABLED_TIME (1<<7) +#define QUIRK_SKIP_SHUTDOWN (1<<8) struct intel_fbdev; struct intel_fbc_work; -- 2.30.1 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH resend 2/2] drm/i915/display: Make vlv_find_free_pps() skip pipes which are in use for non DP purposes
00af [8.664307] RAX: ffda RBX: 5573f0770cf0 RCX: 7fe825d9a6be [8.664314] RDX: 7fe825ed035a RSI: 0052b0a0 RDI: 5573f112ae10 [8.664321] RBP: 5573f112ae10 R08: 5573f112ae10 R09: 7fffdc774f70 [8.664328] R10: 5573f0759010 R11: 0246 R12: 7fe825ed035a [8.664334] R13: 5573f077e1e0 R14: 0007 R15: 5573f077f2d0 [8.664379] irq event stamp: 126913 [8.664385] hardirqs last enabled at (126919): [] console_unlock+0x4e9/0x600 [8.664397] hardirqs last disabled at (126924): [] console_unlock+0x45c/0x600 [8.664406] softirqs last enabled at (126624): [] asm_call_irq_on_stack+0x12/0x20 [8.664416] softirqs last disabled at (126619): [] asm_call_irq_on_stack+0x12/0x20 [8.664426] ---[ end trace 5049606d4dbfaebc ]--- Add a check for the combination of the DPLL not being enabled (indicating that DP is not active on the pipe), while the pipe is enabled; and when both conditions are true don't use the pipe for pps. This fixes the above WARN/backtrace. After this the attempt to detect the non existing eDP panel on port B results in the following 2 info messages: [8.461967] i915 :00:02.0: [drm] Pipe A is used for non DP, not using it for pps [8.675304] i915 :00:02.0: [drm] failed to retrieve link info, disabling eDP Indicating that everything is working as it should. Signed-off-by: Hans de Goede --- drivers/gpu/drm/i915/display/intel_pps.c | 22 ++ 1 file changed, 22 insertions(+) diff --git a/drivers/gpu/drm/i915/display/intel_pps.c b/drivers/gpu/drm/i915/display/intel_pps.c index f20ba71f4307..757e82825919 100644 --- a/drivers/gpu/drm/i915/display/intel_pps.c +++ b/drivers/gpu/drm/i915/display/intel_pps.c @@ -121,6 +121,7 @@ static enum pipe vlv_find_free_pps(struct drm_i915_private *dev_priv) { struct intel_encoder *encoder; unsigned int pipes = (1 << PIPE_A) | (1 << PIPE_B); + enum pipe pipe; /* * We don't have power sequencer currently. @@ -146,6 +147,27 @@ static enum pipe vlv_find_free_pps(struct drm_i915_private *dev_priv) } } + /* +* If the DPLL is not enabled and the pipe is enabled then the pipe is +* in use for non DP uses. In this case we *must* not use it for pps. +* This may happen when PIPE A is used for a DSI panel, yet the VLV code +* in intel_setup_outputs() thinks port B may be used for eDP and calls +* intel_dp_init() to check. +*/ + for (pipe = PIPE_A; pipe <= PIPE_B; pipe++) { + if (!(pipes & (1 << pipe))) + continue; + + if (intel_de_read(dev_priv, DPLL(pipe)) & DPLL_VCO_ENABLE) + continue; + + if (intel_pipe_is_enabled(dev_priv, (enum transcoder)pipe)) { + drm_info(&dev_priv->drm, "Pipe %c is used for non DP, not using it for pps\n", +pipe_name(pipe)); + pipes &= ~(1 << pipe); + } + } + if (pipes == 0) return INVALID_PIPE; -- 2.30.1 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH resend 0/2] drm/i915/display: Make vlv_find_free_pps() skip pipes which are in use for non DP purposes
Hi All, Here is a resend of my patch-set to deal with an "transcoder A assertion failure (expected off, current on)" error + WARN (and backtrace) seen on some Bay Trail devices with a DSI panel. I've rebased it on the latest drm-intel-next, so this time around the CI should be able to actually apply and test it, please review. Regards, Hans Hans de Goede (2): drm/i915/display: Add a intel_pipe_is_enabled() helper drm/i915/display: Make vlv_find_free_pps() skip pipes which are in use for non DP purposes drivers/gpu/drm/i915/display/intel_display.c | 20 -- drivers/gpu/drm/i915/display/intel_display.h | 2 ++ drivers/gpu/drm/i915/display/intel_pps.c | 22 3 files changed, 38 insertions(+), 6 deletions(-) -- 2.30.1 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH resend 1/2] drm/i915/display: Add a intel_pipe_is_enabled() helper
Factor the code to check if a pipe is currently enabled out of assert_pipe() and put it in a new intel_pipe_is_enabled() helper, so that it can be re-used without copy-pasting it. Signed-off-by: Hans de Goede --- drivers/gpu/drm/i915/display/intel_display.c | 20 ++-- drivers/gpu/drm/i915/display/intel_display.h | 2 ++ 2 files changed, 16 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index e1060076ac83..9cb304aee285 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -442,17 +442,13 @@ void assert_panel_unlocked(struct drm_i915_private *dev_priv, enum pipe pipe) pipe_name(pipe)); } -void assert_pipe(struct drm_i915_private *dev_priv, -enum transcoder cpu_transcoder, bool state) +bool intel_pipe_is_enabled(struct drm_i915_private *dev_priv, + enum transcoder cpu_transcoder) { bool cur_state; enum intel_display_power_domain power_domain; intel_wakeref_t wakeref; - /* we keep both pipes enabled on 830 */ - if (IS_I830(dev_priv)) - state = true; - power_domain = POWER_DOMAIN_TRANSCODER(cpu_transcoder); wakeref = intel_display_power_get_if_enabled(dev_priv, power_domain); if (wakeref) { @@ -464,6 +460,18 @@ void assert_pipe(struct drm_i915_private *dev_priv, cur_state = false; } + return cur_state; +} + +void assert_pipe(struct drm_i915_private *dev_priv, +enum transcoder cpu_transcoder, bool state) +{ + bool cur_state = intel_pipe_is_enabled(dev_priv, cpu_transcoder); + + /* we keep both pipes enabled on 830 */ + if (IS_I830(dev_priv)) + state = true; + I915_STATE_WARN(cur_state != state, "transcoder %s assertion failure (expected %s, current %s)\n", transcoder_name(cpu_transcoder), diff --git a/drivers/gpu/drm/i915/display/intel_display.h b/drivers/gpu/drm/i915/display/intel_display.h index 0e4c1481fa00..642cc87f3e38 100644 --- a/drivers/gpu/drm/i915/display/intel_display.h +++ b/drivers/gpu/drm/i915/display/intel_display.h @@ -533,6 +533,8 @@ void intel_enable_pipe(const struct intel_crtc_state *new_crtc_state); void intel_disable_pipe(const struct intel_crtc_state *old_crtc_state); void i830_enable_pipe(struct drm_i915_private *dev_priv, enum pipe pipe); void i830_disable_pipe(struct drm_i915_private *dev_priv, enum pipe pipe); +bool intel_pipe_is_enabled(struct drm_i915_private *dev_priv, + enum transcoder cpu_transcoder); enum pipe intel_crtc_pch_transcoder(struct intel_crtc *crtc); int vlv_get_hpll_vco(struct drm_i915_private *dev_priv); int vlv_get_cck_clock(struct drm_i915_private *dev_priv, -- 2.30.1 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
Re: [PATCH] drm/vboxvideo: Use managed VRAM-helper initialization
Hi, On 3/11/21 2:11 PM, Daniel Vetter wrote: > On Wed, Mar 03, 2021 at 09:39:46AM +0800, Tian Tao wrote: >> updated to use drmm_vram_helper_init(). >> >> Signed-off-by: Tian Tao > > Hans, do you plan to pick this up? The drm patch-workflow falls outside my daily kernel-work workflow, so it is always a bit of a task-switch for me to switch to dealing with the "dim" workflow. ATM I don't have any other drm work pending, so I would appreciate it if someone else can pick this up. The change does look good to me: Reviewed-by: Hans de Goede Regards, Hans > -Daniel > >> --- >> drivers/gpu/drm/vboxvideo/vbox_ttm.c | 7 ++- >> 1 file changed, 2 insertions(+), 5 deletions(-) >> >> diff --git a/drivers/gpu/drm/vboxvideo/vbox_ttm.c >> b/drivers/gpu/drm/vboxvideo/vbox_ttm.c >> index 0066a3c..fd8a53a 100644 >> --- a/drivers/gpu/drm/vboxvideo/vbox_ttm.c >> +++ b/drivers/gpu/drm/vboxvideo/vbox_ttm.c >> @@ -12,15 +12,13 @@ >> >> int vbox_mm_init(struct vbox_private *vbox) >> { >> -struct drm_vram_mm *vmm; >> int ret; >> struct drm_device *dev = &vbox->ddev; >> struct pci_dev *pdev = to_pci_dev(dev->dev); >> >> -vmm = drm_vram_helper_alloc_mm(dev, pci_resource_start(pdev, 0), >> +ret = drmm_vram_helper_init(dev, pci_resource_start(pdev, 0), >> vbox->available_vram_size); >> -if (IS_ERR(vmm)) { >> -ret = PTR_ERR(vmm); >> +if (ret) { >> DRM_ERROR("Error initializing VRAM MM; %d\n", ret); >> return ret; >> } >> @@ -33,5 +31,4 @@ int vbox_mm_init(struct vbox_private *vbox) >> void vbox_mm_fini(struct vbox_private *vbox) >> { >> arch_phys_wc_del(vbox->fb_mtrr); >> -drm_vram_helper_release_mm(&vbox->ddev); >> } >> -- >> 2.7.4 >> > ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
Re: [PATCH 4/9] drm/connector: Add support for out-of-band hotplug notification
Hi, On 5/3/21 10:00 AM, Heikki Krogerus wrote: > Hi Hans, > > On Wed, Apr 28, 2021 at 11:52:52PM +0200, Hans de Goede wrote: >> +/** >> + * struct drm_connector_oob_hotplug_event_data: OOB hotplug event data >> + * >> + * Contains data about out-of-band hotplug events, signalled through >> + * drm_connector_oob_hotplug_event(). >> + */ >> +struct drm_connector_oob_hotplug_event_data { >> +/** >> + * @connected: New connected status for the connector. >> + */ >> +bool connected; >> +/** >> + * @dp_lanes: Number of available displayport lanes, 0 if unknown. >> + */ >> +int dp_lanes; >> +/** >> + * @orientation: Connector orientation. >> + */ >> +enum typec_orientation orientation; >> +}; > > I don't think the orientation is relevant. It will always be "normal" > from DP PoW after muxing, no? That is what I thought to, but during the discussion of my previous attempt at this one of the i915 devs mentioned that in some cases the muxes manage to swap the lane order when the connector upside-down and at least the Intel GPUs can correct for this on the GPU side, so they asked for this info to be included. > I'm also not sure those deatils are enough in the long run. Based on > what I've understood from our graphics team guys, for example knowing > if multi-function is preferred may be important in some cases. The current data being passed is just intended as a starting point, this is purely a kernel internal API so we can easily add more data to the struct. As I mentioned in the cover-letter the current oob_hotplug handler which the i915 patch adds to the i915 driver does not actually do anything with the data. ATM it is purely there to demonstrate that the ability to pass relevant data is there now (which was an issue with the previous attempt). I believe the current code is fine as a PoC of "pass event data" once GPU drivers actually start doing something with the data we can extend or outright replace it without issues. > +Imre. > > All of that, and more, is already available in the Configuration VDO > Status VDO that the we have negotiated with the DP partner. Both those > VDOs are part of struct typec_displayport_data. I think we should > simply supply that structure to the DRM code instead of picking those > details out of it... I'm not sure I like the idea of passing the raw VDO, but if the DRM folks think that would be useful we can certainly add it. Regards, Hans > >> /** >> * struct drm_tv_connector_state - TV connector related states >> * @subconnector: selected subconnector >> @@ -1110,6 +1132,15 @@ struct drm_connector_funcs { >> */ >> void (*atomic_print_state)(struct drm_printer *p, >> const struct drm_connector_state *state); >> + >> +/** >> + * @oob_hotplug_event: >> + * >> + * This will get called when a hotplug-event for a drm-connector >> + * has been received from a source outside the display driver / device. >> + */ >> +void (*oob_hotplug_event)(struct drm_connector *connector, >> + struct drm_connector_oob_hotplug_event_data >> *data); > > So I would not try to generalise this like that. This callback should > be USB Type-C DP altmode specific: > > void (*oob_hotplug_event)(struct drm_connector *connector, > struct typec_displayport_data *data); > > Or like this if the orientation can really be reversed after muxing: > > void (*oob_hotplug_event)(struct drm_connector *connector, > struct typec_altmode *altmode, > struct typec_displayport_data *data); > > You can now check the orientation separately with > typec_altmode_get_orientation() if necessary. > > > thanks, > ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH 0/9] drm + usb-type-c: Add support for out-of-band hotplug notification (v2)
Hi All, Here is v2 of my work on making DP over Type-C work on devices where the Type-C controller does not drive the HPD pin on the GPU, but instead we need to forward HPD events from the Type-C controller to the DRM driver. Changes in v2: - Replace the bogus "drm/connector: Make the drm_sysfs connector->kdev device hold a reference to the connector" patch with: "drm/connector: Give connector sysfs devices there own device_type" the new patch is a dep for patch 2/9 see the patches - Stop using a class-dev-iter, instead at a global connector list to drm_connector.c and use that to find the connector by the fwnode, similar to how we already do this in drm_panel.c and drm_bridge.c - Make drm_connector_oob_hotplug_event() take a fwnode pointer as argument, rather then a drm_connector pointer and let it do the lookup itself. This allows making drm_connector_find_by_fwnode() a drm-internal function and avoids code outside the drm subsystem potentially holding on the a drm_connector reference for a longer period. This series not only touches drm subsys files but it also touches drivers/usb/typec/altmodes/typec_displayport.c, that file usually does not see a whole lot of changes. So I believe it would be best to just merge the entire series through drm-misc, Assuming we can get an ack from Greg for merging the typec_displayport.c changes this way. ### As already mentioned in the v1 cover-letter this series replaces a previous attempt from quite some time ago. For anyone interested here are the old (2019!) patches for this: https://patchwork.freedesktop.org/patch/288491/ https://patchwork.freedesktop.org/patch/288493/ https://patchwork.freedesktop.org/patch/288495/ Last time I posted this the biggest change requested was for more info to be included in the event send to the DRM-subsystem, specifically sending the following info was requested: 1. Which DP connector on the GPU the event is for 2. How many lanes are available 3. Connector orientation This series is basically an entirely new approach, which no longer uses the notifier framework at all. Instead the Type-C code looksup a connector based on a fwnode (this was suggested by Heikki Krogerus) and then calls a new oob_hotplug_event drm_connector_func directly on the connector, passing the requested info as argument. Info such as the orientation and the number of dp-lanes is now passed to the drm_connector_oob_hotplug_event() function as requested in the review of the old code, but nothing is done with it for now. Using this info falls well outside of my knowledge of the i915 driver so this is left to a follow-up patch (I will be available to test patches for this). Regards, Hans Hans de Goede (8): drm/connector: Give connector sysfs devices there own device_type drm/connector: Add a fwnode pointer to drm_connector and register with ACPI drm/connector: Add drm_connector_find_by_fwnode() function (v2) drm/connector: Add support for out-of-band hotplug notification (v2) drm/i915/dp: Add support for out-of-bound hotplug events usb: typec: altmodes/displayport: Make dp_altmode_notify() more generic usb: typec: altmodes/displayport: Notify drm subsys of hotplug events platform/x86/intel_cht_int33fe: Correct "displayport" fwnode reference Heikki Krogerus (1): drm/i915: Associate ACPI connector nodes with connector entries drivers/gpu/drm/drm_connector.c | 79 + drivers/gpu/drm/drm_crtc_internal.h | 1 + drivers/gpu/drm/drm_sysfs.c | 87 --- drivers/gpu/drm/i915/display/intel_acpi.c | 40 + drivers/gpu/drm/i915/display/intel_acpi.h | 3 + drivers/gpu/drm/i915/display/intel_display.c | 1 + drivers/gpu/drm/i915/display/intel_dp.c | 13 +++ .../platform/x86/intel_cht_int33fe_typec.c| 4 +- drivers/usb/typec/altmodes/Kconfig| 1 + drivers/usb/typec/altmodes/displayport.c | 73 +++- include/drm/drm_connector.h | 43 + 11 files changed, 308 insertions(+), 37 deletions(-) -- 2.31.1 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH 2/9] drm/connector: Add a fwnode pointer to drm_connector and register with ACPI
Add a fwnode pointer to struct drm_connector and register an acpi_bus_type for the connectors with the ACPI subsystem (when CONFIG_ACPI is enabled). The adding of the fwnode pointer allows drivers to associate a fwnode that represents a connector with that connector. When the new fwnode pointer points to an ACPI-companion, then the new acpi_bus_type will cause the ACPI subsys to bind the device instantiated for the connector with the fwnode by calling acpi_bind_one(). This will result in a firmware_node symlink under /sys/class/card#-/ which helps to verify that the fwnode-s and connectors are properly matched. Co-authored-by: Heikki Krogerus Signed-off-by: Heikki Krogerus Signed-off-by: Hans de Goede --- drivers/gpu/drm/drm_sysfs.c | 37 + include/drm/drm_connector.h | 2 ++ 2 files changed, 39 insertions(+) diff --git a/drivers/gpu/drm/drm_sysfs.c b/drivers/gpu/drm/drm_sysfs.c index 553024bcda8a..12cc649c44f0 100644 --- a/drivers/gpu/drm/drm_sysfs.c +++ b/drivers/gpu/drm/drm_sysfs.c @@ -10,6 +10,7 @@ * Copyright (c) 2003-2004 IBM Corp. */ +#include #include #include #include @@ -56,6 +57,39 @@ static struct device_type drm_sysfs_device_connector = { struct class *drm_class; +#ifdef CONFIG_ACPI +static bool drm_connector_acpi_bus_match(struct device *dev) +{ + return dev->type == &drm_sysfs_device_connector; +} + +static struct acpi_device *drm_connector_acpi_find_companion(struct device *dev) +{ + struct drm_connector *connector = to_drm_connector(dev); + + return to_acpi_device_node(connector->fwnode); +} + +static struct acpi_bus_type drm_connector_acpi_bus = { + .name = "drm_connector", + .match = drm_connector_acpi_bus_match, + .find_companion = drm_connector_acpi_find_companion, +}; + +static void drm_sysfs_acpi_register(void) +{ + register_acpi_bus_type(&drm_connector_acpi_bus); +} + +static void drm_sysfs_acpi_unregister(void) +{ + unregister_acpi_bus_type(&drm_connector_acpi_bus); +} +#else +static void drm_sysfs_acpi_register(void) { } +static void drm_sysfs_acpi_unregister(void) { } +#endif + static char *drm_devnode(struct device *dev, umode_t *mode) { return kasprintf(GFP_KERNEL, "dri/%s", dev_name(dev)); @@ -89,6 +123,8 @@ int drm_sysfs_init(void) } drm_class->devnode = drm_devnode; + + drm_sysfs_acpi_register(); return 0; } @@ -101,6 +137,7 @@ void drm_sysfs_destroy(void) { if (IS_ERR_OR_NULL(drm_class)) return; + drm_sysfs_acpi_unregister(); class_remove_file(drm_class, &class_attr_version.attr); class_destroy(drm_class); drm_class = NULL; diff --git a/include/drm/drm_connector.h b/include/drm/drm_connector.h index 0261801af62c..d20bfd7576ed 100644 --- a/include/drm/drm_connector.h +++ b/include/drm/drm_connector.h @@ -1254,6 +1254,8 @@ struct drm_connector { struct device *kdev; /** @attr: sysfs attributes */ struct device_attribute *attr; + /** @fwnode: associated fwnode supplied by platform firmware */ + struct fwnode_handle *fwnode; /** * @head: -- 2.31.1 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH 1/9] drm/connector: Give connector sysfs devices there own device_type
Give connector sysfs devices there own device_type, this allows us to check if a device passed to functions dealing with generic devices is a drm_connector or not. A check like this is necessary in the drm_connector_acpi_bus_match() function added in the next patch in this series. Signed-off-by: Hans de Goede --- drivers/gpu/drm/drm_sysfs.c | 50 +++-- 1 file changed, 37 insertions(+), 13 deletions(-) diff --git a/drivers/gpu/drm/drm_sysfs.c b/drivers/gpu/drm/drm_sysfs.c index f0336c804639..553024bcda8a 100644 --- a/drivers/gpu/drm/drm_sysfs.c +++ b/drivers/gpu/drm/drm_sysfs.c @@ -50,6 +50,10 @@ static struct device_type drm_sysfs_device_minor = { .name = "drm_minor" }; +static struct device_type drm_sysfs_device_connector = { + .name = "drm_connector", +}; + struct class *drm_class; static char *drm_devnode(struct device *dev, umode_t *mode) @@ -102,6 +106,11 @@ void drm_sysfs_destroy(void) drm_class = NULL; } +static void drm_sysfs_release(struct device *dev) +{ + kfree(dev); +} + /* * Connector properties */ @@ -274,27 +283,47 @@ static const struct attribute_group *connector_dev_groups[] = { int drm_sysfs_connector_add(struct drm_connector *connector) { struct drm_device *dev = connector->dev; + struct device *kdev; + int r; if (connector->kdev) return 0; - connector->kdev = - device_create_with_groups(drm_class, dev->primary->kdev, 0, - connector, connector_dev_groups, - "card%d-%s", dev->primary->index, - connector->name); + kdev = kzalloc(sizeof(*kdev), GFP_KERNEL); + if (!kdev) + return -ENOMEM; + + device_initialize(kdev); + kdev->class = drm_class; + kdev->type = &drm_sysfs_device_connector; + kdev->parent = dev->primary->kdev; + kdev->groups = connector_dev_groups; + kdev->release = drm_sysfs_release; + dev_set_drvdata(kdev, connector); + + r = dev_set_name(kdev, "card%d-%s", dev->primary->index, connector->name); + if (r) + goto err_free; + DRM_DEBUG("adding \"%s\" to sysfs\n", connector->name); - if (IS_ERR(connector->kdev)) { - DRM_ERROR("failed to register connector device: %ld\n", PTR_ERR(connector->kdev)); - return PTR_ERR(connector->kdev); + r = device_add(kdev); + if (r) { + DRM_ERROR("failed to register connector device: %d\n", r); + goto err_free; } + connector->kdev = kdev; + if (connector->ddc) return sysfs_create_link(&connector->kdev->kobj, &connector->ddc->dev.kobj, "ddc"); return 0; + +err_free: + put_device(kdev); + return r; } void drm_sysfs_connector_remove(struct drm_connector *connector) @@ -375,11 +404,6 @@ void drm_sysfs_connector_status_event(struct drm_connector *connector, } EXPORT_SYMBOL(drm_sysfs_connector_status_event); -static void drm_sysfs_release(struct device *dev) -{ - kfree(dev); -} - struct device *drm_sysfs_minor_alloc(struct drm_minor *minor) { const char *minor_str; -- 2.31.1 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH 3/9] drm/connector: Add drm_connector_find_by_fwnode() function (v2)
Add a function to find a connector based on a fwnode. This will be used by the new drm_connector_oob_hotplug_event() function which is added by the next patch in this patch-set. Changes in v2: - Complete rewrite to use a global connector list in drm_connector.c rather then using a class-dev-iter in drm_sysfs.c Signed-off-by: Hans de Goede --- drivers/gpu/drm/drm_connector.c | 50 + drivers/gpu/drm/drm_crtc_internal.h | 1 + include/drm/drm_connector.h | 8 + 3 files changed, 59 insertions(+) diff --git a/drivers/gpu/drm/drm_connector.c b/drivers/gpu/drm/drm_connector.c index 87c68563e6c3..ef759d6add81 100644 --- a/drivers/gpu/drm/drm_connector.c +++ b/drivers/gpu/drm/drm_connector.c @@ -66,6 +66,14 @@ * support can instead use e.g. drm_helper_hpd_irq_event(). */ +/* + * Global connector list for drm_connector_find_by_fwnode(). + * Note drm_connector_[un]register() first take connector->lock and then + * take the connector_list_lock. + */ +static DEFINE_MUTEX(connector_list_lock); +static LIST_HEAD(connector_list); + struct drm_conn_prop_enum_list { int type; const char *name; @@ -267,6 +275,7 @@ int drm_connector_init(struct drm_device *dev, goto out_put_type_id; } + INIT_LIST_HEAD(&connector->global_connector_list_entry); INIT_LIST_HEAD(&connector->probed_modes); INIT_LIST_HEAD(&connector->modes); mutex_init(&connector->mutex); @@ -540,6 +549,9 @@ int drm_connector_register(struct drm_connector *connector) drm_privacy_screen_register_notifier(connector->privacy_screen, &connector->privacy_screen_notifier); + mutex_lock(&connector_list_lock); + list_add_tail(&connector->global_connector_list_entry, &connector_list); + mutex_unlock(&connector_list_lock); goto unlock; err_debugfs: @@ -568,6 +580,10 @@ void drm_connector_unregister(struct drm_connector *connector) return; } + mutex_lock(&connector_list_lock); + list_del_init(&connector->global_connector_list_entry); + mutex_unlock(&connector_list_lock); + if (connector->privacy_screen) drm_privacy_screen_unregister_notifier( connector->privacy_screen, @@ -2676,6 +2692,40 @@ int drm_mode_getconnector(struct drm_device *dev, void *data, return ret; } +/** + * drm_connector_find_by_fwnode - Find a connector based on the associated fwnode + * @fwnode: fwnode for which to find the matching drm_connector + * + * This functions looks up a drm_connector based on its associated fwnode. When + * a connector is found a reference to the connector is returned. The caller must + * call drm_connector_put() to release this reference when it is done with the + * connector. + * + * Returns: A reference to the found connector or an ERR_PTR(). + */ +struct drm_connector *drm_connector_find_by_fwnode(struct fwnode_handle *fwnode) +{ + struct drm_connector *connector, *found = ERR_PTR(-ENODEV); + + if (!fwnode) + return ERR_PTR(-ENODEV); + + mutex_lock(&connector_list_lock); + + list_for_each_entry(connector, &connector_list, global_connector_list_entry) { + if (connector->fwnode == fwnode || + (connector->fwnode && connector->fwnode->secondary == fwnode)) { + drm_connector_get(connector); + found = connector; + break; + } + } + + mutex_unlock(&connector_list_lock); + + return found; +} + /** * DOC: Tile group diff --git a/drivers/gpu/drm/drm_crtc_internal.h b/drivers/gpu/drm/drm_crtc_internal.h index 54d4cf1233e9..6e28fc00a740 100644 --- a/drivers/gpu/drm/drm_crtc_internal.h +++ b/drivers/gpu/drm/drm_crtc_internal.h @@ -185,6 +185,7 @@ int drm_connector_set_obj_prop(struct drm_mode_object *obj, int drm_connector_create_standard_properties(struct drm_device *dev); const char *drm_get_connector_force_name(enum drm_connector_force force); void drm_connector_free_work_fn(struct work_struct *work); +struct drm_connector *drm_connector_find_by_fwnode(struct fwnode_handle *fwnode); /* IOCTL */ int drm_connector_property_set_ioctl(struct drm_device *dev, diff --git a/include/drm/drm_connector.h b/include/drm/drm_connector.h index d20bfd7576ed..ae377354e48e 100644 --- a/include/drm/drm_connector.h +++ b/include/drm/drm_connector.h @@ -1267,6 +1267,14 @@ struct drm_connector { */ struct list_head head; + /** +* @global_connector_list_entry: +* +* Connector entry in the global connector-list, used by +* drm_connector_find_by_fwnode(). +*/ + struct list_head globa
[PATCH 4/9] drm/connector: Add support for out-of-band hotplug notification (v2)
Add a new drm_connector_oob_hotplug_event() function and oob_hotplug_event drm_connector_funcs member. On some hardware a hotplug event notification may come from outside the display driver / device. An example of this is some USB Type-C setups where the hardware muxes the DisplayPort data and aux-lines but does not pass the altmode HPD status bit to the GPU's DP HPD pin. In cases like this the new drm_connector_oob_hotplug_event() function can be used to report these out-of-band events. Changes in v2: - Make drm_connector_oob_hotplug_event() take a fwnode as argument and have it call drm_connector_find_by_fwnode() internally. This allows making drm_connector_find_by_fwnode() a drm-internal function and avoids code outside the drm subsystem potentially holding on the a drm_connector reference for a longer period. Signed-off-by: Hans de Goede --- drivers/gpu/drm/drm_connector.c | 29 + include/drm/drm_connector.h | 33 + 2 files changed, 62 insertions(+) diff --git a/drivers/gpu/drm/drm_connector.c b/drivers/gpu/drm/drm_connector.c index ef759d6add81..b5e09d751694 100644 --- a/drivers/gpu/drm/drm_connector.c +++ b/drivers/gpu/drm/drm_connector.c @@ -2726,6 +2726,35 @@ struct drm_connector *drm_connector_find_by_fwnode(struct fwnode_handle *fwnode) return found; } +/** + * drm_connector_oob_hotplug_event - Report out-of-band hotplug event to connector + * @connector: connector to report the event on + * @data: data related to the event + * + * On some hardware a hotplug event notification may come from outside the display + * driver / device. An example of this is some USB Type-C setups where the hardware + * muxes the DisplayPort data and aux-lines but does not pass the altmode HPD + * status bit to the GPU's DP HPD pin. + * + * This function can be used to report these out-of-band events after obtaining + * a drm_connector reference through calling drm_connector_find_by_fwnode(). + */ +void drm_connector_oob_hotplug_event(struct fwnode_handle *connector_fwnode, +struct drm_connector_oob_hotplug_event_data *data) +{ + struct drm_connector *connector; + + connector = drm_connector_find_by_fwnode(connector_fwnode); + if (IS_ERR(connector)) + return; + + if (connector->funcs->oob_hotplug_event) + connector->funcs->oob_hotplug_event(connector, data); + + drm_connector_put(connector); +} +EXPORT_SYMBOL(drm_connector_oob_hotplug_event); + /** * DOC: Tile group diff --git a/include/drm/drm_connector.h b/include/drm/drm_connector.h index ae377354e48e..bb61aeb9ba2d 100644 --- a/include/drm/drm_connector.h +++ b/include/drm/drm_connector.h @@ -27,6 +27,7 @@ #include #include #include +#include /* For enum typec_orientation */ #include #include @@ -649,6 +650,27 @@ struct drm_connector_tv_margins { unsigned int top; }; +/** + * struct drm_connector_oob_hotplug_event_data: OOB hotplug event data + * + * Contains data about out-of-band hotplug events, signalled through + * drm_connector_oob_hotplug_event(). + */ +struct drm_connector_oob_hotplug_event_data { + /** +* @connected: New connected status for the connector. +*/ + bool connected; + /** +* @dp_lanes: Number of available displayport lanes, 0 if unknown. +*/ + int dp_lanes; + /** +* @orientation: Connector orientation. +*/ + enum typec_orientation orientation; +}; + /** * struct drm_tv_connector_state - TV connector related states * @subconnector: selected subconnector @@ -1110,6 +1132,15 @@ struct drm_connector_funcs { */ void (*atomic_print_state)(struct drm_printer *p, const struct drm_connector_state *state); + + /** +* @oob_hotplug_event: +* +* This will get called when a hotplug-event for a drm-connector +* has been received from a source outside the display driver / device. +*/ + void (*oob_hotplug_event)(struct drm_connector *connector, + struct drm_connector_oob_hotplug_event_data *data); }; /** @@ -1704,6 +1735,8 @@ drm_connector_is_unregistered(struct drm_connector *connector) DRM_CONNECTOR_UNREGISTERED; } +void drm_connector_oob_hotplug_event(struct fwnode_handle *connector_fwnode, +struct drm_connector_oob_hotplug_event_data *data); const char *drm_get_connector_type_name(unsigned int connector_type); const char *drm_get_connector_status_name(enum drm_connector_status status); const char *drm_get_subpixel_order_name(enum subpixel_order order); -- 2.31.1 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH 6/9] drm/i915/dp: Add support for out-of-bound hotplug events
On some Cherry Trail devices, DisplayPort over Type-C is supported through a USB-PD microcontroller (e.g. a fusb302) + a mux to switch the superspeed datalines between USB-3 and DP (e.g. a pi3usb30532). The kernel in this case does the PD/alt-mode negotiation itself, rather then everything being handled in firmware. So the kernel itself picks an alt-mode, tells the Type-C "dongle" to switch to DP mode and sets the mux accordingly. In this setup the HPD pin is not connected, so the i915 driver needs to respond to a software event and scan the DP port for changes manually. This commit adds support for this. Together with the recent addition of DP alt-mode support to the Type-C subsystem this makes DP over Type-C work on these devices. Signed-off-by: Hans de Goede --- drivers/gpu/drm/i915/display/intel_dp.c | 13 + 1 file changed, 13 insertions(+) diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c index 64a73b3ced94..1029720cc945 100644 --- a/drivers/gpu/drm/i915/display/intel_dp.c +++ b/drivers/gpu/drm/i915/display/intel_dp.c @@ -5846,6 +5846,18 @@ static int intel_dp_connector_atomic_check(struct drm_connector *conn, return intel_modeset_synced_crtcs(state, conn); } +static void intel_dp_oob_hotplug_event(struct drm_connector *connector, + struct drm_connector_oob_hotplug_event_data *data) +{ + struct intel_encoder *encoder = intel_attached_encoder(to_intel_connector(connector)); + struct drm_i915_private *i915 = to_i915(connector->dev); + + spin_lock_irq(&i915->irq_lock); + i915->hotplug.event_bits |= BIT(encoder->hpd_pin); + spin_unlock_irq(&i915->irq_lock); + queue_delayed_work(system_wq, &i915->hotplug.hotplug_work, 0); +} + static const struct drm_connector_funcs intel_dp_connector_funcs = { .force = intel_dp_force, .fill_modes = drm_helper_probe_single_connector_modes, @@ -5856,6 +5868,7 @@ static const struct drm_connector_funcs intel_dp_connector_funcs = { .destroy = intel_connector_destroy, .atomic_destroy_state = drm_atomic_helper_connector_destroy_state, .atomic_duplicate_state = intel_digital_connector_duplicate_state, + .oob_hotplug_event = intel_dp_oob_hotplug_event, }; static const struct drm_connector_helper_funcs intel_dp_connector_helper_funcs = { -- 2.31.1 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH 5/9] drm/i915: Associate ACPI connector nodes with connector entries
From: Heikki Krogerus On Intel platforms we know that the ACPI connector device node order will follow the order the driver (i915) decides. The decision is made using the custom Intel ACPI OpRegion (intel_opregion.c), though the driver does not actually know that the values it sends to ACPI there are used for associating a device node for the connectors, and assigning address for them. In reality that custom Intel ACPI OpRegion actually violates ACPI specification (we supply dynamic information to objects that are defined static, for example _ADR), however, it makes assigning correct connector node for a connector entry straightforward (it's one-on-one mapping). Signed-off-by: Heikki Krogerus [hdego...@redhat.com: Move intel_acpi_assign_connector_fwnodes() to intel_acpi.c] Signed-off-by: Hans de Goede --- drivers/gpu/drm/i915/display/intel_acpi.c| 40 drivers/gpu/drm/i915/display/intel_acpi.h| 3 ++ drivers/gpu/drm/i915/display/intel_display.c | 1 + 3 files changed, 44 insertions(+) diff --git a/drivers/gpu/drm/i915/display/intel_acpi.c b/drivers/gpu/drm/i915/display/intel_acpi.c index 833d0c1be4f1..9f266dfda7dd 100644 --- a/drivers/gpu/drm/i915/display/intel_acpi.c +++ b/drivers/gpu/drm/i915/display/intel_acpi.c @@ -263,3 +263,43 @@ void intel_acpi_device_id_update(struct drm_i915_private *dev_priv) } drm_connector_list_iter_end(&conn_iter); } + +/* NOTE: The connector order must be final before this is called. */ +void intel_acpi_assign_connector_fwnodes(struct drm_i915_private *i915) +{ + struct drm_connector_list_iter conn_iter; + struct drm_device *drm_dev = &i915->drm; + struct device *kdev = &drm_dev->pdev->dev; + struct fwnode_handle *fwnode = NULL; + struct drm_connector *connector; + struct acpi_device *adev; + + drm_connector_list_iter_begin(drm_dev, &conn_iter); + drm_for_each_connector_iter(connector, &conn_iter) { + /* Always getting the next, even when the last was not used. */ + fwnode = device_get_next_child_node(kdev, fwnode); + if (!fwnode) + break; + + switch (connector->connector_type) { + case DRM_MODE_CONNECTOR_LVDS: + case DRM_MODE_CONNECTOR_eDP: + case DRM_MODE_CONNECTOR_DSI: + /* +* Integrated displays have a specific address 0x1f on +* most Intel platforms, but not on all of them. +*/ + adev = acpi_find_child_device(ACPI_COMPANION(kdev), + 0x1f, 0); + if (adev) { + connector->fwnode = acpi_fwnode_handle(adev); + break; + } + fallthrough; + default: + connector->fwnode = fwnode; + break; + } + } + drm_connector_list_iter_end(&conn_iter); +} diff --git a/drivers/gpu/drm/i915/display/intel_acpi.h b/drivers/gpu/drm/i915/display/intel_acpi.h index e8b068661d22..d2435691f4b5 100644 --- a/drivers/gpu/drm/i915/display/intel_acpi.h +++ b/drivers/gpu/drm/i915/display/intel_acpi.h @@ -12,11 +12,14 @@ struct drm_i915_private; void intel_register_dsm_handler(void); void intel_unregister_dsm_handler(void); void intel_acpi_device_id_update(struct drm_i915_private *i915); +void intel_acpi_assign_connector_fwnodes(struct drm_i915_private *i915); #else static inline void intel_register_dsm_handler(void) { return; } static inline void intel_unregister_dsm_handler(void) { return; } static inline void intel_acpi_device_id_update(struct drm_i915_private *i915) { return; } +static inline +void intel_acpi_assign_connector_fwnodes(struct drm_i915_private *i915) { return; } #endif /* CONFIG_ACPI */ #endif /* __INTEL_ACPI_H__ */ diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index 828ef4c5625f..87cad549632c 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -14970,6 +14970,7 @@ int intel_modeset_init_nogem(struct drm_i915_private *i915) drm_modeset_lock_all(dev); intel_modeset_setup_hw_state(dev, dev->mode_config.acquire_ctx); + intel_acpi_assign_connector_fwnodes(i915); drm_modeset_unlock_all(dev); for_each_intel_crtc(dev, crtc) { -- 2.31.1 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH 7/9] usb: typec: altmodes/displayport: Make dp_altmode_notify() more generic
Make dp_altmode_notify() handle the dp->data.conf == 0 case too, rather then having separate code-paths for this in various places which call it. Signed-off-by: Hans de Goede --- drivers/usb/typec/altmodes/displayport.c | 35 +--- 1 file changed, 13 insertions(+), 22 deletions(-) diff --git a/drivers/usb/typec/altmodes/displayport.c b/drivers/usb/typec/altmodes/displayport.c index b7f094435b00..aa669b9cf70e 100644 --- a/drivers/usb/typec/altmodes/displayport.c +++ b/drivers/usb/typec/altmodes/displayport.c @@ -66,10 +66,17 @@ struct dp_altmode { static int dp_altmode_notify(struct dp_altmode *dp) { - u8 state = get_count_order(DP_CONF_GET_PIN_ASSIGN(dp->data.conf)); + unsigned long conf; + u8 state; + + if (dp->data.conf) { + state = get_count_order(DP_CONF_GET_PIN_ASSIGN(dp->data.conf)); + conf = TYPEC_MODAL_STATE(state); + } else { + conf = TYPEC_STATE_USB; + } - return typec_altmode_notify(dp->alt, TYPEC_MODAL_STATE(state), - &dp->data); + return typec_altmode_notify(dp->alt, conf, &dp->data); } static int dp_altmode_configure(struct dp_altmode *dp, u8 con) @@ -137,21 +144,10 @@ static int dp_altmode_status_update(struct dp_altmode *dp) static int dp_altmode_configured(struct dp_altmode *dp) { - int ret; - sysfs_notify(&dp->alt->dev.kobj, "displayport", "configuration"); - - if (!dp->data.conf) - return typec_altmode_notify(dp->alt, TYPEC_STATE_USB, - &dp->data); - - ret = dp_altmode_notify(dp); - if (ret) - return ret; - sysfs_notify(&dp->alt->dev.kobj, "displayport", "pin_assignment"); - return 0; + return dp_altmode_notify(dp); } static int dp_altmode_configure_vdm(struct dp_altmode *dp, u32 conf) @@ -172,13 +168,8 @@ static int dp_altmode_configure_vdm(struct dp_altmode *dp, u32 conf) } ret = typec_altmode_vdm(dp->alt, header, &conf, 2); - if (ret) { - if (DP_CONF_GET_PIN_ASSIGN(dp->data.conf)) - dp_altmode_notify(dp); - else - typec_altmode_notify(dp->alt, TYPEC_STATE_USB, -&dp->data); - } + if (ret) + dp_altmode_notify(dp); return ret; } -- 2.31.1 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH 8/9] usb: typec: altmodes/displayport: Notify drm subsys of hotplug events
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 --- 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 #include #include +#include #include #include +#include #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); -- 2.31.1 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH 9/9] platform/x86/intel_cht_int33fe: Correct "displayport" fwnode reference
The Type-C connector on these devices is connected to DP-2 not DP-1, so the reference must be to the DD04 child-node of the GPU, rather then the DD02 child-node. Signed-off-by: Hans de Goede --- drivers/platform/x86/intel_cht_int33fe_typec.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/platform/x86/intel_cht_int33fe_typec.c b/drivers/platform/x86/intel_cht_int33fe_typec.c index b61bad9cc8d2..d59544167430 100644 --- a/drivers/platform/x86/intel_cht_int33fe_typec.c +++ b/drivers/platform/x86/intel_cht_int33fe_typec.c @@ -168,8 +168,8 @@ static int cht_int33fe_setup_dp(struct cht_int33fe_data *data) return -ENODEV; } - /* Then the DP child device node */ - data->dp = device_get_named_child_node(&pdev->dev, "DD02"); + /* Then the DP-2 child device node */ + data->dp = device_get_named_child_node(&pdev->dev, "DD04"); pci_dev_put(pdev); if (!data->dp) return -ENODEV; -- 2.31.1 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
Re: [PATCH 3/9] drm/connector: Add drm_connector_find_by_fwnode() function (v2)
Hi, On 5/4/21 10:00 AM, Andy Shevchenko wrote: > > > On Monday, May 3, 2021, Hans de Goede <mailto:hdego...@redhat.com>> wrote: > > Add a function to find a connector based on a fwnode. > > This will be used by the new drm_connector_oob_hotplug_event() > function which is added by the next patch in this patch-set. > > Changes in v2: > - Complete rewrite to use a global connector list in drm_connector.c > rather then using a class-dev-iter in drm_sysfs.c > > Signed-off-by: Hans de Goede <mailto:hdego...@redhat.com>> > --- > drivers/gpu/drm/drm_connector.c | 50 + > drivers/gpu/drm/drm_crtc_internal.h | 1 + > include/drm/drm_connector.h | 8 + > 3 files changed, 59 insertions(+) > > diff --git a/drivers/gpu/drm/drm_connector.c > b/drivers/gpu/drm/drm_connector.c > index 87c68563e6c3..ef759d6add81 100644 > --- a/drivers/gpu/drm/drm_connector.c > +++ b/drivers/gpu/drm/drm_connector.c > @@ -66,6 +66,14 @@ > * support can instead use e.g. drm_helper_hpd_irq_event(). > */ > > +/* > + * Global connector list for drm_connector_find_by_fwnode(). > + * Note drm_connector_[un]register() first take connector->lock and then > + * take the connector_list_lock. > + */ > +static DEFINE_MUTEX(connector_list_lock); > +static LIST_HEAD(connector_list); > + > struct drm_conn_prop_enum_list { > int type; > const char *name; > @@ -267,6 +275,7 @@ int drm_connector_init(struct drm_device *dev, > goto out_put_type_id; > } > > + INIT_LIST_HEAD(&connector->global_connector_list_entry); > INIT_LIST_HEAD(&connector->probed_modes); > INIT_LIST_HEAD(&connector->modes); > mutex_init(&connector->mutex); > @@ -540,6 +549,9 @@ int drm_connector_register(struct drm_connector > *connector) > > drm_privacy_screen_register_notifier(connector->privacy_screen, > > &connector->privacy_screen_notifier); > > + mutex_lock(&connector_list_lock); > + list_add_tail(&connector->global_connector_list_entry, > &connector_list); > + mutex_unlock(&connector_list_lock); > goto unlock; > > err_debugfs: > @@ -568,6 +580,10 @@ void drm_connector_unregister(struct drm_connector > *connector) > return; > } > > + mutex_lock(&connector_list_lock); > + list_del_init(&connector->global_connector_list_entry); > + mutex_unlock(&connector_list_lock); > + > if (connector->privacy_screen) > drm_privacy_screen_unregister_notifier( > connector->privacy_screen, > @@ -2676,6 +2692,40 @@ int drm_mode_getconnector(struct drm_device *dev, > void *data, > return ret; > } > > +/** > + * drm_connector_find_by_fwnode - Find a connector based on the > associated fwnode > + * @fwnode: fwnode for which to find the matching drm_connector > + * > + * This functions looks up a drm_connector based on its associated > fwnode. When > + * a connector is found a reference to the connector is returned. The > caller must > + * call drm_connector_put() to release this reference when it is done > with the > + * connector. > + * > + * Returns: A reference to the found connector or an ERR_PTR(). > + */ > +struct drm_connector *drm_connector_find_by_fwnode(struct fwnode_handle > *fwnode) > +{ > + struct drm_connector *connector, *found = ERR_PTR(-ENODEV); > + > + if (!fwnode) > + return ERR_PTR(-ENODEV); > + > + mutex_lock(&connector_list_lock); > + > + list_for_each_entry(connector, &connector_list, > global_connector_list_entry) { > + if (connector->fwnode == fwnode || > + (connector->fwnode && connector->fwnode->secondary == > fwnode)) { > + drm_connector_get(connector); > + found = connector; > + break; > + } > + } > + > + mutex_unlock(&connector_list_lock); > + > + return found; > > > > If I am not mistaken you can replace this
Re: [PATCH 4/9] drm/connector: Add support for out-of-band hotplug notification
Hi, On 5/4/21 4:52 PM, Heikki Krogerus wrote: > On Mon, May 03, 2021 at 04:35:29PM +0200, Hans de Goede wrote: >> Hi, >> >> On 5/3/21 10:00 AM, Heikki Krogerus wrote: >>> Hi Hans, >>> >>> On Wed, Apr 28, 2021 at 11:52:52PM +0200, Hans de Goede wrote: >>>> +/** >>>> + * struct drm_connector_oob_hotplug_event_data: OOB hotplug event data >>>> + * >>>> + * Contains data about out-of-band hotplug events, signalled through >>>> + * drm_connector_oob_hotplug_event(). >>>> + */ >>>> +struct drm_connector_oob_hotplug_event_data { >>>> + /** >>>> + * @connected: New connected status for the connector. >>>> + */ >>>> + bool connected; >>>> + /** >>>> + * @dp_lanes: Number of available displayport lanes, 0 if unknown. >>>> + */ >>>> + int dp_lanes; >>>> + /** >>>> + * @orientation: Connector orientation. >>>> + */ >>>> + enum typec_orientation orientation; >>>> +}; >>> >>> I don't think the orientation is relevant. It will always be "normal" >>> from DP PoW after muxing, no? >> >> That is what I thought to, but during the discussion of my previous attempt >> at this one of the i915 devs mentioned that in some cases the muxes manage >> to swap the lane order when the connector upside-down and at least the >> Intel GPUs can correct for this on the GPU side, so they asked for this >> info to be included. >> >>> I'm also not sure those deatils are enough in the long run. Based on >>> what I've understood from our graphics team guys, for example knowing >>> if multi-function is preferred may be important in some cases. >> >> The current data being passed is just intended as a starting point, >> this is purely a kernel internal API so we can easily add more >> data to the struct. As I mentioned in the cover-letter the current >> oob_hotplug handler which the i915 patch adds to the i915 driver does >> not actually do anything with the data. ATM it is purely there to >> demonstrate that the ability to pass relevant data is there now >> (which was an issue with the previous attempt). I believe the current >> code is fine as a PoC of "pass event data" once GPU drivers actually >> start doing something with the data we can extend or outright replace >> it without issues. > > Ah, if there is nothing using that information yet, then just don't > pass it at all for now. As you said, it's kernel internal API, we can > change it later if needed. > >>> All of that, and more, is already available in the Configuration VDO >>> Status VDO that the we have negotiated with the DP partner. Both those >>> VDOs are part of struct typec_displayport_data. I think we should >>> simply supply that structure to the DRM code instead of picking those >>> details out of it... >> >> I'm not sure I like the idea of passing the raw VDO, but if the >> DRM folks think that would be useful we can certainly add it. > > Why are you against passing all the data that we have? What is the > benefit in picking only certain details out of an object that has a > standard format, and constructing a customised object for those > details instead? The VDO is Type-C specific and the drm_connector_oob_hotplug_event() is intended to be a generic API. There are other OOB event sources, e.g. the drivers/apci/acpi_video.c code receives hotplug events for connectors on powered-down GPUs on dual/hybrid GPU laptops. ATM the GPU drivers register an ACPI notifier to catch these; and there are no immediate plans to change this, but this does illustrate how OOB hotplug notification is not just a Type-C thing, where as the VDO and its format very much are Type-C things. Regards, Hans ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
Re: [PATCH 4/9] drm/connector: Add support for out-of-band hotplug notification (v2)
Hi, On 5/4/21 5:10 PM, Heikki Krogerus wrote: >> +/** >> + * drm_connector_oob_hotplug_event - Report out-of-band hotplug event to >> connector >> + * @connector: connector to report the event on >> + * @data: data related to the event >> + * >> + * On some hardware a hotplug event notification may come from outside the >> display >> + * driver / device. An example of this is some USB Type-C setups where the >> hardware >> + * muxes the DisplayPort data and aux-lines but does not pass the altmode >> HPD >> + * status bit to the GPU's DP HPD pin. >> + * >> + * This function can be used to report these out-of-band events after >> obtaining >> + * a drm_connector reference through calling drm_connector_find_by_fwnode(). >> + */ >> +void drm_connector_oob_hotplug_event(struct fwnode_handle *connector_fwnode, >> + struct >> drm_connector_oob_hotplug_event_data *data) >> +{ >> +struct drm_connector *connector; >> + >> +connector = drm_connector_find_by_fwnode(connector_fwnode); >> +if (IS_ERR(connector)) >> +return; >> + >> +if (connector->funcs->oob_hotplug_event) >> +connector->funcs->oob_hotplug_event(connector, data); >> + >> +drm_connector_put(connector); >> +} >> +EXPORT_SYMBOL(drm_connector_oob_hotplug_event); > > So it does looks like the "data" parameter is not needed at all: Well Imre did indicate that having the number of lanes is useful, so for the next version I'll drop the orientation but I plan to keep the number of lanes if that is ok with you. Not having passing along this info was one of the reasons why my previous attempt at this was nacked, so dropping it all together feels wrong. Regards, Hans ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
Re: [PATCH 5/9] drm/i915: Associate ACPI connector nodes with connector entries
Hi, On 5/4/21 9:52 AM, Andy Shevchenko wrote: > > > On Monday, May 3, 2021, Hans de Goede <mailto:hdego...@redhat.com>> wrote: > > From: Heikki Krogerus <mailto:heikki.kroge...@linux.intel.com>> > > On Intel platforms we know that the ACPI connector device > node order will follow the order the driver (i915) decides. > The decision is made using the custom Intel ACPI OpRegion > (intel_opregion.c), though the driver does not actually know > that the values it sends to ACPI there are used for > associating a device node for the connectors, and assigning > address for them. > > In reality that custom Intel ACPI OpRegion actually violates > ACPI specification (we supply dynamic information to objects > that are defined static, for example _ADR), however, it > makes assigning correct connector node for a connector entry > straightforward (it's one-on-one mapping). > > Signed-off-by: Heikki Krogerus <mailto:heikki.kroge...@linux.intel.com>> > [hdego...@redhat.com <mailto:hdego...@redhat.com>: Move > intel_acpi_assign_connector_fwnodes() to > intel_acpi.c] > Signed-off-by: Hans de Goede <mailto:hdego...@redhat.com>> > --- > drivers/gpu/drm/i915/display/intel_acpi.c | 40 > drivers/gpu/drm/i915/display/intel_acpi.h | 3 ++ > drivers/gpu/drm/i915/display/intel_display.c | 1 + > 3 files changed, 44 insertions(+) > > diff --git a/drivers/gpu/drm/i915/display/intel_acpi.c > b/drivers/gpu/drm/i915/display/intel_acpi.c > index 833d0c1be4f1..9f266dfda7dd 100644 > --- a/drivers/gpu/drm/i915/display/intel_acpi.c > +++ b/drivers/gpu/drm/i915/display/intel_acpi.c > @@ -263,3 +263,43 @@ void intel_acpi_device_id_update(struct > drm_i915_private *dev_priv) > } > drm_connector_list_iter_end(&conn_iter); > } > + > +/* NOTE: The connector order must be final before this is called. */ > +void intel_acpi_assign_connector_fwnodes(struct drm_i915_private *i915) > +{ > + struct drm_connector_list_iter conn_iter; > + struct drm_device *drm_dev = &i915->drm; > + struct device *kdev = &drm_dev->pdev->dev; > + struct fwnode_handle *fwnode = NULL; > + struct drm_connector *connector; > + struct acpi_device *adev; > + > + drm_connector_list_iter_begin(drm_dev, &conn_iter); > + drm_for_each_connector_iter(connector, &conn_iter) { > + /* Always getting the next, even when the last was not > used. */ > + fwnode = device_get_next_child_node(kdev, fwnode); > + if (!fwnode) > + break; > > > > Who is dropping reference counting on fwnode ? We are dealing with ACPI fwnode-s here and those are not ref-counted, they are embedded inside a struct acpi_device and their lifetime is tied to that struct. They should probably still be ref-counted (with the count never dropping to 0) so that the generic fwnode functions behave the same anywhere but atm the ACPI nodes are not refcounted, see: acpi_get_next_subnode() in drivers/acpi/property.c which is the get_next_child_node() implementation for ACPI fwnode-s. > I’m in the middle of a pile of fixes for fwnode refcounting when > for_each_child or get_next_child is used. So, please double check you drop a > reference. The kdoc comments on device_get_next_child_node() / fwnode_get_next_child_node() do not mention anything about these functions returning a reference. So I think we need to first make up our mind here how we want this all to work and then fix the actual implementation and docs before fixing callers. Regards, Hans > > > + > + switch (connector->connector_type) { > + case DRM_MODE_CONNECTOR_LVDS: > + case DRM_MODE_CONNECTOR_eDP: > + case DRM_MODE_CONNECTOR_DSI: > + /* > + * Integrated displays have a specific address > 0x1f on > + * most Intel platforms, but not on all of them. > + */ > + adev = > acpi_find_child_device(ACPI_COMPANION(kdev), > + 0x1f, 0); > + if (adev) { > + connector->fwnode = > acpi_fwnode_handle(adev); > + break; > + } > + fallthrough; > +
Re: [PATCH 5/9] drm/i915: Associate ACPI connector nodes with connector entries
Hi, On 5/5/21 11:17 AM, Andy Shevchenko wrote: > On Wed, May 5, 2021 at 12:07 PM Hans de Goede wrote: >> On 5/4/21 9:52 AM, Andy Shevchenko wrote: >>> On Monday, May 3, 2021, Hans de Goede >> <mailto:hdego...@redhat.com>> wrote: > > ... > >>> + fwnode = device_get_next_child_node(kdev, fwnode); > >>> Who is dropping reference counting on fwnode ? >> >> We are dealing with ACPI fwnode-s here and those are not ref-counted, they >> are embedded inside a struct acpi_device and their lifetime is tied to >> that struct. They should probably still be ref-counted (with the count >> never dropping to 0) so that the generic fwnode functions behave the same >> anywhere but atm the ACPI nodes are not refcounted, see: >> acpi_get_next_subnode() >> in drivers/acpi/property.c which is the get_next_child_node() implementation >> for ACPI fwnode-s. > > Yes, ACPI currently is exceptional, but fwnode API is not. > If you may guarantee that this case won't ever be outside of ACPI Yes I can guarantee that currently this code (which is for the i915 driver only) only deals with ACPI fwnodes. > and > even though if ACPI won't ever gain a reference counting for fwnodes, > we can leave it as is. Would it not be better to add fake ref-counting to the ACPI fwnode next_child_node() op though. I believe just getting a reference on the return value there should work fine; and then all fwnode implementations would be consistent ? (note I did not check that the of and swnode code do return a reference but I would assume so). >>> I’m in the middle of a pile of fixes for fwnode refcounting when >>> for_each_child or get_next_child is used. So, please double check you drop >>> a reference. >> >> The kdoc comments on device_get_next_child_node() / >> fwnode_get_next_child_node() >> do not mention anything about these functions returning a reference. > > It's possible. I dunno if it had to be done earlier. Sakari? > >> So I think we need to first make up our mind here how we want this all to >> work and then fix the actual implementation and docs before fixing callers. > > We have already issues, so I prefer not to wait for a documentation > update, because for old kernels it will still be an issue. I wonder if we really have issues though, in practice fwnodes are generated from an devicetree or ACPI tables (or by platform codes adding swnodes) and then these pretty much stick around for ever. IOW the initial refcount of 1 is never dropped at least for of-nodes and ACPI nodes. I know there are some exceptions like device-tree overlays which I guess may also be dynamically removed again, but those exceptions are not widely used. And if we forget to drop a reference in the worst case we have a small non-re-occuring (so not growing) memleak. Where as if we start adding put() calls everywhere we may end up freeing things which are still in use; or dropping refcounts below 0 triggering WARNs in various places (IIRC). So it seems the cure is potentially worse then the disease in this case. So if you want to work on this, then IMHO it would be best to first make sure that all the fwnode implementations behave in the same way wrt ref-counting, before adding the missing put() calls in various places. And once the behavior is consistent then we can also document this properly making it easier for other people to do the right thing when using these functions. Regards, Hans ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel