Re: [PATCH 10/10] drm/i915: Add privacy-screen support (v3)

2021-11-17 Thread Hans de Goede
Hi Rajat,

On 11/17/21 14:59, Rajat Jain wrote:
> Hello Hans,
> 
> I'm working on my platform's privacy-screen support based on your
> patches, and had some (I know late) questions. Would be great if you
> could please help answer. Please see inline.
> 
> On Tue, Oct 5, 2021 at 1:25 PM Hans de Goede  wrote:
>>
>> Add support for eDP panels with a built-in privacy screen using the
>> new drm_privacy_screen class.
>>
>> Changes in v3:
>> - Move drm_privacy_screen_get() call to intel_ddi_init_dp_connector()
>>
>> Changes in v2:
>> - Call drm_connector_update_privacy_screen() from
>>   intel_enable_ddi_dp() / intel_ddi_update_pipe_dp() instead of adding a
>>   for_each_new_connector_in_state() loop to intel_atomic_commit_tail()
>> - Move the probe-deferral check to the intel_modeset_probe_defer() helper
>>
>> Signed-off-by: Hans de Goede 
>> ---
>>  drivers/gpu/drm/i915/display/intel_atomic.c  |  1 +
>>  drivers/gpu/drm/i915/display/intel_ddi.c | 16 
>>  drivers/gpu/drm/i915/display/intel_display.c | 10 ++
>>  3 files changed, 27 insertions(+)
>>
>> diff --git a/drivers/gpu/drm/i915/display/intel_atomic.c 
>> b/drivers/gpu/drm/i915/display/intel_atomic.c
>> index b4e7ac51aa31..a62550711e98 100644
>> --- a/drivers/gpu/drm/i915/display/intel_atomic.c
>> +++ b/drivers/gpu/drm/i915/display/intel_atomic.c
>> @@ -139,6 +139,7 @@ int intel_digital_connector_atomic_check(struct 
>> drm_connector *conn,
>> new_conn_state->base.picture_aspect_ratio != 
>> old_conn_state->base.picture_aspect_ratio ||
>> new_conn_state->base.content_type != 
>> old_conn_state->base.content_type ||
>> new_conn_state->base.scaling_mode != 
>> old_conn_state->base.scaling_mode ||
>> +   new_conn_state->base.privacy_screen_sw_state != 
>> old_conn_state->base.privacy_screen_sw_state ||
>> !drm_connector_atomic_hdr_metadata_equal(old_state, new_state))
>> crtc_state->mode_changed = true;
>>
>> diff --git a/drivers/gpu/drm/i915/display/intel_ddi.c 
>> b/drivers/gpu/drm/i915/display/intel_ddi.c
>> index 0d4cf7fa8720..272714e07cc6 100644
>> --- a/drivers/gpu/drm/i915/display/intel_ddi.c
>> +++ b/drivers/gpu/drm/i915/display/intel_ddi.c
>> @@ -25,6 +25,7 @@
>>   *
>>   */
>>
>> +#include 
>>  #include 
>>
>>  #include "i915_drv.h"
>> @@ -2946,6 +2947,7 @@ static void intel_enable_ddi_dp(struct 
>> intel_atomic_state *state,
>> if (port == PORT_A && DISPLAY_VER(dev_priv) < 9)
>> intel_dp_stop_link_train(intel_dp, crtc_state);
>>
>> +   drm_connector_update_privacy_screen(conn_state);
>> intel_edp_backlight_on(crtc_state, conn_state);
>>
>> if (!dig_port->lspcon.active || dig_port->dp.has_hdmi_sink)
>> @@ -3161,6 +3163,7 @@ static void intel_ddi_update_pipe_dp(struct 
>> intel_atomic_state *state,
>> intel_drrs_update(intel_dp, crtc_state);
>>
>> intel_backlight_update(state, encoder, crtc_state, conn_state);
>> +   drm_connector_update_privacy_screen(conn_state);
>>  }
>>
>>  void intel_ddi_update_pipe(struct intel_atomic_state *state,
>> @@ -3979,6 +3982,19 @@ intel_ddi_init_dp_connector(struct intel_digital_port 
>> *dig_port)
>> return NULL;
>> }
>>
>> +   if (dig_port->base.type == INTEL_OUTPUT_EDP) {
>> +   struct drm_device *dev = dig_port->base.base.dev;
>> +   struct drm_privacy_screen *privacy_screen;
>> +
>> +   privacy_screen = drm_privacy_screen_get(dev->dev, NULL);
> 
> Why pass NULL for con_id? Can we pass something more meaningful (e.g.
> "eDP-1") so that the non-KMS platform components that provide the
> privacy-screen can provide a more specific lookup? Or is that
> information (connector name) not available at the time this call is
> being made?

For the x86 ACPI case it does not matter because the static lookups
added by drivers/gpu/drm/drm_privacy_screen_x86.c do not set
a con_id in the lookup and if the lookup lack a con_id then
the value passed to drm_privacy_screen_get() is a no-op.

So, if it helps you to pass a connector-name then go for it.

As for the connecter_name already being set at this point,
I don't know, you need to check.

But also see below.

>> +   if (!IS_ERR(privacy_screen)) {
>> +   
>> drm_connector_attach_privacy_screen_provider(>base,
>> +   

[PATCH] drm: panel-orientation-quirks: Add quirk for the Lenovo Yoga Book X91F/L

2021-11-06 Thread Hans de Goede
The Lenovo Yoga Book X91F/L uses a panel which has been mounted
90 degrees rotated. Add a quirk for this.

Cc: Yauhen Kharuzhy 
Signed-off-by: Hans de Goede 
---
 drivers/gpu/drm/drm_panel_orientation_quirks.c | 6 ++
 1 file changed, 6 insertions(+)

diff --git a/drivers/gpu/drm/drm_panel_orientation_quirks.c 
b/drivers/gpu/drm/drm_panel_orientation_quirks.c
index d92b9408fe48..2cced702d225 100644
--- a/drivers/gpu/drm/drm_panel_orientation_quirks.c
+++ b/drivers/gpu/drm/drm_panel_orientation_quirks.c
@@ -262,6 +262,12 @@ static const struct dmi_system_id orientation_data[] = {
  DMI_EXACT_MATCH(DMI_PRODUCT_VERSION, "Lenovo ideapad 
D330-10IGM"),
},
.driver_data = (void *)_rightside_up,
+   }, {/* Lenovo Yoga Book X90F / X91F / X91L */
+   .matches = {
+ /* Non exact match to match all versions */
+ DMI_MATCH(DMI_PRODUCT_NAME, "Lenovo YB1-X9"),
+   },
+   .driver_data = (void *)_rightside_up,
}, {/* OneGX1 Pro */
.matches = {
  DMI_EXACT_MATCH(DMI_SYS_VENDOR, "SYSTEM_MANUFACTURER"),
-- 
2.31.1



Re: [PATCH 10/10] drm/i915: Add privacy-screen support (v3)

2021-11-04 Thread Hans de Goede
Hi,

On 11/4/21 00:16, Rajat Jain wrote:
> Hello Hans,
> 
> Thanks a lot for working on this diligently and getting almost all of
> it finally merged!
> 
> On Wed, Oct 13, 2021 at 2:59 PM Ville Syrjälä
>  wrote:
>>
>> On Tue, Oct 05, 2021 at 10:23:22PM +0200, Hans de Goede wrote:
>>> Add support for eDP panels with a built-in privacy screen using the
>>> new drm_privacy_screen class.
>>>
>>> Changes in v3:
>>> - Move drm_privacy_screen_get() call to intel_ddi_init_dp_connector()
>>>
>>> Changes in v2:
>>> - Call drm_connector_update_privacy_screen() from
>>>   intel_enable_ddi_dp() / intel_ddi_update_pipe_dp() instead of adding a
>>>   for_each_new_connector_in_state() loop to intel_atomic_commit_tail()
>>> - Move the probe-deferral check to the intel_modeset_probe_defer() helper
>>>
>>> Signed-off-by: Hans de Goede 
>>> ---
>>>  drivers/gpu/drm/i915/display/intel_atomic.c  |  1 +
>>>  drivers/gpu/drm/i915/display/intel_ddi.c | 16 
>>>  drivers/gpu/drm/i915/display/intel_display.c | 10 ++
>>>  3 files changed, 27 insertions(+)
>>>
>>> diff --git a/drivers/gpu/drm/i915/display/intel_atomic.c 
>>> b/drivers/gpu/drm/i915/display/intel_atomic.c
>>> index b4e7ac51aa31..a62550711e98 100644
>>> --- a/drivers/gpu/drm/i915/display/intel_atomic.c
>>> +++ b/drivers/gpu/drm/i915/display/intel_atomic.c
>>> @@ -139,6 +139,7 @@ int intel_digital_connector_atomic_check(struct 
>>> drm_connector *conn,
>>>   new_conn_state->base.picture_aspect_ratio != 
>>> old_conn_state->base.picture_aspect_ratio ||
>>>   new_conn_state->base.content_type != 
>>> old_conn_state->base.content_type ||
>>>   new_conn_state->base.scaling_mode != 
>>> old_conn_state->base.scaling_mode ||
>>> + new_conn_state->base.privacy_screen_sw_state != 
>>> old_conn_state->base.privacy_screen_sw_state ||
>>>   !drm_connector_atomic_hdr_metadata_equal(old_state, new_state))
>>>   crtc_state->mode_changed = true;
>>>
>>> diff --git a/drivers/gpu/drm/i915/display/intel_ddi.c 
>>> b/drivers/gpu/drm/i915/display/intel_ddi.c
>>> index 0d4cf7fa8720..272714e07cc6 100644
>>> --- a/drivers/gpu/drm/i915/display/intel_ddi.c
>>> +++ b/drivers/gpu/drm/i915/display/intel_ddi.c
>>> @@ -25,6 +25,7 @@
>>>   *
>>>   */
>>>
>>> +#include 
>>>  #include 
>>>
>>>  #include "i915_drv.h"
>>> @@ -2946,6 +2947,7 @@ static void intel_enable_ddi_dp(struct 
>>> intel_atomic_state *state,
>>>   if (port == PORT_A && DISPLAY_VER(dev_priv) < 9)
>>>   intel_dp_stop_link_train(intel_dp, crtc_state);
>>>
>>> + drm_connector_update_privacy_screen(conn_state);
>>>   intel_edp_backlight_on(crtc_state, conn_state);
>>>
>>>   if (!dig_port->lspcon.active || dig_port->dp.has_hdmi_sink)
>>> @@ -3161,6 +3163,7 @@ static void intel_ddi_update_pipe_dp(struct 
>>> intel_atomic_state *state,
>>>   intel_drrs_update(intel_dp, crtc_state);
>>>
>>>   intel_backlight_update(state, encoder, crtc_state, conn_state);
>>> + drm_connector_update_privacy_screen(conn_state);
>>>  }
>>>
>>>  void intel_ddi_update_pipe(struct intel_atomic_state *state,
>>> @@ -3979,6 +3982,19 @@ intel_ddi_init_dp_connector(struct 
>>> intel_digital_port *dig_port)
>>>   return NULL;
>>>   }
>>>
>>> + if (dig_port->base.type == INTEL_OUTPUT_EDP) {
>>
>> Connector type check would be a bit more consistent with what this is
>> about I think. But there's is 1:1 correspondence with the encoder type
>> for eDP so not a particularly important point.
>>
>> Reviewed-by: Ville Syrjälä 
> 
> I see only 8 out of 10 patches in this series were applied to drm-tip.
> I'm curious if there is any reason for which the last 2 patches were
> not applied:
> 
> [Patch 9/10]: drm/i915: Add intel_modeset_probe_defer() helper
> [Patch 10/10]: drm/i915: Add privacy-screen support (v3)
> 
> I look forward to getting them merged so that I can use them.

The main-parts of the patch-set were merged through drm-misc-next,
the 2 i915 patches had a conflict there since the series was
based on drm-tip and some of the surrounding i915 code had some
small changes in drm-intel-next which was not in drm-misc

Re: [PATCH v2 3/3] backlight: lp855x: Add support ACPI enumeration

2021-11-04 Thread Hans de Goede
Hi,

On 11/4/21 09:29, Lee Jones wrote:
> On Wed, 03 Nov 2021, Daniel Thompson wrote:
> 
>> On Wed, Nov 03, 2021 at 06:28:15PM +0100, Hans de Goede wrote:
>>> Hi,
>>>
>>> On 11/3/21 18:17, Daniel Thompson wrote:
>>>> On Tue, Nov 02, 2021 at 11:55:04PM +0100, Hans de Goede wrote:
>>>>> The Xiaomi Mi Pad 2 tablet uses an ACPI enumerated LP8556 backlight
>>>>> controller for its LCD-panel, with a Xiaomi specific ACPI HID of
>>>>> "XMCC0001", add support for this.
>>>>>
>>>>> Note the new "if (id)" check also fixes a NULL pointer deref when a user
>>>>> tries to manually bind the driver from sysfs.
>>>>>
>>>>> When CONFIG_ACPI is disabled acpi_match_device() will always return NULL,
>>>>> so the lp855x_parse_acpi() call will get optimized away.
>>>>>
>>>>> Signed-off-by: Hans de Goede 
>>>>
>>>> Reviewed-by: Daniel Thompson 
>>>
>>> Thank you.
>>>
>>> So what is the process for upstreaming backlight patches,
>>> do these go through drm-misc-next (in that case I can push
>>> the series myself), or will you pick these up ?
>>
>> Lee Jones gathers up the backlight patches and sends a PR (but, except
>> in exceptional cases, treats my R-b as a pre-requisite before doing so).
> 
> Also the merge-window is open, so this is headed for v5.17.

Right, I didn't expect anything else.

Regards,

Hans



Re: [PATCH v2 3/3] backlight: lp855x: Add support ACPI enumeration

2021-11-03 Thread Hans de Goede
Hi,

On 11/3/21 18:31, Daniel Thompson wrote:
> On Wed, Nov 03, 2021 at 06:28:15PM +0100, Hans de Goede wrote:
>> Hi,
>>
>> On 11/3/21 18:17, Daniel Thompson wrote:
>>> On Tue, Nov 02, 2021 at 11:55:04PM +0100, Hans de Goede wrote:
>>>> The Xiaomi Mi Pad 2 tablet uses an ACPI enumerated LP8556 backlight
>>>> controller for its LCD-panel, with a Xiaomi specific ACPI HID of
>>>> "XMCC0001", add support for this.
>>>>
>>>> Note the new "if (id)" check also fixes a NULL pointer deref when a user
>>>> tries to manually bind the driver from sysfs.
>>>>
>>>> When CONFIG_ACPI is disabled acpi_match_device() will always return NULL,
>>>> so the lp855x_parse_acpi() call will get optimized away.
>>>>
>>>> Signed-off-by: Hans de Goede 
>>>
>>> Reviewed-by: Daniel Thompson 
>>
>> Thank you.
>>
>> So what is the process for upstreaming backlight patches,
>> do these go through drm-misc-next (in that case I can push
>> the series myself), or will you pick these up ?
> 
> Lee Jones gathers up the backlight patches and sends a PR (but, except
> in exceptional cases, treats my R-b as a pre-requisite before doing so).

Ok, thanks.

Regards,

Hans



Re: [PATCH v2 3/3] backlight: lp855x: Add support ACPI enumeration

2021-11-03 Thread Hans de Goede
Hi,

On 11/3/21 18:17, Daniel Thompson wrote:
> On Tue, Nov 02, 2021 at 11:55:04PM +0100, Hans de Goede wrote:
>> The Xiaomi Mi Pad 2 tablet uses an ACPI enumerated LP8556 backlight
>> controller for its LCD-panel, with a Xiaomi specific ACPI HID of
>> "XMCC0001", add support for this.
>>
>> Note the new "if (id)" check also fixes a NULL pointer deref when a user
>> tries to manually bind the driver from sysfs.
>>
>> When CONFIG_ACPI is disabled acpi_match_device() will always return NULL,
>> so the lp855x_parse_acpi() call will get optimized away.
>>
>> Signed-off-by: Hans de Goede 
> 
> Reviewed-by: Daniel Thompson 

Thank you.

So what is the process for upstreaming backlight patches,
do these go through drm-misc-next (in that case I can push
the series myself), or will you pick these up ?

Regards,

Hans



[PATCH v2 3/3] backlight: lp855x: Add support ACPI enumeration

2021-11-02 Thread Hans de Goede
The Xiaomi Mi Pad 2 tablet uses an ACPI enumerated LP8556 backlight
controller for its LCD-panel, with a Xiaomi specific ACPI HID of
"XMCC0001", add support for this.

Note the new "if (id)" check also fixes a NULL pointer deref when a user
tries to manually bind the driver from sysfs.

When CONFIG_ACPI is disabled acpi_match_device() will always return NULL,
so the lp855x_parse_acpi() call will get optimized away.

Signed-off-by: Hans de Goede 
---
Changes in v2:
- Remove `lp->pdata = pdata` assignment from lp855x_parse_dt()
- Add "and is in register mode" to the comment in
  lp855x_parse_acpi()
---
 drivers/video/backlight/lp855x_bl.c | 73 -
 1 file changed, 61 insertions(+), 12 deletions(-)

diff --git a/drivers/video/backlight/lp855x_bl.c 
b/drivers/video/backlight/lp855x_bl.c
index d1d27d5eb0f2..2b9e203e 100644
--- a/drivers/video/backlight/lp855x_bl.c
+++ b/drivers/video/backlight/lp855x_bl.c
@@ -5,6 +5,7 @@
  * Copyright (C) 2011 Texas Instruments
  */
 
+#include 
 #include 
 #include 
 #include 
@@ -330,7 +331,7 @@ static int lp855x_parse_dt(struct lp855x *lp)
 {
struct device *dev = lp->dev;
struct device_node *node = dev->of_node;
-   struct lp855x_platform_data *pdata;
+   struct lp855x_platform_data *pdata = lp->pdata;
int rom_length;
 
if (!node) {
@@ -338,10 +339,6 @@ static int lp855x_parse_dt(struct lp855x *lp)
return -EINVAL;
}
 
-   pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
-   if (!pdata)
-   return -ENOMEM;
-
of_property_read_string(node, "bl-name", >name);
of_property_read_u8(node, "dev-ctrl", >device_control);
of_property_read_u8(node, "init-brt", >initial_brightness);
@@ -368,8 +365,6 @@ static int lp855x_parse_dt(struct lp855x *lp)
pdata->rom_data = [0];
}
 
-   lp->pdata = pdata;
-
return 0;
 }
 #else
@@ -379,8 +374,32 @@ static int lp855x_parse_dt(struct lp855x *lp)
 }
 #endif
 
+static int lp855x_parse_acpi(struct lp855x *lp)
+{
+   int ret;
+
+   /*
+* On ACPI the device has already been initialized by the firmware
+* and is in register mode, so we can read back the settings from
+* the registers.
+*/
+   ret = i2c_smbus_read_byte_data(lp->client, lp->cfg->reg_brightness);
+   if (ret < 0)
+   return ret;
+
+   lp->pdata->initial_brightness = ret;
+
+   ret = i2c_smbus_read_byte_data(lp->client, lp->cfg->reg_devicectrl);
+   if (ret < 0)
+   return ret;
+
+   lp->pdata->device_control = ret;
+   return 0;
+}
+
 static int lp855x_probe(struct i2c_client *cl, const struct i2c_device_id *id)
 {
+   const struct acpi_device_id *acpi_id = NULL;
struct device *dev = >dev;
struct lp855x *lp;
int ret;
@@ -394,10 +413,20 @@ static int lp855x_probe(struct i2c_client *cl, const 
struct i2c_device_id *id)
 
lp->client = cl;
lp->dev = dev;
-   lp->chipname = id->name;
-   lp->chip_id = id->driver_data;
lp->pdata = dev_get_platdata(dev);
 
+   if (id) {
+   lp->chipname = id->name;
+   lp->chip_id = id->driver_data;
+   } else {
+   acpi_id = acpi_match_device(dev->driver->acpi_match_table, dev);
+   if (!acpi_id)
+   return -ENODEV;
+
+   lp->chipname = acpi_id->id;
+   lp->chip_id = acpi_id->driver_data;
+   }
+
switch (lp->chip_id) {
case LP8550:
case LP8551:
@@ -415,9 +444,19 @@ static int lp855x_probe(struct i2c_client *cl, const 
struct i2c_device_id *id)
}
 
if (!lp->pdata) {
-   ret = lp855x_parse_dt(lp);
-   if (ret < 0)
-   return ret;
+   lp->pdata = devm_kzalloc(dev, sizeof(*lp->pdata), GFP_KERNEL);
+   if (!lp->pdata)
+   return -ENOMEM;
+
+   if (id) {
+   ret = lp855x_parse_dt(lp);
+   if (ret < 0)
+   return ret;
+   } else {
+   ret = lp855x_parse_acpi(lp);
+   if (ret < 0)
+   return ret;
+   }
}
 
if (lp->pdata->period_ns > 0)
@@ -537,10 +576,20 @@ static const struct i2c_device_id lp855x_ids[] = {
 };
 MODULE_DEVICE_TABLE(i2c, lp855x_ids);
 
+#ifdef CONFIG_ACPI
+static const struct acpi_device_id lp855x_acpi_match[] = {
+   /* Xiaomi specific HID used for the LP8556 on the Mi Pad 2 */
+   { "XMCC0001", LP8556 },
+   { }
+};
+MODULE_DEVICE_TABLE(acpi, lp855x_acpi_match);
+#en

[PATCH v2 1/3] backlight: lp855x: Move device_config setting out of lp855x_configure()

2021-11-02 Thread Hans de Goede
Move the setting of the lp->cfg pointer to the chip specific
lp855x_device_config struct from lp855x_configure() to
lp855x_probe(), before calling lp855x_parse_dt().

This is a preperation patch for adding ACPI enumeration support.

Reviewed-by: Daniel Thompson 
Signed-off-by: Hans de Goede 
---
 drivers/video/backlight/lp855x_bl.c | 32 ++---
 1 file changed, 16 insertions(+), 16 deletions(-)

diff --git a/drivers/video/backlight/lp855x_bl.c 
b/drivers/video/backlight/lp855x_bl.c
index e94932c69f54..808ff00b2003 100644
--- a/drivers/video/backlight/lp855x_bl.c
+++ b/drivers/video/backlight/lp855x_bl.c
@@ -170,22 +170,6 @@ static int lp855x_configure(struct lp855x *lp)
int i, ret;
struct lp855x_platform_data *pd = lp->pdata;
 
-   switch (lp->chip_id) {
-   case LP8550:
-   case LP8551:
-   case LP8552:
-   case LP8553:
-   case LP8556:
-   lp->cfg = _dev_cfg;
-   break;
-   case LP8555:
-   case LP8557:
-   lp->cfg = _dev_cfg;
-   break;
-   default:
-   return -EINVAL;
-   }
-
if (lp->cfg->pre_init_device) {
ret = lp->cfg->pre_init_device(lp);
if (ret) {
@@ -413,6 +397,22 @@ static int lp855x_probe(struct i2c_client *cl, const 
struct i2c_device_id *id)
lp->chip_id = id->driver_data;
lp->pdata = dev_get_platdata(>dev);
 
+   switch (lp->chip_id) {
+   case LP8550:
+   case LP8551:
+   case LP8552:
+   case LP8553:
+   case LP8556:
+   lp->cfg = _dev_cfg;
+   break;
+   case LP8555:
+   case LP8557:
+   lp->cfg = _dev_cfg;
+   break;
+   default:
+   return -EINVAL;
+   }
+
if (!lp->pdata) {
ret = lp855x_parse_dt(lp);
if (ret < 0)
-- 
2.31.1



[PATCH v2 2/3] backlight: lp855x: Add dev helper variable to lp855x_probe()

2021-11-02 Thread Hans de Goede
Add a dev local variable to the lp855x_probe(), to replace ">dev"
and "lp->dev" in various places.

Also switch to dev_err_probe() in one case which takes care of not
printing -EPROBE_DEFER errors for us.

This is mostly a preparation for adding ACPI enumeration support which
will use the new "dev" variable more.

Reviewed-by: Daniel Thompson 
Signed-off-by: Hans de Goede 
---
 drivers/video/backlight/lp855x_bl.c | 29 +
 1 file changed, 13 insertions(+), 16 deletions(-)

diff --git a/drivers/video/backlight/lp855x_bl.c 
b/drivers/video/backlight/lp855x_bl.c
index 808ff00b2003..d1d27d5eb0f2 100644
--- a/drivers/video/backlight/lp855x_bl.c
+++ b/drivers/video/backlight/lp855x_bl.c
@@ -381,21 +381,22 @@ static int lp855x_parse_dt(struct lp855x *lp)
 
 static int lp855x_probe(struct i2c_client *cl, const struct i2c_device_id *id)
 {
+   struct device *dev = >dev;
struct lp855x *lp;
int ret;
 
if (!i2c_check_functionality(cl->adapter, I2C_FUNC_SMBUS_I2C_BLOCK))
return -EIO;
 
-   lp = devm_kzalloc(>dev, sizeof(struct lp855x), GFP_KERNEL);
+   lp = devm_kzalloc(dev, sizeof(struct lp855x), GFP_KERNEL);
if (!lp)
return -ENOMEM;
 
lp->client = cl;
-   lp->dev = >dev;
+   lp->dev = dev;
lp->chipname = id->name;
lp->chip_id = id->driver_data;
-   lp->pdata = dev_get_platdata(>dev);
+   lp->pdata = dev_get_platdata(dev);
 
switch (lp->chip_id) {
case LP8550:
@@ -424,30 +425,27 @@ static int lp855x_probe(struct i2c_client *cl, const 
struct i2c_device_id *id)
else
lp->mode = REGISTER_BASED;
 
-   lp->supply = devm_regulator_get(lp->dev, "power");
+   lp->supply = devm_regulator_get(dev, "power");
if (IS_ERR(lp->supply)) {
if (PTR_ERR(lp->supply) == -EPROBE_DEFER)
return -EPROBE_DEFER;
lp->supply = NULL;
}
 
-   lp->enable = devm_regulator_get_optional(lp->dev, "enable");
+   lp->enable = devm_regulator_get_optional(dev, "enable");
if (IS_ERR(lp->enable)) {
ret = PTR_ERR(lp->enable);
if (ret == -ENODEV) {
lp->enable = NULL;
} else {
-   if (ret != -EPROBE_DEFER)
-   dev_err(lp->dev, "error getting enable 
regulator: %d\n",
-   ret);
-   return ret;
+   return dev_err_probe(dev, ret, "getting enable 
regulator\n");
}
}
 
if (lp->supply) {
ret = regulator_enable(lp->supply);
if (ret < 0) {
-   dev_err(>dev, "failed to enable supply: %d\n", ret);
+   dev_err(dev, "failed to enable supply: %d\n", ret);
return ret;
}
}
@@ -455,7 +453,7 @@ static int lp855x_probe(struct i2c_client *cl, const struct 
i2c_device_id *id)
if (lp->enable) {
ret = regulator_enable(lp->enable);
if (ret < 0) {
-   dev_err(lp->dev, "failed to enable vddio: %d\n", ret);
+   dev_err(dev, "failed to enable vddio: %d\n", ret);
goto disable_supply;
}
 
@@ -470,20 +468,19 @@ static int lp855x_probe(struct i2c_client *cl, const 
struct i2c_device_id *id)
 
ret = lp855x_configure(lp);
if (ret) {
-   dev_err(lp->dev, "device config err: %d", ret);
+   dev_err(dev, "device config err: %d", ret);
goto disable_vddio;
}
 
ret = lp855x_backlight_register(lp);
if (ret) {
-   dev_err(lp->dev,
-   "failed to register backlight. err: %d\n", ret);
+   dev_err(dev, "failed to register backlight. err: %d\n", ret);
goto disable_vddio;
}
 
-   ret = sysfs_create_group(>dev->kobj, _attr_group);
+   ret = sysfs_create_group(>kobj, _attr_group);
if (ret) {
-   dev_err(lp->dev, "failed to register sysfs. err: %d\n", ret);
+   dev_err(dev, "failed to register sysfs. err: %d\n", ret);
goto disable_vddio;
}
 
-- 
2.31.1



Re: [PATCH 3/3] backlight: lp855x: Add support ACPI enumeration

2021-11-02 Thread Hans de Goede
Hi Daniel,

Thank you for the quick review of this series.

On 11/2/21 13:22, Daniel Thompson wrote:
> On Mon, Nov 01, 2021 at 07:55:17PM +0100, Hans de Goede wrote:
>> The Xiaomi Mi Pad 2 tablet uses an ACPI enumerated LP8556 backlight
>> controller for its LCD-panel, with a Xiaomi specific ACPI HID of
>> "XMCC0001", add support for this.
>>
>> Note the new "if (id)" check also fixes a NULL pointer deref when a user
>> tries to manually bind the driver from sysfs.
>>
>> When CONFIG_ACPI is disabled acpi_match_device() will always return NULL,
>> so the lp855x_parse_acpi() call will get optimized away.
>>
>> Signed-off-by: Hans de Goede 
>> ---
>>  drivers/video/backlight/lp855x_bl.c | 70 -
>>  1 file changed, 60 insertions(+), 10 deletions(-)
>>
>> diff --git a/drivers/video/backlight/lp855x_bl.c 
>> b/drivers/video/backlight/lp855x_bl.c
>> index d1d27d5eb0f2..f075ec84acfb 100644
>> --- a/drivers/video/backlight/lp855x_bl.c
>> +++ b/drivers/video/backlight/lp855x_bl.c
>> @@ -338,10 +339,6 @@ static int lp855x_parse_dt(struct lp855x *lp)
>>  return -EINVAL;
>>  }
>>  
>> -pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
>> -if (!pdata)
>> -return -ENOMEM;
>> -
>>  of_property_read_string(node, "bl-name", >name);
>>  of_property_read_u8(node, "dev-ctrl", >device_control);
>>  of_property_read_u8(node, "init-brt", >initial_brightness);
> 
> Shouldn't there be a removal of an `lp->pdata = pdata` from somewhere in
> this function?

Ack, fixed for v2.

>> @@ -379,8 +376,31 @@ static int lp855x_parse_dt(struct lp855x *lp)
>>  }
>>  #endif
>>  
>> +static int lp855x_parse_acpi(struct lp855x *lp)
>> +{
>> +int ret;
>> +
>> +/*
>> + * On ACPI the device has already been initialized by the firmware
> 
> Perhaps nitpicking but ideally I'd like "and is in register mode" here 
> since I presume it can also be assumed that everything with this HID
> has adopted that).

Nope not nitpicking, that is a good point, also fixed for v2.

Regards,

Hans



[PATCH 2/3] backlight: lp855x: Add dev helper variable to lp855x_probe()

2021-11-01 Thread Hans de Goede
Add a dev local variable to the lp855x_probe(), to replace ">dev"
and "lp->dev" in various places.

Also switch to dev_err_probe() in one case which takes care of not
printing -EPROBE_DEFER errors for us.

This is mostly a preparation for adding ACPI enumeration support which
will use the new "dev" variable more.

Signed-off-by: Hans de Goede 
---
 drivers/video/backlight/lp855x_bl.c | 29 +
 1 file changed, 13 insertions(+), 16 deletions(-)

diff --git a/drivers/video/backlight/lp855x_bl.c 
b/drivers/video/backlight/lp855x_bl.c
index 808ff00b2003..d1d27d5eb0f2 100644
--- a/drivers/video/backlight/lp855x_bl.c
+++ b/drivers/video/backlight/lp855x_bl.c
@@ -381,21 +381,22 @@ static int lp855x_parse_dt(struct lp855x *lp)
 
 static int lp855x_probe(struct i2c_client *cl, const struct i2c_device_id *id)
 {
+   struct device *dev = >dev;
struct lp855x *lp;
int ret;
 
if (!i2c_check_functionality(cl->adapter, I2C_FUNC_SMBUS_I2C_BLOCK))
return -EIO;
 
-   lp = devm_kzalloc(>dev, sizeof(struct lp855x), GFP_KERNEL);
+   lp = devm_kzalloc(dev, sizeof(struct lp855x), GFP_KERNEL);
if (!lp)
return -ENOMEM;
 
lp->client = cl;
-   lp->dev = >dev;
+   lp->dev = dev;
lp->chipname = id->name;
lp->chip_id = id->driver_data;
-   lp->pdata = dev_get_platdata(>dev);
+   lp->pdata = dev_get_platdata(dev);
 
switch (lp->chip_id) {
case LP8550:
@@ -424,30 +425,27 @@ static int lp855x_probe(struct i2c_client *cl, const 
struct i2c_device_id *id)
else
lp->mode = REGISTER_BASED;
 
-   lp->supply = devm_regulator_get(lp->dev, "power");
+   lp->supply = devm_regulator_get(dev, "power");
if (IS_ERR(lp->supply)) {
if (PTR_ERR(lp->supply) == -EPROBE_DEFER)
return -EPROBE_DEFER;
lp->supply = NULL;
}
 
-   lp->enable = devm_regulator_get_optional(lp->dev, "enable");
+   lp->enable = devm_regulator_get_optional(dev, "enable");
if (IS_ERR(lp->enable)) {
ret = PTR_ERR(lp->enable);
if (ret == -ENODEV) {
lp->enable = NULL;
} else {
-   if (ret != -EPROBE_DEFER)
-   dev_err(lp->dev, "error getting enable 
regulator: %d\n",
-   ret);
-   return ret;
+   return dev_err_probe(dev, ret, "getting enable 
regulator\n");
}
}
 
if (lp->supply) {
ret = regulator_enable(lp->supply);
if (ret < 0) {
-   dev_err(>dev, "failed to enable supply: %d\n", ret);
+   dev_err(dev, "failed to enable supply: %d\n", ret);
return ret;
}
}
@@ -455,7 +453,7 @@ static int lp855x_probe(struct i2c_client *cl, const struct 
i2c_device_id *id)
if (lp->enable) {
ret = regulator_enable(lp->enable);
if (ret < 0) {
-   dev_err(lp->dev, "failed to enable vddio: %d\n", ret);
+   dev_err(dev, "failed to enable vddio: %d\n", ret);
goto disable_supply;
}
 
@@ -470,20 +468,19 @@ static int lp855x_probe(struct i2c_client *cl, const 
struct i2c_device_id *id)
 
ret = lp855x_configure(lp);
if (ret) {
-   dev_err(lp->dev, "device config err: %d", ret);
+   dev_err(dev, "device config err: %d", ret);
goto disable_vddio;
}
 
ret = lp855x_backlight_register(lp);
if (ret) {
-   dev_err(lp->dev,
-   "failed to register backlight. err: %d\n", ret);
+   dev_err(dev, "failed to register backlight. err: %d\n", ret);
goto disable_vddio;
}
 
-   ret = sysfs_create_group(>dev->kobj, _attr_group);
+   ret = sysfs_create_group(>kobj, _attr_group);
if (ret) {
-   dev_err(lp->dev, "failed to register sysfs. err: %d\n", ret);
+   dev_err(dev, "failed to register sysfs. err: %d\n", ret);
goto disable_vddio;
}
 
-- 
2.31.1



[PATCH 3/3] backlight: lp855x: Add support ACPI enumeration

2021-11-01 Thread Hans de Goede
The Xiaomi Mi Pad 2 tablet uses an ACPI enumerated LP8556 backlight
controller for its LCD-panel, with a Xiaomi specific ACPI HID of
"XMCC0001", add support for this.

Note the new "if (id)" check also fixes a NULL pointer deref when a user
tries to manually bind the driver from sysfs.

When CONFIG_ACPI is disabled acpi_match_device() will always return NULL,
so the lp855x_parse_acpi() call will get optimized away.

Signed-off-by: Hans de Goede 
---
 drivers/video/backlight/lp855x_bl.c | 70 -
 1 file changed, 60 insertions(+), 10 deletions(-)

diff --git a/drivers/video/backlight/lp855x_bl.c 
b/drivers/video/backlight/lp855x_bl.c
index d1d27d5eb0f2..f075ec84acfb 100644
--- a/drivers/video/backlight/lp855x_bl.c
+++ b/drivers/video/backlight/lp855x_bl.c
@@ -5,6 +5,7 @@
  * Copyright (C) 2011 Texas Instruments
  */
 
+#include 
 #include 
 #include 
 #include 
@@ -330,7 +331,7 @@ static int lp855x_parse_dt(struct lp855x *lp)
 {
struct device *dev = lp->dev;
struct device_node *node = dev->of_node;
-   struct lp855x_platform_data *pdata;
+   struct lp855x_platform_data *pdata = lp->pdata;
int rom_length;
 
if (!node) {
@@ -338,10 +339,6 @@ static int lp855x_parse_dt(struct lp855x *lp)
return -EINVAL;
}
 
-   pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
-   if (!pdata)
-   return -ENOMEM;
-
of_property_read_string(node, "bl-name", >name);
of_property_read_u8(node, "dev-ctrl", >device_control);
of_property_read_u8(node, "init-brt", >initial_brightness);
@@ -379,8 +376,31 @@ static int lp855x_parse_dt(struct lp855x *lp)
 }
 #endif
 
+static int lp855x_parse_acpi(struct lp855x *lp)
+{
+   int ret;
+
+   /*
+* On ACPI the device has already been initialized by the firmware
+* so we read back the settings from the registers.
+*/
+   ret = i2c_smbus_read_byte_data(lp->client, lp->cfg->reg_brightness);
+   if (ret < 0)
+   return ret;
+
+   lp->pdata->initial_brightness = ret;
+
+   ret = i2c_smbus_read_byte_data(lp->client, lp->cfg->reg_devicectrl);
+   if (ret < 0)
+   return ret;
+
+   lp->pdata->device_control = ret;
+   return 0;
+}
+
 static int lp855x_probe(struct i2c_client *cl, const struct i2c_device_id *id)
 {
+   const struct acpi_device_id *acpi_id = NULL;
struct device *dev = >dev;
struct lp855x *lp;
int ret;
@@ -394,10 +414,20 @@ static int lp855x_probe(struct i2c_client *cl, const 
struct i2c_device_id *id)
 
lp->client = cl;
lp->dev = dev;
-   lp->chipname = id->name;
-   lp->chip_id = id->driver_data;
lp->pdata = dev_get_platdata(dev);
 
+   if (id) {
+   lp->chipname = id->name;
+   lp->chip_id = id->driver_data;
+   } else {
+   acpi_id = acpi_match_device(dev->driver->acpi_match_table, dev);
+   if (!acpi_id)
+   return -ENODEV;
+
+   lp->chipname = acpi_id->id;
+   lp->chip_id = acpi_id->driver_data;
+   }
+
switch (lp->chip_id) {
case LP8550:
case LP8551:
@@ -415,9 +445,19 @@ static int lp855x_probe(struct i2c_client *cl, const 
struct i2c_device_id *id)
}
 
if (!lp->pdata) {
-   ret = lp855x_parse_dt(lp);
-   if (ret < 0)
-   return ret;
+   lp->pdata = devm_kzalloc(dev, sizeof(*lp->pdata), GFP_KERNEL);
+   if (!lp->pdata)
+   return -ENOMEM;
+
+   if (id) {
+   ret = lp855x_parse_dt(lp);
+   if (ret < 0)
+   return ret;
+   } else {
+   ret = lp855x_parse_acpi(lp);
+   if (ret < 0)
+   return ret;
+   }
}
 
if (lp->pdata->period_ns > 0)
@@ -537,10 +577,20 @@ static const struct i2c_device_id lp855x_ids[] = {
 };
 MODULE_DEVICE_TABLE(i2c, lp855x_ids);
 
+#ifdef CONFIG_ACPI
+static const struct acpi_device_id lp855x_acpi_match[] = {
+   /* Xiaomi specific HID used for the LP8556 on the Mi Pad 2 */
+   { "XMCC0001", LP8556 },
+   { }
+};
+MODULE_DEVICE_TABLE(acpi, lp855x_acpi_match);
+#endif
+
 static struct i2c_driver lp855x_driver = {
.driver = {
   .name = "lp855x",
   .of_match_table = of_match_ptr(lp855x_dt_ids),
+  .acpi_match_table = ACPI_PTR(lp855x_acpi_match),
   },
.probe = lp855x_probe,
.remove = lp855x_remove,
-- 
2.31.1



[PATCH 1/3] backlight: lp855x: Move device_config setting out of lp855x_configure()

2021-11-01 Thread Hans de Goede
Move the setting of the lp->cfg pointer to the chip specific
lp855x_device_config struct from lp855x_configure() to
lp855x_probe(), before calling lp855x_parse_dt().

This is a preperation patch for adding ACPI enumeration support.

Signed-off-by: Hans de Goede 
---
 drivers/video/backlight/lp855x_bl.c | 32 ++---
 1 file changed, 16 insertions(+), 16 deletions(-)

diff --git a/drivers/video/backlight/lp855x_bl.c 
b/drivers/video/backlight/lp855x_bl.c
index e94932c69f54..808ff00b2003 100644
--- a/drivers/video/backlight/lp855x_bl.c
+++ b/drivers/video/backlight/lp855x_bl.c
@@ -170,22 +170,6 @@ static int lp855x_configure(struct lp855x *lp)
int i, ret;
struct lp855x_platform_data *pd = lp->pdata;
 
-   switch (lp->chip_id) {
-   case LP8550:
-   case LP8551:
-   case LP8552:
-   case LP8553:
-   case LP8556:
-   lp->cfg = _dev_cfg;
-   break;
-   case LP8555:
-   case LP8557:
-   lp->cfg = _dev_cfg;
-   break;
-   default:
-   return -EINVAL;
-   }
-
if (lp->cfg->pre_init_device) {
ret = lp->cfg->pre_init_device(lp);
if (ret) {
@@ -413,6 +397,22 @@ static int lp855x_probe(struct i2c_client *cl, const 
struct i2c_device_id *id)
lp->chip_id = id->driver_data;
lp->pdata = dev_get_platdata(>dev);
 
+   switch (lp->chip_id) {
+   case LP8550:
+   case LP8551:
+   case LP8552:
+   case LP8553:
+   case LP8556:
+   lp->cfg = _dev_cfg;
+   break;
+   case LP8555:
+   case LP8557:
+   lp->cfg = _dev_cfg;
+   break;
+   default:
+   return -EINVAL;
+   }
+
if (!lp->pdata) {
ret = lp855x_parse_dt(lp);
if (ret < 0)
-- 
2.31.1



Re: [PATCH] drm/i915: Add NO_VLV_DISP_PW_DPIO_CMN_BC_INIT quirk

2021-10-27 Thread Hans de Goede
Hi,

On 10/27/21 15:38, Ville Syrjälä wrote:
> On Sun, Oct 24, 2021 at 05:50:10PM +0200, Hans de Goede wrote:
>> Add a NO_VLV_DISP_PW_DPIO_CMN_BC_INIT quirk to fix i915 not working on
>> the Xiaomi Mi Pad 2 (with CHT x5-Z8500 SoC).
>>
>> The Xiaomi Mi Pad 2 uses quite an unusual hardware-design for a Cherry
>> Trail tablet. It deviates from the typical reference design based tablets
>> in many ways.
>>
>> The Mi Pad 2 does not have any DisplayPort or HDMI outouts. I suspect that
>> as part of its unusual design it also has some supply rail which is only
>> used for DisplayPort or HDMI not connected.
> 
> Do we have the VBT somewhere (preferable attached to a bug report)?
> Maybe we can avoid an ugly quirk.

I agree that solving this in a way where we can avoid the quirk would be great.

I've filed an issue for this here now:

https://gitlab.freedesktop.org/drm/intel/-/issues/4385

This has a dump of /sys/kernel/debug/dri/0/i915_vbt as well as
dmesg output from a boot with drm.debug=0x1e attached (from a boot
with this patch, since otherwise the system hangs).

>>
>> Force-enabling the dpio-common-bc powerwell as the i915 normal does at boot
>> appears to cause the P-Unit to hang. When booting with a serial-usb console
>> the following errors are logged before the system freezes:
>>
>>  i915 :00:02.0: [drm] *ERROR* timeout setting power well state  
>> (f3ff)
>>  i915 :00:02.0: [drm] *ERROR* Display PHY 0 is not power up
> 
> Hmm. I wonder if we're missing a clock or something...
> 
> Either of these do anything different?
> 
> --- a/drivers/gpu/drm/i915/display/intel_display_power.c
> +++ b/drivers/gpu/drm/i915/display/intel_display_power.c
> @@ -1419,6 +1419,10 @@ static void vlv_display_power_well_init(struct 
> drm_i915_private *dev_priv)
>   for_each_pipe(dev_priv, pipe) {
>   u32 val = intel_de_read(dev_priv, DPLL(pipe));
>  
> + val |= DPLL_SSC_REF_CLK_CHV;
>   or
> + val &= ~DPLL_SSC_REF_CLK_CHV;
> 
>   val |= DPLL_REF_CLK_ENABLE_VLV | DPLL_VGA_MODE_DIS;
>   if (pipe != PIPE_A)
>   val |= DPLL_INTEGRATED_CRI_CLK_VLV;
> 

The hang gets triggered from chv_dpio_cmn_power_well_enable() which does not
call vlv_display_power_well_init() at all, it directly calls 
vlv_set_power_well()
without first calling vlv_display_power_well_init() .

Note the same goes for vlv_dpio_cmn_power_well_enable(). Only the
vlv_display_power_well_enable() / chv_pipe_power_well_enable() call
vlv_display_power_well_init().

Note I can still give the suggested change a try if you want,
the "display" powerwell is listed first and has DOMAIN_INIT set,
so assuming for_each_power_domain_well() goes through the domains in
the order they are listed, then vlv_display_power_well_init() will
still run first. But it would seem to be wrong if enabling one domain
depends on things setup by another domain ?

Regards,

Hans



Re: [PATCH] drm/i915: Add NO_VLV_DISP_PW_DPIO_CMN_BC_INIT quirk

2021-10-25 Thread Hans de Goede
Hi,

On 10/25/21 10:25, Jani Nikula wrote:
> On Sun, 24 Oct 2021, Hans de Goede  wrote:
>> Add a NO_VLV_DISP_PW_DPIO_CMN_BC_INIT quirk to fix i915 not working on
>> the Xiaomi Mi Pad 2 (with CHT x5-Z8500 SoC).
>>
>> The Xiaomi Mi Pad 2 uses quite an unusual hardware-design for a Cherry
>> Trail tablet. It deviates from the typical reference design based tablets
>> in many ways.
>>
>> The Mi Pad 2 does not have any DisplayPort or HDMI outouts. I suspect that
>> as part of its unusual design it also has some supply rail which is only
>> used for DisplayPort or HDMI not connected.
>>
>> Force-enabling the dpio-common-bc powerwell as the i915 normal does at boot
>> appears to cause the P-Unit to hang. When booting with a serial-usb console
>> the following errors are logged before the system freezes:
>>
>>  i915 :00:02.0: [drm] *ERROR* timeout setting power well state  
>> (f3ff)
>>  i915 :00:02.0: [drm] *ERROR* Display PHY 0 is not power up
>>  [ cut here ]
>>  i915 :00:02.0: DPIO read pipe A reg 0x8170 == 0x
>>  WARNING: CPU: 3 PID: 258 at drivers/gpu/drm/i915/intel_sideband.c:257 
>> vlv_dpio_read+0x95/0xb0 [i915]
>>  ...
>>  Call Trace:
>>   chv_dpio_cmn_power_well_enable+0xab/0x210 [i915]
>>   __intel_display_power_get_domain.part.0+0xa0/0xc0 [i915]
>>   intel_power_domains_init_hw+0x26d/0x760 [i915]
>>   intel_modeset_init_noirq+0x5d/0x270 [i915]
>>   i915_driver_probe+0x6b6/0xd10 [i915]
>>   ...
>>
>> If I disable the WARN about the register being 0x, so that the
>> system can log some more dmesg output over the serial console before
>> freezing, the following errors are also logged:
>>
>>  i915 :00:02.0: [drm] *ERROR* timeout setting power well state  
>> (fcfff3ff)
>>  i915 :00:02.0: [drm] *ERROR* Display PHY 1 is not power up
>>
>> With this patch to disable the force-enabling of the PHY 0 / dpio-common-bc
>> powerwell in place, this error for PHY 1 goes away. So it seems that trying
>> the force-enabling of the PHY 0 / dpio-common-bc powerwell freezes the
>> P-Unit, causing the subsequent enabling of PHY 1 to also fail (and causing
>> the entire system to freeze within seconds).
>>
>> With this patch the PHY 1 error disappears and the entire system works.
>>
>> Note this change also moves the intel_init_quirks() call a bit up inside
>> intel_modeset_init_noirq() this is necessary so that the quirk is set
>> before the intel_power_domains_init_hw() call. This is harmless, all that
>> intel_init_quirks() does is set some bits in drm_i915_private.quirks and
>> make some drm_info() log calls.
>>
>> Reported-by: Tsuchiya Yuto 
>> Signed-off-by: Hans de Goede 
>> ---
>>  drivers/gpu/drm/i915/display/intel_display.c |  4 ++--
>>  .../gpu/drm/i915/display/intel_display_power.c   | 16 ++--
>>  drivers/gpu/drm/i915/display/intel_quirks.c  | 10 ++
>>  drivers/gpu/drm/i915/i915_drv.h  |  1 +
>>  4 files changed, 27 insertions(+), 4 deletions(-)
>>
>> diff --git a/drivers/gpu/drm/i915/display/intel_display.c 
>> b/drivers/gpu/drm/i915/display/intel_display.c
>> index 015854b5078c..1fb885cc86c9 100644
>> --- a/drivers/gpu/drm/i915/display/intel_display.c
>> +++ b/drivers/gpu/drm/i915/display/intel_display.c
>> @@ -12467,6 +12467,8 @@ int intel_modeset_init_noirq(struct drm_i915_private 
>> *i915)
>>  if (ret)
>>  goto cleanup_bios;
>>  
>> +intel_init_quirks(i915);
>> +
>>  /* FIXME: completely on the wrong abstraction layer */
>>  intel_power_domains_init_hw(i915, false);
>>  
>> @@ -12501,8 +12503,6 @@ int intel_modeset_init_noirq(struct drm_i915_private 
>> *i915)
>>  INIT_WORK(>atomic_helper.free_work,
>>intel_atomic_helper_free_state_worker);
>>  
>> -intel_init_quirks(i915);
>> -
>>  intel_fbc_init(i915);
>>  
>>  return 0;
>> diff --git a/drivers/gpu/drm/i915/display/intel_display_power.c 
>> b/drivers/gpu/drm/i915/display/intel_display_power.c
>> index cce1a926fcc1..eeaba3dc064b 100644
>> --- a/drivers/gpu/drm/i915/display/intel_display_power.c
>> +++ b/drivers/gpu/drm/i915/display/intel_display_power.c
>> @@ -2090,8 +2090,14 @@ __intel_display_power_get_domain(struct 
>> drm_i915_private *dev_priv,
>>  if (intel_display_power_grab_async_put_ref(dev_priv, domain))
>>  return;
>>  
>> -for_each_power_domain_well(dev_priv, 

[PATCH] drm/i915/vlv_dsi: Double pixelclock on read-back for dual-link panels

2021-10-24 Thread Hans de Goede
In intel_dsi_get_config() double the pclk returned by foo_dsi_get_pclk()
for dual-link panels. This fixes the following WARN triggering:

 i915 :00:02.0: [drm] *ERROR* [CRTC:51:pipe A] mismatch in pixel_rate 
(expected 235710, found 118056)
 i915 :00:02.0: [drm] *ERROR* [CRTC:51:pipe A] mismatch in 
hw.pipe_mode.crtc_clock (expected 235710, found 118056)
 i915 :00:02.0: [drm] *ERROR* [CRTC:51:pipe A] mismatch in 
hw.adjusted_mode.crtc_clock (expected 235710, found 118056)
 i915 :00:02.0: [drm] *ERROR* [CRTC:51:pipe A] mismatch in port_clock 
(expected 235710, found 118056)
 [ cut here ]
 pipe state doesn't match!
 WARNING: CPU: 3 PID: 136 at drivers/gpu/drm/i915/display/intel_display.c:9125 
intel_display_finish_reset+0x1bd3/0x2050 [i915]
 ...

This has been tested on a Xiaomi Mi Pad 2 (with CHT x5-Z8500 SoC) tablet,
with a 1536x2048 dual-link DSI panel.

Note this fix was taken from icl_dsi.c which does the same in
its get_config().

Cc: Tsuchiya Yuto 
Signed-off-by: Hans de Goede 
---
 drivers/gpu/drm/i915/display/vlv_dsi.c | 5 +
 1 file changed, 5 insertions(+)

diff --git a/drivers/gpu/drm/i915/display/vlv_dsi.c 
b/drivers/gpu/drm/i915/display/vlv_dsi.c
index 3e646a58b38a..2b7909bc52ff 100644
--- a/drivers/gpu/drm/i915/display/vlv_dsi.c
+++ b/drivers/gpu/drm/i915/display/vlv_dsi.c
@@ -1265,7 +1265,9 @@ static void intel_dsi_get_config(struct intel_encoder 
*encoder,
 struct intel_crtc_state *pipe_config)
 {
struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
+   struct intel_dsi *intel_dsi = enc_to_intel_dsi(encoder);
u32 pclk;
+
drm_dbg_kms(_priv->drm, "\n");
 
pipe_config->output_types |= BIT(INTEL_OUTPUT_DSI);
@@ -1277,6 +1279,9 @@ static void intel_dsi_get_config(struct intel_encoder 
*encoder,
pclk = vlv_dsi_get_pclk(encoder, pipe_config);
}
 
+   if (intel_dsi->dual_link)
+   pclk *= 2;
+
if (pclk) {
pipe_config->hw.adjusted_mode.crtc_clock = pclk;
pipe_config->port_clock = pclk;
-- 
2.31.1



[PATCH] drm/i915: Add NO_VLV_DISP_PW_DPIO_CMN_BC_INIT quirk

2021-10-24 Thread Hans de Goede
Add a NO_VLV_DISP_PW_DPIO_CMN_BC_INIT quirk to fix i915 not working on
the Xiaomi Mi Pad 2 (with CHT x5-Z8500 SoC).

The Xiaomi Mi Pad 2 uses quite an unusual hardware-design for a Cherry
Trail tablet. It deviates from the typical reference design based tablets
in many ways.

The Mi Pad 2 does not have any DisplayPort or HDMI outouts. I suspect that
as part of its unusual design it also has some supply rail which is only
used for DisplayPort or HDMI not connected.

Force-enabling the dpio-common-bc powerwell as the i915 normal does at boot
appears to cause the P-Unit to hang. When booting with a serial-usb console
the following errors are logged before the system freezes:

 i915 :00:02.0: [drm] *ERROR* timeout setting power well state  
(f3ff)
 i915 :00:02.0: [drm] *ERROR* Display PHY 0 is not power up
 [ cut here ]
 i915 :00:02.0: DPIO read pipe A reg 0x8170 == 0x
 WARNING: CPU: 3 PID: 258 at drivers/gpu/drm/i915/intel_sideband.c:257 
vlv_dpio_read+0x95/0xb0 [i915]
 ...
 Call Trace:
  chv_dpio_cmn_power_well_enable+0xab/0x210 [i915]
  __intel_display_power_get_domain.part.0+0xa0/0xc0 [i915]
  intel_power_domains_init_hw+0x26d/0x760 [i915]
  intel_modeset_init_noirq+0x5d/0x270 [i915]
  i915_driver_probe+0x6b6/0xd10 [i915]
  ...

If I disable the WARN about the register being 0x, so that the
system can log some more dmesg output over the serial console before
freezing, the following errors are also logged:

 i915 :00:02.0: [drm] *ERROR* timeout setting power well state  
(fcfff3ff)
 i915 :00:02.0: [drm] *ERROR* Display PHY 1 is not power up

With this patch to disable the force-enabling of the PHY 0 / dpio-common-bc
powerwell in place, this error for PHY 1 goes away. So it seems that trying
the force-enabling of the PHY 0 / dpio-common-bc powerwell freezes the
P-Unit, causing the subsequent enabling of PHY 1 to also fail (and causing
the entire system to freeze within seconds).

With this patch the PHY 1 error disappears and the entire system works.

Note this change also moves the intel_init_quirks() call a bit up inside
intel_modeset_init_noirq() this is necessary so that the quirk is set
before the intel_power_domains_init_hw() call. This is harmless, all that
intel_init_quirks() does is set some bits in drm_i915_private.quirks and
make some drm_info() log calls.

Reported-by: Tsuchiya Yuto 
Signed-off-by: Hans de Goede 
---
 drivers/gpu/drm/i915/display/intel_display.c |  4 ++--
 .../gpu/drm/i915/display/intel_display_power.c   | 16 ++--
 drivers/gpu/drm/i915/display/intel_quirks.c  | 10 ++
 drivers/gpu/drm/i915/i915_drv.h  |  1 +
 4 files changed, 27 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_display.c 
b/drivers/gpu/drm/i915/display/intel_display.c
index 015854b5078c..1fb885cc86c9 100644
--- a/drivers/gpu/drm/i915/display/intel_display.c
+++ b/drivers/gpu/drm/i915/display/intel_display.c
@@ -12467,6 +12467,8 @@ int intel_modeset_init_noirq(struct drm_i915_private 
*i915)
if (ret)
goto cleanup_bios;
 
+   intel_init_quirks(i915);
+
/* FIXME: completely on the wrong abstraction layer */
intel_power_domains_init_hw(i915, false);
 
@@ -12501,8 +12503,6 @@ int intel_modeset_init_noirq(struct drm_i915_private 
*i915)
INIT_WORK(>atomic_helper.free_work,
  intel_atomic_helper_free_state_worker);
 
-   intel_init_quirks(i915);
-
intel_fbc_init(i915);
 
return 0;
diff --git a/drivers/gpu/drm/i915/display/intel_display_power.c 
b/drivers/gpu/drm/i915/display/intel_display_power.c
index cce1a926fcc1..eeaba3dc064b 100644
--- a/drivers/gpu/drm/i915/display/intel_display_power.c
+++ b/drivers/gpu/drm/i915/display/intel_display_power.c
@@ -2090,8 +2090,14 @@ __intel_display_power_get_domain(struct drm_i915_private 
*dev_priv,
if (intel_display_power_grab_async_put_ref(dev_priv, domain))
return;
 
-   for_each_power_domain_well(dev_priv, power_well, BIT_ULL(domain))
+   for_each_power_domain_well(dev_priv, power_well, BIT_ULL(domain)) {
+   if (domain == POWER_DOMAIN_INIT &&
+   (dev_priv->quirks & QUIRK_NO_VLV_DISP_PW_DPIO_CMN_BC_INIT) 
&&
+   power_well->desc->id == VLV_DISP_PW_DPIO_CMN_BC)
+   continue;
+
intel_power_well_get(dev_priv, power_well);
+   }
 
power_domains->domain_use_count[domain]++;
 }
@@ -2184,8 +2190,14 @@ __intel_display_power_put_domain(struct drm_i915_private 
*dev_priv,
 
power_domains->domain_use_count[domain]--;
 
-   for_each_power_domain_well_reverse(dev_priv, power_well, 
BIT_ULL(domain))
+   for_each_power_domain_well_reverse(dev_priv, power_well, 
BIT_ULL(domain)) {
+   if (domain == POWER_DOMAIN_INIT &&
+   (dev_priv-&

Re: [Intel-gfx] [PULL] drm-misc-next

2021-10-14 Thread Hans de Goede
Hi,

On 10/14/21 3:24 PM, Hans de Goede wrote:
> Hi,
> 
> On 10/14/21 2:04 PM, Maxime Ripard wrote:
>> Hi Dave, Daniel,
>>
>> Here's this week drm-misc-next PR
>>
>> Maxime
>>
>> drm-misc-next-2021-10-14:
>> drm-misc-next for 5.16:
> 
> Ugh, this just missed the drm-privacy-screen work which I just pushed
> out to drm-misc-next (I was waiting for the last i915 integration patch
> to get reviewed).
> 
> It would be nice if we can still get the drm-privacy-screen work
> included into 5.16. But if it is too late I understand.

Thinking more about this, delaying this till 5.17 is fine, that
will nicely align its release with GNOME42 which will be the
first userspace to support this; and it will give it a nice long
time to find any issues in -next (not that I expect any).

Regards,

Hans


>> UAPI Changes:
>>
>> Cross-subsystem Changes:
>>
>> Core Changes:
>>   - fbdev: Fix double-free, Remove unused scrolling acceleration
>>   - locking: improve logging for contented locks without backoff
>>   - dma-buf: Add dma_resv_for_each_fence iterator, and conversion of
>> users
>>
>> Driver Changes:
>>   - nouveau: Various code style improvements
>>   - bridge: HPD improvements for lt9611uxc, eDP aux-bus support for
>> ps8640, lvds-codec data-mapping selection support
>>   - panels: Vivax TPC-9150, Innolux G070Y2-T02, LOGIC Technologies
>> LTTD800480070-L2RT, Sharp LS060T1SX01,
>> The following changes since commit 9962601ca5719050906915c3c33a63744ac7b15c:
>>
>>   drm/bridge: dw-hdmi-cec: Make use of the helper function 
>> devm_add_action_or_reset() (2021-10-06 11:21:46 +0200)
>>
>> are available in the Git repository at:
>>
>>   git://anongit.freedesktop.org/drm/drm-misc tags/drm-misc-next-2021-10-14
>>
>> for you to fetch changes up to b3ec8cdf457e5e63d396fe1346cc788cf7c1b578:
>>
>>   fbdev: Garbage collect fbdev scrolling acceleration, part 1 (from TODO 
>> list) (2021-10-13 15:29:23 +0200)
>>
>> 
>> drm-misc-next for 5.16:
>>
>> UAPI Changes:
>>
>> Cross-subsystem Changes:
>>
>> Core Changes:
>>   - fbdev: Fix double-free, Remove unused scrolling acceleration
>>   - locking: improve logging for contented locks without backoff
>>   - dma-buf: Add dma_resv_for_each_fence iterator, and conversion of
>> users
>>
>> Driver Changes:
>>   - nouveau: Various code style improvements
>>   - bridge: HPD improvements for lt9611uxc, eDP aux-bus support for
>> ps8640, lvds-codec data-mapping selection support
>>   - panels: Vivax TPC-9150, Innolux G070Y2-T02, LOGIC Technologies
>> LTTD800480070-L2RT, Sharp LS060T1SX01,
>>
>> 
>> Alex Xu (Hello71) (1):
>>   drm/plane-helper: fix uninitialized variable reference
>>
>> Amos Kong (1):
>>   drm/ttm_bo_api: update the description for @placement and @sg
>>
>> Christian König (7):
>>   dma-buf: add dma_resv_for_each_fence v3
>>   dma-buf: use the new iterator in dma_buf_debug_show
>>   dma-buf: use the new iterator in dma_resv_poll
>>   drm/ttm: use the new iterator in ttm_bo_flush_all_fences
>>   drm/scheduler: use new iterator in 
>> drm_sched_job_add_implicit_dependencies v2
>>   drm/i915: use the new iterator in i915_request_await_object v2
>>   drm: use new iterator in drm_gem_fence_array_add_implicit v3
>>
>> Claudio Suarez (1):
>>   fbdev: Garbage collect fbdev scrolling acceleration, part 1 (from TODO 
>> list)
>>
>> Dan Carpenter (1):
>>   drm/v3d: fix copy_from_user() error codes
>>
>> David Heidelberg (1):
>>   dt-bindings: display: simple: hardware can use ddc-i2c-bus
>>
>> Dmitry Baryshkov (5):
>>   drm/bridge/lontium-lt9611uxc: fix provided connector suport
>>   dt-bindings: add bindings for the Sharp LS060T1SX01 panel
>>   drm/panel: Add support for Sharp LS060T1SX01 panel
>>   dt-bindings: add bindings for the Sharp LS060T1SX01 panel
>>   drm/panel: Add support for Sharp LS060T1SX01 panel
>>
>> Guido Günther (5):
>>   drm/bridge: nwl-dsi: Add atomic_get_input_bus_fmts
>>   drm/panel: mantix: Add media bus format
>>   drm/panel: st7703: Add media bus format
>>   drm: mxsfb: Print failed bus format in hex
>>   drm: mxsfb: Set fallback bus format when the bridge doesn't provide one
>>
>> Jani Nikula (1):
>&g

Re: [Intel-gfx] [PULL] drm-misc-next

2021-10-14 Thread Hans de Goede
Hi,

On 10/14/21 2:04 PM, Maxime Ripard wrote:
> Hi Dave, Daniel,
> 
> Here's this week drm-misc-next PR
> 
> Maxime
> 
> drm-misc-next-2021-10-14:
> drm-misc-next for 5.16:

Ugh, this just missed the drm-privacy-screen work which I just pushed
out to drm-misc-next (I was waiting for the last i915 integration patch
to get reviewed).

It would be nice if we can still get the drm-privacy-screen work
included into 5.16. But if it is too late I understand.

Regards,

Hans




> 
> UAPI Changes:
> 
> Cross-subsystem Changes:
> 
> Core Changes:
>   - fbdev: Fix double-free, Remove unused scrolling acceleration
>   - locking: improve logging for contented locks without backoff
>   - dma-buf: Add dma_resv_for_each_fence iterator, and conversion of
> users
> 
> Driver Changes:
>   - nouveau: Various code style improvements
>   - bridge: HPD improvements for lt9611uxc, eDP aux-bus support for
> ps8640, lvds-codec data-mapping selection support
>   - panels: Vivax TPC-9150, Innolux G070Y2-T02, LOGIC Technologies
> LTTD800480070-L2RT, Sharp LS060T1SX01,
> The following changes since commit 9962601ca5719050906915c3c33a63744ac7b15c:
> 
>   drm/bridge: dw-hdmi-cec: Make use of the helper function 
> devm_add_action_or_reset() (2021-10-06 11:21:46 +0200)
> 
> are available in the Git repository at:
> 
>   git://anongit.freedesktop.org/drm/drm-misc tags/drm-misc-next-2021-10-14
> 
> for you to fetch changes up to b3ec8cdf457e5e63d396fe1346cc788cf7c1b578:
> 
>   fbdev: Garbage collect fbdev scrolling acceleration, part 1 (from TODO 
> list) (2021-10-13 15:29:23 +0200)
> 
> 
> drm-misc-next for 5.16:
> 
> UAPI Changes:
> 
> Cross-subsystem Changes:
> 
> Core Changes:
>   - fbdev: Fix double-free, Remove unused scrolling acceleration
>   - locking: improve logging for contented locks without backoff
>   - dma-buf: Add dma_resv_for_each_fence iterator, and conversion of
> users
> 
> Driver Changes:
>   - nouveau: Various code style improvements
>   - bridge: HPD improvements for lt9611uxc, eDP aux-bus support for
> ps8640, lvds-codec data-mapping selection support
>   - panels: Vivax TPC-9150, Innolux G070Y2-T02, LOGIC Technologies
> LTTD800480070-L2RT, Sharp LS060T1SX01,
> 
> 
> Alex Xu (Hello71) (1):
>   drm/plane-helper: fix uninitialized variable reference
> 
> Amos Kong (1):
>   drm/ttm_bo_api: update the description for @placement and @sg
> 
> Christian König (7):
>   dma-buf: add dma_resv_for_each_fence v3
>   dma-buf: use the new iterator in dma_buf_debug_show
>   dma-buf: use the new iterator in dma_resv_poll
>   drm/ttm: use the new iterator in ttm_bo_flush_all_fences
>   drm/scheduler: use new iterator in 
> drm_sched_job_add_implicit_dependencies v2
>   drm/i915: use the new iterator in i915_request_await_object v2
>   drm: use new iterator in drm_gem_fence_array_add_implicit v3
> 
> Claudio Suarez (1):
>   fbdev: Garbage collect fbdev scrolling acceleration, part 1 (from TODO 
> list)
> 
> Dan Carpenter (1):
>   drm/v3d: fix copy_from_user() error codes
> 
> David Heidelberg (1):
>   dt-bindings: display: simple: hardware can use ddc-i2c-bus
> 
> Dmitry Baryshkov (5):
>   drm/bridge/lontium-lt9611uxc: fix provided connector suport
>   dt-bindings: add bindings for the Sharp LS060T1SX01 panel
>   drm/panel: Add support for Sharp LS060T1SX01 panel
>   dt-bindings: add bindings for the Sharp LS060T1SX01 panel
>   drm/panel: Add support for Sharp LS060T1SX01 panel
> 
> Guido Günther (5):
>   drm/bridge: nwl-dsi: Add atomic_get_input_bus_fmts
>   drm/panel: mantix: Add media bus format
>   drm/panel: st7703: Add media bus format
>   drm: mxsfb: Print failed bus format in hex
>   drm: mxsfb: Set fallback bus format when the bridge doesn't provide one
> 
> Jani Nikula (1):
>   drm/locking: add backtrace for locking contended locks without backoff
> 
> Jing Xiangfeng (1):
>   drm/virtio: fix the missed drm_gem_object_put() in 
> virtio_gpu_user_framebuffer_create()
> 
> Karol Herbst (1):
>   drm/nouveau/mmu/gp100: remove unused variable
> 
> Lee Jones (1):
>   drm/nouveau/nouveau_bo: Remove unused variables 'dev'
> 
> Luo penghao (2):
>   drm/nouveau/mmu: drop unneeded assignment in the nvkm_uvmm_mthd_page()
>   drm/nouveau/mmu/gp100-: drop unneeded assignment in the if condition.
> 
> Marek Vasut (3):
>   drm/bridge: ti-sn65dsi83: Implement .detach callback
>   dt-bindings: display: bridge: lvds-codec: Document LVDS data mapping 
> select
>   drm/bridge: lvds-codec: Add support for LVDS data mapping select
> 
> Nikola Pavlica (2):
>   dt-bindings: add vendor prefix for Vivax
>   dt-bindings: display: simple: Add Vivax TPC-9150 panel
> 
> Oleksij Rempel (1):
>   dt-bindings: display: simple: add Innolux G070Y2-T02 panel
> 
> Philip Chen 

Re: [Intel-gfx] [PATCH v2 0/4] drm/dp, drm/i915: Finish basic PWM support for VESA backlight helpers

2021-10-07 Thread Hans de Goede
Hi,

On 10/7/21 11:54 AM, Hans de Goede wrote:
> Hi,
> 
> On 10/5/21 10:26 PM, Lyude Paul wrote:
>> On Sat, 2021-10-02 at 11:14 +0200, Hans de Goede wrote:
>>> Hi Lyude,
>>>
>>> On 10/2/21 12:53 AM, Lyude Paul wrote:
>>>> When I originally moved all of the VESA backlight code in i915 into DRM
>>>> helpers, one of the things I didn't have the hardware or time for
>>>> testing was machines that used a combination of PWM and DPCD in order to
>>>> control their backlights. This has since then caused some breakages and
>>>> resulted in us disabling DPCD backlight support on such machines. This
>>>> works fine, unless you have a machine that actually needs this
>>>> functionality for backlight controls to work at all. Additionally, we
>>>> will need to support PWM for when we start adding support for VESA's
>>>> product (as in the product of multiplication) control mode for better
>>>> brightness ranges.
>>>>
>>>> So - let's finally finish up implementing basic support for these types
>>>> of backlights to solve these problems in our DP helpers, along with
>>>> implementing support for this in i915. And since digging into this issue
>>>> solved the last questions we really had about probing backlights in i915
>>>> for the most part, let's update some of the comments around that as
>>>> well!
>>>
>>> Backlight control is a topic which I'm reasonably familiar with,
>>> do you want me to review this series for you ?
>>
>> Possibly, although I definitely want to make sure that someone from Intel 
>> gets
>> a chance to review this as well.
> 
> I already expected you would also want someone from Intel to take a look
> as well :)
> 
> So to figure out if I have system to test this I ended up taking a close
> look at the code, which was a nice learning experience. Interesting how
> some panels use a combination of DCPD + pwm/gpio for enable/disable and/or
> pwm for brightness level control.
> 
> I wonder though what DCPD still does if pwm is used for both the
> enable/disable and brightness-level control ?
> 
> Since I was taking a close look already I decided to do turn this into
> a full, the entire set looks good to me:
> 
> Reviewed-by: Hans de Goede 
> 
>> I'm more curious if you might happen to have
>> any systems that would be able to test this.
> 
> I don't believe I have a system where I can test this, The only systems
> which I have which presumably (I did not check) use eDP / DCPD backlight
> control are boring ThinkPads with only i915 gfx.

Continuing with reading my email I see that you've also posted a v5
with 1 new patch:

[PATCH v3 3/5] drm/dp: Disable unsupported features in 
DP_EDP_BACKLIGHT_MODE_SET_REGISTER

That patch looks good to me too, so you may also add my:

Reviewed-by: Hans de Goede 

To that one / to the entire v3 series.

Regards,

Hans



>>>> Changes:
>>>> * Fixup docs
>>>> * Add patch to stop us from breaking nouveau
>>>>
>>>> Lyude Paul (4):
>>>>   drm/i915: Add support for panels with VESA backlights with PWM
>>>>     enable/disable
>>>>   drm/nouveau/kms/nv50-: Explicitly check DPCD backlights for aux
>>>>     enable/brightness
>>>>   drm/dp, drm/i915: Add support for VESA backlights using PWM for
>>>>     brightness control
>>>>   drm/i915: Clarify probing order in intel_dp_aux_init_backlight_funcs()
>>>>
>>>>  drivers/gpu/drm/drm_dp_helper.c   | 75 +++--
>>>>  .../drm/i915/display/intel_dp_aux_backlight.c | 80 ++-
>>>>  drivers/gpu/drm/nouveau/nouveau_backlight.c   |  5 +-
>>>>  include/drm/drm_dp_helper.h   |  7 +-
>>>>  4 files changed, 122 insertions(+), 45 deletions(-)
>>>>
>>>
>>



Re: [Intel-gfx] [PATCH v2 0/4] drm/dp, drm/i915: Finish basic PWM support for VESA backlight helpers

2021-10-07 Thread Hans de Goede
Hi,

On 10/5/21 10:26 PM, Lyude Paul wrote:
> On Sat, 2021-10-02 at 11:14 +0200, Hans de Goede wrote:
>> Hi Lyude,
>>
>> On 10/2/21 12:53 AM, Lyude Paul wrote:
>>> When I originally moved all of the VESA backlight code in i915 into DRM
>>> helpers, one of the things I didn't have the hardware or time for
>>> testing was machines that used a combination of PWM and DPCD in order to
>>> control their backlights. This has since then caused some breakages and
>>> resulted in us disabling DPCD backlight support on such machines. This
>>> works fine, unless you have a machine that actually needs this
>>> functionality for backlight controls to work at all. Additionally, we
>>> will need to support PWM for when we start adding support for VESA's
>>> product (as in the product of multiplication) control mode for better
>>> brightness ranges.
>>>
>>> So - let's finally finish up implementing basic support for these types
>>> of backlights to solve these problems in our DP helpers, along with
>>> implementing support for this in i915. And since digging into this issue
>>> solved the last questions we really had about probing backlights in i915
>>> for the most part, let's update some of the comments around that as
>>> well!
>>
>> Backlight control is a topic which I'm reasonably familiar with,
>> do you want me to review this series for you ?
> 
> Possibly, although I definitely want to make sure that someone from Intel gets
> a chance to review this as well.

I already expected you would also want someone from Intel to take a look
as well :)

So to figure out if I have system to test this I ended up taking a close
look at the code, which was a nice learning experience. Interesting how
some panels use a combination of DCPD + pwm/gpio for enable/disable and/or
pwm for brightness level control.

I wonder though what DCPD still does if pwm is used for both the
enable/disable and brightness-level control ?

Since I was taking a close look already I decided to do turn this into
a full, the entire set looks good to me:

Reviewed-by: Hans de Goede 

> I'm more curious if you might happen to have
> any systems that would be able to test this.

I don't believe I have a system where I can test this, The only systems
which I have which presumably (I did not check) use eDP / DCPD backlight
control are boring ThinkPads with only i915 gfx.

Regards,

Hans



>>> Changes:
>>> * Fixup docs
>>> * Add patch to stop us from breaking nouveau
>>>
>>> Lyude Paul (4):
>>>   drm/i915: Add support for panels with VESA backlights with PWM
>>>     enable/disable
>>>   drm/nouveau/kms/nv50-: Explicitly check DPCD backlights for aux
>>>     enable/brightness
>>>   drm/dp, drm/i915: Add support for VESA backlights using PWM for
>>>     brightness control
>>>   drm/i915: Clarify probing order in intel_dp_aux_init_backlight_funcs()
>>>
>>>  drivers/gpu/drm/drm_dp_helper.c   | 75 +++--
>>>  .../drm/i915/display/intel_dp_aux_backlight.c | 80 ++-
>>>  drivers/gpu/drm/nouveau/nouveau_backlight.c   |  5 +-
>>>  include/drm/drm_dp_helper.h   |  7 +-
>>>  4 files changed, 122 insertions(+), 45 deletions(-)
>>>
>>
> 



Re: [PATCH RFC] drm: introduce DRM_MODE_FB_PERSIST

2021-10-07 Thread Hans de Goede
Hi,

On 10/7/21 9:45 AM, Pekka Paalanen wrote:
> On Wed, 6 Oct 2021 21:24:44 +0200
> Daniel Vetter  wrote:
> 
>> On Wed, Oct 6, 2021 at 5:19 PM Simon Ser  wrote:
>>> This new ADDFB2 flag allows callers to mark a framebuffer as
>>> "persistent", and no longer have RMFB semantics when the DRM
>>> file is closed.
>>>
>>> [1]: https://lore.kernel.org/dri-devel/YTJypepF1Hpc2YYT@reader/
>>>
>>> Signed-off-by: Simon Ser 
>>> Cc: Hans de Goede 
>>> Cc: Dennis Filder 
>>> Cc: Daniel Vetter 
>>> Cc: Pekka Paalanen 
>>> ---
>>>
>>> I'm not sure this is enough, but posting this to get initial
>>> feedback and allow to start e.g. Plymouth experiments. I'll
>>> follow up with an IGT test soon.
>>>
>>>  drivers/gpu/drm/drm_framebuffer.c |  6 --
>>>  include/uapi/drm/drm_mode.h   | 15 +++
>>>  2 files changed, 19 insertions(+), 2 deletions(-)
>>>
>>> diff --git a/drivers/gpu/drm/drm_framebuffer.c 
>>> b/drivers/gpu/drm/drm_framebuffer.c
>>> index 07f5abc875e9..9b398838e1f4 100644
>>> --- a/drivers/gpu/drm/drm_framebuffer.c
>>> +++ b/drivers/gpu/drm/drm_framebuffer.c
>>> @@ -292,7 +292,8 @@ drm_internal_framebuffer_create(struct drm_device *dev,
>>> struct drm_framebuffer *fb;
>>> int ret;
>>>
>>> -   if (r->flags & ~(DRM_MODE_FB_INTERLACED | DRM_MODE_FB_MODIFIERS)) {
>>> +   if (r->flags & ~(DRM_MODE_FB_INTERLACED | DRM_MODE_FB_MODIFIERS |
>>> +DRM_MODE_FB_PERSIST)) {
>>> DRM_DEBUG_KMS("bad framebuffer flags 0x%08x\n", r->flags);
>>> return ERR_PTR(-EINVAL);
>>> }
>>> @@ -789,7 +790,8 @@ void drm_fb_release(struct drm_file *priv)
>>>  * at it any more.
>>>  */
>>> list_for_each_entry_safe(fb, tfb, >fbs, filp_head) {
>>> -   if (drm_framebuffer_read_refcount(fb) > 1) {
>>> +   if (drm_framebuffer_read_refcount(fb) > 1 &&
>>> +   !(fb->flags & DRM_MODE_FB_PERSIST)) {
>>> list_move_tail(>filp_head, );
>>> } else {
>>> list_del_init(>filp_head);
>>> diff --git a/include/uapi/drm/drm_mode.h b/include/uapi/drm/drm_mode.h
>>> index e1e351682872..c7a7089ec31e 100644
>>> --- a/include/uapi/drm/drm_mode.h
>>> +++ b/include/uapi/drm/drm_mode.h
>>> @@ -662,6 +662,21 @@ struct drm_mode_fb_cmd {
>>>
>>>  #define DRM_MODE_FB_INTERLACED (1<<0) /* for interlaced framebuffers */
>>>  #define DRM_MODE_FB_MODIFIERS  (1<<1) /* enables ->modifer[] */
>>> +/**
>>> + * DRM_MODE_FB_PERSIST
>>> + *
>>> + * DRM framebuffers are normally implicitly removed when their owner 
>>> closes the
>>> + * DRM FD. Passing this flag will make the framebuffer persistent: it will 
>>> not
>>> + * be implicitly removed. This is useful to implement flicker-free 
>>> transitions
>>> + * between two processes.
>>> + *
>>> + * This flag doesn't change the behavior of _IOCTL_MODE_RMFB.
>>> + *
>>> + * User-space should ensure the framebuffer doesn't expose any sensitive 
>>> user
>>> + * information: persistent framebuffers can be read back by the next DRM
>>> + * master.  
>>
>> Should probably explain here that the persistent fb stays around for
>> as long as it's still in use by a plane, but will disappear
>> automatically when it's no longer in active use.
> 
> Yes, I think that is an important detail.
> 
>> Also I guess there was some discussion I've missed on why we exclude
>> rmfb from this (unlike the CLOSEFB thing robclark proposed ages ago).
> 
> What does that mean? Was the CLOSEFB proposal saying that doing an RMFB
> on a persistent FB does not actually RM the FB? If so, what effect did
> it have, did it only invalidate the userspace FB ID?
> 
> That is an interesting thought. Userspace would not need to
> deliberately "leak" the FB ID, it could still RMFB it which feels more
> clean to me.
> 
> What if persistence was a flag on RMFB instead? If userspace forgets to
> call RMFB at all, then closing the device removes the FB and avoids
> information leaks. Only by doing special RMFB would allow the FB to
> remain after closing the device. That should also encourage userspace
> to track their FBs better.
> 
>> The nice thing about closefb is that you can give it persistent
>> semantics retroactively, so don't need to re-wrap an gem_bo and do a
>> page flip when you quit.
> 
> When you quit, you are going to need to draw once more anyway to get
> rid of any potentially sensitive information for sure, so the re-wrap
> does not seem much extra to me.

Right that was my though too.

> OTOH, I guess userspace code would be a
> little simpler if it does not need to re-wrap (assuming the code
> already keeps FB IDs around and does not re-ADDFB on every flip -
> weston does this caching).
> 
> I think my order of favourites is:
>  1. RMFB flag
>  2. ioctl to set an existing FB as persistent
>  3. ADDFB flag
> 
> They all seem workable to me.

I fully agree with the above.

Regards,

Hans



[PATCH 10/10] drm/i915: Add privacy-screen support (v3)

2021-10-05 Thread Hans de Goede
Add support for eDP panels with a built-in privacy screen using the
new drm_privacy_screen class.

Changes in v3:
- Move drm_privacy_screen_get() call to intel_ddi_init_dp_connector()

Changes in v2:
- Call drm_connector_update_privacy_screen() from
  intel_enable_ddi_dp() / intel_ddi_update_pipe_dp() instead of adding a
  for_each_new_connector_in_state() loop to intel_atomic_commit_tail()
- Move the probe-deferral check to the intel_modeset_probe_defer() helper

Signed-off-by: Hans de Goede 
---
 drivers/gpu/drm/i915/display/intel_atomic.c  |  1 +
 drivers/gpu/drm/i915/display/intel_ddi.c | 16 
 drivers/gpu/drm/i915/display/intel_display.c | 10 ++
 3 files changed, 27 insertions(+)

diff --git a/drivers/gpu/drm/i915/display/intel_atomic.c 
b/drivers/gpu/drm/i915/display/intel_atomic.c
index b4e7ac51aa31..a62550711e98 100644
--- a/drivers/gpu/drm/i915/display/intel_atomic.c
+++ b/drivers/gpu/drm/i915/display/intel_atomic.c
@@ -139,6 +139,7 @@ int intel_digital_connector_atomic_check(struct 
drm_connector *conn,
new_conn_state->base.picture_aspect_ratio != 
old_conn_state->base.picture_aspect_ratio ||
new_conn_state->base.content_type != 
old_conn_state->base.content_type ||
new_conn_state->base.scaling_mode != 
old_conn_state->base.scaling_mode ||
+   new_conn_state->base.privacy_screen_sw_state != 
old_conn_state->base.privacy_screen_sw_state ||
!drm_connector_atomic_hdr_metadata_equal(old_state, new_state))
crtc_state->mode_changed = true;
 
diff --git a/drivers/gpu/drm/i915/display/intel_ddi.c 
b/drivers/gpu/drm/i915/display/intel_ddi.c
index 0d4cf7fa8720..272714e07cc6 100644
--- a/drivers/gpu/drm/i915/display/intel_ddi.c
+++ b/drivers/gpu/drm/i915/display/intel_ddi.c
@@ -25,6 +25,7 @@
  *
  */
 
+#include 
 #include 
 
 #include "i915_drv.h"
@@ -2946,6 +2947,7 @@ static void intel_enable_ddi_dp(struct intel_atomic_state 
*state,
if (port == PORT_A && DISPLAY_VER(dev_priv) < 9)
intel_dp_stop_link_train(intel_dp, crtc_state);
 
+   drm_connector_update_privacy_screen(conn_state);
intel_edp_backlight_on(crtc_state, conn_state);
 
if (!dig_port->lspcon.active || dig_port->dp.has_hdmi_sink)
@@ -3161,6 +3163,7 @@ static void intel_ddi_update_pipe_dp(struct 
intel_atomic_state *state,
intel_drrs_update(intel_dp, crtc_state);
 
intel_backlight_update(state, encoder, crtc_state, conn_state);
+   drm_connector_update_privacy_screen(conn_state);
 }
 
 void intel_ddi_update_pipe(struct intel_atomic_state *state,
@@ -3979,6 +3982,19 @@ intel_ddi_init_dp_connector(struct intel_digital_port 
*dig_port)
return NULL;
}
 
+   if (dig_port->base.type == INTEL_OUTPUT_EDP) {
+   struct drm_device *dev = dig_port->base.base.dev;
+   struct drm_privacy_screen *privacy_screen;
+
+   privacy_screen = drm_privacy_screen_get(dev->dev, NULL);
+   if (!IS_ERR(privacy_screen)) {
+   
drm_connector_attach_privacy_screen_provider(>base,
+
privacy_screen);
+   } else if (PTR_ERR(privacy_screen) != -ENODEV) {
+   drm_warn(dev, "Error getting privacy-screen\n");
+   }
+   }
+
return connector;
 }
 
diff --git a/drivers/gpu/drm/i915/display/intel_display.c 
b/drivers/gpu/drm/i915/display/intel_display.c
index 86dbe366a907..84715a779d9d 100644
--- a/drivers/gpu/drm/i915/display/intel_display.c
+++ b/drivers/gpu/drm/i915/display/intel_display.c
@@ -42,6 +42,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 
@@ -12769,6 +12770,8 @@ void intel_modeset_driver_remove_nogem(struct 
drm_i915_private *i915)
 
 bool intel_modeset_probe_defer(struct pci_dev *pdev)
 {
+   struct drm_privacy_screen *privacy_screen;
+
/*
 * apple-gmux is needed on dual GPU MacBook Pro
 * to probe the panel if we're the inactive GPU.
@@ -12776,6 +12779,13 @@ bool intel_modeset_probe_defer(struct pci_dev *pdev)
if (vga_switcheroo_client_probe_defer(pdev))
return true;
 
+   /* If the LCD panel has a privacy-screen, wait for it */
+   privacy_screen = drm_privacy_screen_get(>dev, NULL);
+   if (IS_ERR(privacy_screen) && PTR_ERR(privacy_screen) == -EPROBE_DEFER)
+   return true;
+
+   drm_privacy_screen_put(privacy_screen);
+
return false;
 }
 
-- 
2.31.1



[PATCH 09/10] drm/i915: Add intel_modeset_probe_defer() helper

2021-10-05 Thread Hans de Goede
The upcoming privacy-screen support adds another check for
deferring probe till some other drivers have bound first.

Factor out the current vga_switcheroo_client_probe_defer() check
into an intel_modeset_probe_defer() helper, so that further
probe-deferral checks can be added there.

Reviewed-by: Ville Syrjälä 
Signed-off-by: Hans de Goede 
---
 drivers/gpu/drm/i915/display/intel_display.c | 13 +
 drivers/gpu/drm/i915/display/intel_display.h |  1 +
 drivers/gpu/drm/i915/i915_pci.c  |  9 ++---
 3 files changed, 16 insertions(+), 7 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_display.c 
b/drivers/gpu/drm/i915/display/intel_display.c
index 4f0badb11bbb..86dbe366a907 100644
--- a/drivers/gpu/drm/i915/display/intel_display.c
+++ b/drivers/gpu/drm/i915/display/intel_display.c
@@ -32,6 +32,7 @@
 #include 
 #include 
 #include 
+#include 
 
 #include 
 #include 
@@ -12766,6 +12767,18 @@ void intel_modeset_driver_remove_nogem(struct 
drm_i915_private *i915)
intel_bios_driver_remove(i915);
 }
 
+bool intel_modeset_probe_defer(struct pci_dev *pdev)
+{
+   /*
+* apple-gmux is needed on dual GPU MacBook Pro
+* to probe the panel if we're the inactive GPU.
+*/
+   if (vga_switcheroo_client_probe_defer(pdev))
+   return true;
+
+   return false;
+}
+
 void intel_display_driver_register(struct drm_i915_private *i915)
 {
if (!HAS_DISPLAY(i915))
diff --git a/drivers/gpu/drm/i915/display/intel_display.h 
b/drivers/gpu/drm/i915/display/intel_display.h
index 3028072c2cf3..d3d34acb6c08 100644
--- a/drivers/gpu/drm/i915/display/intel_display.h
+++ b/drivers/gpu/drm/i915/display/intel_display.h
@@ -633,6 +633,7 @@ void intel_display_driver_register(struct drm_i915_private 
*i915);
 void intel_display_driver_unregister(struct drm_i915_private *i915);
 
 /* modesetting */
+bool intel_modeset_probe_defer(struct pci_dev *pdev);
 void intel_modeset_init_hw(struct drm_i915_private *i915);
 int intel_modeset_init_noirq(struct drm_i915_private *i915);
 int intel_modeset_init_nogem(struct drm_i915_private *i915);
diff --git a/drivers/gpu/drm/i915/i915_pci.c b/drivers/gpu/drm/i915/i915_pci.c
index 169837de395d..8fc45d8119b6 100644
--- a/drivers/gpu/drm/i915/i915_pci.c
+++ b/drivers/gpu/drm/i915/i915_pci.c
@@ -22,8 +22,6 @@
  *
  */
 
-#include 
-
 #include 
 #include 
 
@@ -1189,11 +1187,8 @@ static int i915_pci_probe(struct pci_dev *pdev, const 
struct pci_device_id *ent)
if (PCI_FUNC(pdev->devfn))
return -ENODEV;
 
-   /*
-* apple-gmux is needed on dual GPU MacBook Pro
-* to probe the panel if we're the inactive GPU.
-*/
-   if (vga_switcheroo_client_probe_defer(pdev))
+   /* Detect if we need to wait for other drivers early on */
+   if (intel_modeset_probe_defer(pdev))
return -EPROBE_DEFER;
 
err = i915_driver_probe(pdev, ent);
-- 
2.31.1



[PATCH 08/10] platform/x86: thinkpad_acpi: Register a privacy-screen device

2021-10-05 Thread Hans de Goede
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 a new standardized
interface which all user-space code should use to query and control
the privacy-screen.

Reviewed-by: Emil Velikov 
Reviewed-by: Lyude Paul 
Signed-off-by: Hans de Goede 
---
Changes in v3:
- On receiving a TP_HKEY_EV_PRIVACYGUARD_TOGGLE event only call
  drm_privacy_screen_call_notifier_chain() if the privacy-screen state
  has actually changed

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 | 97 +---
 2 files changed, 74 insertions(+), 25 deletions(-)

diff --git a/drivers/platform/x86/Kconfig b/drivers/platform/x86/Kconfig
index e21ea3d23e6f..20208207e366 100644
--- a/drivers/platform/x86/Kconfig
+++ b/drivers/platform/x86/Kconfig
@@ -501,7 +501,9 @@ config THINKPAD_ACPI
depends on ACPI_VIDEO || ACPI_VIDEO = n
depends on BACKLIGHT_CLASS_DEVICE
depends on I2C
+   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 b8f2556c4797..291cd18c9c8f 100644
--- a/drivers/platform/x86/thinkpad_acpi.c
+++ b/drivers/platform/x86/thinkpad_acpi.c
@@ -73,6 +73,7 @@
 #include 
 #include 
 #include 
+#include 
 #include "dual_accel_detect.h"
 
 /* ThinkPad CMOS commands */
@@ -157,6 +158,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 */
@@ -3889,6 +3891,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.
@@ -9819,30 +9827,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(>lock)))
+   return -EIO;
+
if (!acpi_evalf(lcdshadow_set_handle, , 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, , 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;
@@ -9850,36 +9868,44 @@ static int tpacpi_lcdshadow_init(struct ibm_init_struct 
*iibm)
 
status1 = acpi_get_handle(hkey_handle, "GSSS", _get_handle);
status2 = acpi_get_handle(hkey_handle, "", _set_handle);
-   if (ACPI_FAILURE(status1) || ACPI_FAILURE(status2)) {
-   lcdshadow_state = -ENODEV;
+   if (

[PATCH 07/10] platform/x86: thinkpad_acpi: Get privacy-screen / lcdshadow ACPI handles only once

2021-10-05 Thread Hans de Goede
Get the privacy-screen / lcdshadow ACPI handles once and cache them,
instead of retrieving them every time we need them.

Reviewed-by: Emil Velikov 
Reviewed-by: Lyude Paul 
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 83c88a8ebaf2..b8f2556c4797 100644
--- a/drivers/platform/x86/thinkpad_acpi.c
+++ b/drivers/platform/x86/thinkpad_acpi.c
@@ -9819,19 +9819,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, "", 
_shadow_handle))) {
-   pr_warn("Thinkpad ACPI has no %s interface.\n", "");
-   return -EIO;
-   }
-
-   if (!acpi_evalf(set_shadow_handle, , NULL, "dd", (int)state))
+   if (!acpi_evalf(lcdshadow_set_handle, , NULL, "dd", (int)state))
return -EIO;
 
lcdshadow_state = state;
@@ -9849,15 +9845,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", 
_shadow_handle))) {
+   status1 = acpi_get_handle(hkey_handle, "GSSS", _get_handle);
+   status2 = acpi_get_handle(hkey_handle, "", _set_handle);
+   if (ACPI_FAILURE(status1) || ACPI_FAILURE(status2)) {
lcdshadow_state = -ENODEV;
return 0;
}
 
-   if (!acpi_evalf(get_shadow_handle, , NULL, "dd", 0)) {
+   if (!acpi_evalf(lcdshadow_get_handle, , NULL, "dd", 0)) {
lcdshadow_state = -EIO;
return -EIO;
}
-- 
2.31.1



[PATCH 06/10] platform/x86: thinkpad_acpi: Add hotkey_notify_extended_hotkey() helper

2021-10-05 Thread Hans de Goede
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...).

Reviewed-by: Emil Velikov 
Reviewed-by: Lyude Paul 
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 50ff04c84650..83c88a8ebaf2 100644
--- a/drivers/platform/x86/thinkpad_acpi.c
+++ b/drivers/platform/x86/thinkpad_acpi.c
@@ -3885,6 +3885,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)
@@ -3919,17 +3937,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



[PATCH 05/10] drm/connector: Add a drm_connector privacy-screen helper functions (v2)

2021-10-05 Thread Hans de Goede
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(), update the privacy-screen's
sw_state if the connector has a privacy-screen.

Changes in v2:
- Do not update connector->state->privacy_screen_sw_state on
  atomic-commits.
- Change drm_connector_update_privacy_screen() to take drm_connector_state
  as argument instead of a full drm_atomic_state. This allows the helper
  to be called by drivers when they are enabling crtcs/encoders/connectors.

Reviewed-by: Emil Velikov 
Reviewed-by: Lyude Paul 
Signed-off-by: Hans de Goede 
---
 drivers/gpu/drm/drm_connector.c | 102 
 include/drm/drm_connector.h |  11 
 2 files changed, 113 insertions(+)

diff --git a/drivers/gpu/drm/drm_connector.c b/drivers/gpu/drm/drm_connector.c
index b2f1f1b1bfb4..00cf3b6135f6 100644
--- a/drivers/gpu/drm/drm_connector.c
+++ b/drivers/gpu/drm/drm_connector.c
@@ -28,6 +28,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 
 #include 
@@ -462,6 +463,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;
@@ -543,6 +549,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,
+  >privacy_screen_notifier);
+
mutex_lock(_list_lock);
list_add_tail(>global_connector_list_entry, _list);
mutex_unlock(_list_lock);
@@ -578,6 +588,11 @@ void drm_connector_unregister(struct drm_connector 
*connector)
list_del_init(>global_connector_list_entry);
mutex_unlock(_list_lock);
 
+   if (connector->privacy_screen)
+   drm_privacy_screen_unregister_notifier(
+   connector->privacy_screen,
+   >privacy_screen_notifier);
+
if (connector->funcs->early_unregister)
connector->funcs->early_unregister(connector);
 
@@ -2442,6 +2457,93 @@ 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, bool set_sw_state)
+{
+   enum drm_privacy_screen_status sw_state, hw_state;
+
+   drm_privacy_screen_get_state(connector->privacy_screen,
+_state, _state);
+
+   if (set_sw_state)
+   connector->state->privacy_screen_sw_state = sw_state;
+   drm_object_property_set_value(>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(>mode_config.connection_mutex, NULL);
+   drm_connector_update_privacy_screen_properties(connector, true);
+   drm_modeset_unlock(>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(
+

[PATCH 04/10] drm/privacy-screen: Add notifier support (v2)

2021-10-05 Thread Hans de Goede
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.

Changes in v2:
- Drop WARN_ON(mutex_is_locked(>lock)) check in
  drm_privacy_screen_call_notifier_chain() it may be locked by
  another thread, which would lead to a false-positive triggering
  of the check

Reviewed-by: Emil Velikov 
Reviewed-by: Lyude Paul 
Signed-off-by: Hans de Goede 
---
 drivers/gpu/drm/drm_privacy_screen.c  | 64 +++
 include/drm/drm_privacy_screen_consumer.h | 15 ++
 include/drm/drm_privacy_screen_driver.h   |  4 ++
 3 files changed, 83 insertions(+)

diff --git a/drivers/gpu/drm/drm_privacy_screen.c 
b/drivers/gpu/drm/drm_privacy_screen.c
index 183a6011adf0..beaf99e9120a 100644
--- a/drivers/gpu/drm/drm_privacy_screen.c
+++ b/drivers/gpu/drm/drm_privacy_screen.c
@@ -257,6 +257,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(>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(>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,
@@ -354,6 +397,7 @@ struct drm_privacy_screen *drm_privacy_screen_register(
return ERR_PTR(-ENOMEM);
 
mutex_init(>lock);
+   BLOCKING_INIT_NOTIFIER_HEAD(>notifier_head);
 
priv->dev.class = drm_class;
priv->dev.type = _privacy_screen_type;
@@ -401,3 +445,23 @@ void drm_privacy_screen_unregister(struct 
drm_privacy_screen *priv)
device_unregister(>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)
+{
+   blocking_notifier_call_chain(>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 0cbd23b0453d..7f66a90d15b7 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(stru

[PATCH 03/10] drm/privacy-screen: Add X86 specific arch init code

2021-10-05 Thread Hans de Goede
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.

Reviewed-by: Emil Velikov 
Reviewed-by: Lyude Paul 
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 788fc37096f6..12997ca5670d 100644
--- a/drivers/gpu/drm/Makefile
+++ b/drivers/gpu/drm/Makefile
@@ -32,7 +32,7 @@ drm-$(CONFIG_OF) += drm_of.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
 
 obj-$(CONFIG_DRM_DP_AUX_BUS) += drm_dp_aux_bus.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 = , };
+   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, _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", , );
+   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(_lookup);
+   break;
+   }
+}
+
+void drm_privacy_screen_lookup_exit(void)
+{
+   if (arch_lookup.provider)
+   drm_privacy_screen_lookup_remove(_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



[PATCH 02/10] drm: Add privacy-screen class (v4)

2021-10-05 Thread Hans de Goede
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

Changes in v3:
- Make the static inline drm_privacy_screen_get_state() stub set sw_state
  and hw_state to PRIVACY_SCREEN_DISABLED to squelch an uninitialized
  variable warning when CONFIG_DRM_PRIVICAY_SCREEN is not set

Changes in v4:
- Make drm_privacy_screen_set_sw_state() skip calling out to the hw if
  hw_state == new_sw_state

Reviewed-by: Emil Velikov 
Reviewed-by: Lyude Paul 
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  | 403 ++
 include/drm/drm_privacy_screen_consumer.h |  50 +++
 include/drm/drm_privacy_screen_driver.h   |  80 +
 include/drm/drm_privacy_screen_machine.h  |  41 +++
 9 files changed, 606 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 ec2f65b31930..5bb55ec1b9b5 100644
--- a/Documentation/gpu/drm-kms-helpers.rst
+++ b/Documentation/gpu/drm-kms-helpers.rst
@@ -435,3 +435,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 28e5f0ae1009..cb94bb3b8724 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -6423,6 +6423,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 2a926d0de423..c686c08447ac 100644
--- a/drivers/gpu/drm/Kconfig
+++ b/drivers/gpu/drm/Kconfig
@@ -481,3 +481,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 0dff40bb863c..788fc37096f6 100644
--- a/drivers/gpu/drm/Makefile
+++ b/drivers/gpu/drm/Makefile
@@ -32,6 +32,7 @@ drm-$(CONFIG_OF) += drm_of.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
 
 obj-$(CONFIG_DRM_DP_AUX_BUS) += drm_dp_aux_bus.o
 
diff --git a/drivers/gpu/drm/drm_drv.c b/drivers/gpu/drm/drm_drv.c
index 7a5097467ba5..dc293b771c3f 100644
--- a/drivers/gpu/drm/drm_drv.c
+++ b/drivers/gpu/drm/drm_drv.c
@@ -43,6 +43,7 @@
 #include 
 #include 
 #include 
+#include 
 
 #include "drm_crtc_internal.h"
 #include "drm_internal.h"
@@ -1029,6 +1030,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 &

[PATCH 01/10] drm/connector: Add support for privacy-screen properties (v4)

2021-10-05 Thread Hans de Goede
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 
Acked-by: Pekka Paalanen 
Reviewed-by: Mario Limonciello 
Reviewed-by: Emil Velikov 
Reviewed-by: Lyude Paul 
Co-developed-by: Hans de Goede 
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 1ef7951ded5e..d14bf1c35d7e 100644
--- a/Documentation/gpu/drm-kms.rst
+++ b/Documentation/gpu/drm-kms.rst
@@ -506,6 +506,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 909f31833181..cdd31fc78bfc 100644
--- a/drivers/gpu/drm/drm_atomic_uapi.c
+++ b/drivers/gpu/drm/drm_atomic_uapi.c
@@ -797,6 +797,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);
@@ -874,6 +876,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 3bc782b630b9..b2f1f1b1bfb4 100644
--- a/drivers/gpu/drm/drm_connector.c
+++ b/drivers/gpu/drm/drm_connector.c
@@ -1264,6 +1264,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
+ * 

[PATCH 00/10] drm: Add privacy-screen class and connector properties

2021-10-05 Thread Hans de Goede
Hi all,

Here is a new version of my privacy-screen series, addressing the
review-remark from Ville on patch 10/10 from the version posted on
October 2nd. This new version contains the following changes:

- drm/i915: Add privacy-screen support (v3)
 - Move drm_privacy_screen_get() call to intel_ddi_init_dp_connector()

Ville, can you (re)review "[PATCH 10/10] drm/i915: Add privacy-screen
support (v3)" please ?

For anyone just tuning in, here is some more info from the previous
cover-letters:

The first userspace consumer of the new properties is now fully ready
for merging (it is just waiting for the kernel bits to land first):

 - https://gitlab.gnome.org/GNOME/gsettings-desktop-schemas/-/merge_requests/49
 - https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1952
 - https://gitlab.gnome.org/GNOME/gnome-control-center/-/merge_requests/1032

The new API works as designed and 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 (9):
  drm: Add privacy-screen class (v4)
  drm/privacy-screen: Add X86 specific arch init code
  drm/privacy-screen: Add notifier support (v2)
  drm/connector: Add a drm_connector privacy-screen helper functions
(v2)
  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 intel_modeset_probe_defer() helper
  drm/i915: Add privacy-screen support (v3)

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  | 203 
 drivers/gpu/drm/drm_drv.c|   4 +
 drivers/gpu/drm/drm_privacy_screen.c | 467 +++
 drivers/gpu/drm/drm_privacy_screen_x86.c |  86 
 drivers/gpu/drm/i915/display/intel_atomic.c  |   1 +
 drivers/gpu/drm/i915/display/intel_ddi.c |  15 +
 drivers/gpu/drm/i915/display/intel_display.c |  23 +
 drivers/gpu/drm/i915/display/intel_display.h |   1 +
 drivers/gpu/drm/i915/i915_pci.c  |   9 +-
 drivers/platform/x86/Kconfig |   2 +
 drivers/platform/x86/thinkpad_acpi.c | 137 --
 include/drm/drm_connector.h  |  55 +++
 include/drm/drm_privacy_screen_consumer.h|  65 +++
 include/drm/drm_privacy_screen_driver.h  |  

Re: [PATCH 10/10] drm/i915: Add privacy-screen support (v2)

2021-10-04 Thread Hans de Goede
Hi,

On 10/4/21 5:37 PM, Ville Syrjälä wrote:
> On Sat, Oct 02, 2021 at 06:36:18PM +0200, Hans de Goede wrote:
>> Add support for eDP panels with a built-in privacy screen using the
>> new drm_privacy_screen class.
>>
>> Changes in v2:
>> - Call drm_connector_update_privacy_screen() from
>>   intel_enable_ddi_dp() / intel_ddi_update_pipe_dp() instead of adding a
>>   for_each_new_connector_in_state() loop to intel_atomic_commit_tail()
>> - Move the probe-deferral check to the intel_modeset_probe_defer() helper
>>
>> Signed-off-by: Hans de Goede 
>> ---
>>  drivers/gpu/drm/i915/display/intel_atomic.c  |  1 +
>>  drivers/gpu/drm/i915/display/intel_ddi.c |  3 +++
>>  drivers/gpu/drm/i915/display/intel_display.c | 10 ++
>>  drivers/gpu/drm/i915/display/intel_dp.c  | 10 ++
>>  4 files changed, 24 insertions(+)
>>
>> diff --git a/drivers/gpu/drm/i915/display/intel_atomic.c 
>> b/drivers/gpu/drm/i915/display/intel_atomic.c
>> index b4e7ac51aa31..a62550711e98 100644
>> --- a/drivers/gpu/drm/i915/display/intel_atomic.c
>> +++ b/drivers/gpu/drm/i915/display/intel_atomic.c
>> @@ -139,6 +139,7 @@ int intel_digital_connector_atomic_check(struct 
>> drm_connector *conn,
>>  new_conn_state->base.picture_aspect_ratio != 
>> old_conn_state->base.picture_aspect_ratio ||
>>  new_conn_state->base.content_type != 
>> old_conn_state->base.content_type ||
>>  new_conn_state->base.scaling_mode != 
>> old_conn_state->base.scaling_mode ||
>> +new_conn_state->base.privacy_screen_sw_state != 
>> old_conn_state->base.privacy_screen_sw_state ||
>>  !drm_connector_atomic_hdr_metadata_equal(old_state, new_state))
>>  crtc_state->mode_changed = true;
>>  
>> diff --git a/drivers/gpu/drm/i915/display/intel_ddi.c 
>> b/drivers/gpu/drm/i915/display/intel_ddi.c
>> index 51cd0420e00e..e4496c830a35 100644
>> --- a/drivers/gpu/drm/i915/display/intel_ddi.c
>> +++ b/drivers/gpu/drm/i915/display/intel_ddi.c
>> @@ -25,6 +25,7 @@
>>   *
>>   */
>>  
>> +#include 
>>  #include 
>>  
>>  #include "i915_drv.h"
>> @@ -3022,6 +3023,7 @@ static void intel_enable_ddi_dp(struct 
>> intel_atomic_state *state,
>>  if (port == PORT_A && DISPLAY_VER(dev_priv) < 9)
>>  intel_dp_stop_link_train(intel_dp, crtc_state);
>>  
>> +drm_connector_update_privacy_screen(conn_state);
>>  intel_edp_backlight_on(crtc_state, conn_state);
>>  
>>  if (!dig_port->lspcon.active || dig_port->dp.has_hdmi_sink)
>> @@ -3247,6 +3249,7 @@ static void intel_ddi_update_pipe_dp(struct 
>> intel_atomic_state *state,
>>  intel_drrs_update(intel_dp, crtc_state);
>>  
>>  intel_backlight_update(state, encoder, crtc_state, conn_state);
>> +drm_connector_update_privacy_screen(conn_state);
>>  }
>>  
>>  void intel_ddi_update_pipe(struct intel_atomic_state *state,
>> diff --git a/drivers/gpu/drm/i915/display/intel_display.c 
>> b/drivers/gpu/drm/i915/display/intel_display.c
>> index e67f3207ba54..9a5dbe51458d 100644
>> --- a/drivers/gpu/drm/i915/display/intel_display.c
>> +++ b/drivers/gpu/drm/i915/display/intel_display.c
>> @@ -42,6 +42,7 @@
>>  #include 
>>  #include 
>>  #include 
>> +#include 
>>  #include 
>>  #include 
>>  #include 
>> @@ -12693,6 +12694,8 @@ void intel_modeset_driver_remove_nogem(struct 
>> drm_i915_private *i915)
>>  
>>  bool intel_modeset_probe_defer(struct pci_dev *pdev)
>>  {
>> +struct drm_privacy_screen *privacy_screen;
>> +
>>  /*
>>   * apple-gmux is needed on dual GPU MacBook Pro
>>   * to probe the panel if we're the inactive GPU.
>> @@ -12700,6 +12703,13 @@ bool intel_modeset_probe_defer(struct pci_dev *pdev)
>>  if (vga_switcheroo_client_probe_defer(pdev))
>>  return true;
>>  
>> +/* If the LCD panel has a privacy-screen, wait for it */
>> +privacy_screen = drm_privacy_screen_get(>dev, NULL);
>> +if (IS_ERR(privacy_screen) && PTR_ERR(privacy_screen) == -EPROBE_DEFER)
>> +return true;
>> +
>> +drm_privacy_screen_put(privacy_screen);
>> +
>>  return false;
>>  }
>>  
>> diff --git a/drivers/gpu/drm/i915/display/intel_dp.c 
>> b/drivers/gpu/drm/i915/display/intel_dp.c
>> index 74a657ae131a..91207310dc0d 100644
>> --- a/drivers/gpu/drm/i915/display/intel_dp.c
>> +++ b/drivers/gpu/d

Re: [PATCH 05/10] drm/connector: Add a drm_connector privacy-screen helper functions (v2)

2021-10-04 Thread Hans de Goede
Hi,

On 10/4/21 5:22 PM, Ville Syrjälä wrote:
> On Sat, Oct 02, 2021 at 06:36:13PM +0200, Hans de Goede wrote:
>> 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(), update the privacy-screen's
>> sw_state if the connector has a privacy-screen.
>>
>> Changes in v2:
>> - Do not update connector->state->privacy_screen_sw_state on
>>   atomic-commits.
>> - Change drm_connector_update_privacy_screen() to take drm_connector_state
>>   as argument instead of a full drm_atomic_state. This allows the helper
>>   to be called by drivers when they are enabling crtcs/encoders/connectors.
>>
>> Reviewed-by: Emil Velikov 
>> Reviewed-by: Lyude Paul 
>> Signed-off-by: Hans de Goede 
>> ---
>>  drivers/gpu/drm/drm_connector.c | 102 
>>  include/drm/drm_connector.h |  11 
>>  2 files changed, 113 insertions(+)
>>
>> diff --git a/drivers/gpu/drm/drm_connector.c 
>> b/drivers/gpu/drm/drm_connector.c
>> index b2f1f1b1bfb4..00cf3b6135f6 100644
>> --- a/drivers/gpu/drm/drm_connector.c
>> +++ b/drivers/gpu/drm/drm_connector.c
>> @@ -28,6 +28,7 @@
>>  #include 
>>  #include 
>>  #include 
>> +#include 
>>  #include 
>>  
>>  #include 
>> @@ -462,6 +463,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;
>> @@ -543,6 +549,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,
>> +   >privacy_screen_notifier);
>> +
>>  mutex_lock(_list_lock);
>>  list_add_tail(>global_connector_list_entry, _list);
>>  mutex_unlock(_list_lock);
>> @@ -578,6 +588,11 @@ void drm_connector_unregister(struct drm_connector 
>> *connector)
>>  list_del_init(>global_connector_list_entry);
>>  mutex_unlock(_list_lock);
>>  
>> +if (connector->privacy_screen)
>> +drm_privacy_screen_unregister_notifier(
>> +connector->privacy_screen,
>> +>privacy_screen_notifier);
>> +
>>  if (connector->funcs->early_unregister)
>>  connector->funcs->early_unregister(connector);
>>  
>> @@ -2442,6 +2457,93 @@ 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, bool set_sw_state)
>> +{
>> +enum drm_privacy_screen_status sw_state, hw_state;
>> +
>> +drm_privacy_screen_get_state(connector->privacy_screen,
>> + _state, _state);
>> +
>> +if (set_sw_state)
>> +connector->state->privacy_screen_sw_state = sw_state;
>> +drm_object_property_set_value(>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(>mode_config.connection_mutex, NULL);
>> +drm_connector_update_privacy_screen_properties(connector, true);
> 
> This thing still seems pretty un

Re: Handling DRM master transitions cooperatively

2021-10-02 Thread Hans de Goede
Hi,

On 10/1/21 6:33 PM, Simon Ser wrote:
> On Wednesday, September 22nd, 2021 at 11:21, Hans de Goede 
>  wrote:
> 
>> I would be happy to work on the plymouth side of this, so that we
>> have at least one consumer of such a flag lined up for merging.
> 
> Do you have plans to work on the kernel side part of this?

No I don't have any plans to work on the kernel side of this.

> If so, feel free to
> CC me for a review. If not, let me know if you'd like to switch roles, I could
> work on a patch.

I would be happy to review any kernel patches for this
(together with adding support to plymouth for this).

Regards,

Hans



[PATCH 06/10] platform/x86: thinkpad_acpi: Add hotkey_notify_extended_hotkey() helper

2021-10-02 Thread Hans de Goede
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...).

Reviewed-by: Emil Velikov 
Reviewed-by: Lyude Paul 
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 50ff04c84650..83c88a8ebaf2 100644
--- a/drivers/platform/x86/thinkpad_acpi.c
+++ b/drivers/platform/x86/thinkpad_acpi.c
@@ -3885,6 +3885,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)
@@ -3919,17 +3937,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



[PATCH 08/10] platform/x86: thinkpad_acpi: Register a privacy-screen device

2021-10-02 Thread Hans de Goede
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 a new standardized
interface which all user-space code should use to query and control
the privacy-screen.

Reviewed-by: Emil Velikov 
Reviewed-by: Lyude Paul 
Signed-off-by: Hans de Goede 
---
Changes in v3:
- On receiving a TP_HKEY_EV_PRIVACYGUARD_TOGGLE event only call
  drm_privacy_screen_call_notifier_chain() if the privacy-screen state
  has actually changed

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 | 97 +---
 2 files changed, 74 insertions(+), 25 deletions(-)

diff --git a/drivers/platform/x86/Kconfig b/drivers/platform/x86/Kconfig
index e21ea3d23e6f..20208207e366 100644
--- a/drivers/platform/x86/Kconfig
+++ b/drivers/platform/x86/Kconfig
@@ -501,7 +501,9 @@ config THINKPAD_ACPI
depends on ACPI_VIDEO || ACPI_VIDEO = n
depends on BACKLIGHT_CLASS_DEVICE
depends on I2C
+   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 b8f2556c4797..291cd18c9c8f 100644
--- a/drivers/platform/x86/thinkpad_acpi.c
+++ b/drivers/platform/x86/thinkpad_acpi.c
@@ -73,6 +73,7 @@
 #include 
 #include 
 #include 
+#include 
 #include "dual_accel_detect.h"
 
 /* ThinkPad CMOS commands */
@@ -157,6 +158,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 */
@@ -3889,6 +3891,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.
@@ -9819,30 +9827,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(>lock)))
+   return -EIO;
+
if (!acpi_evalf(lcdshadow_set_handle, , 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, , 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;
@@ -9850,36 +9868,44 @@ static int tpacpi_lcdshadow_init(struct ibm_init_struct 
*iibm)
 
status1 = acpi_get_handle(hkey_handle, "GSSS", _get_handle);
status2 = acpi_get_handle(hkey_handle, "", _set_handle);
-   if (ACPI_FAILURE(status1) || ACPI_FAILURE(status2)) {
-   lcdshadow_state = -ENODEV;
+   if (

[PATCH 09/10] drm/i915: Add intel_modeset_probe_defer() helper

2021-10-02 Thread Hans de Goede
The upcoming privacy-screen support adds another check for
deferring probe till some other drivers have bound first.

Factor out the current vga_switcheroo_client_probe_defer() check
into an intel_modeset_probe_defer() helper, so that further
probe-deferral checks can be added there.

Signed-off-by: Hans de Goede 
---
 drivers/gpu/drm/i915/display/intel_display.c | 13 +
 drivers/gpu/drm/i915/display/intel_display.h |  1 +
 drivers/gpu/drm/i915/i915_pci.c  |  9 ++---
 3 files changed, 16 insertions(+), 7 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_display.c 
b/drivers/gpu/drm/i915/display/intel_display.c
index 60b2bc3ad011..e67f3207ba54 100644
--- a/drivers/gpu/drm/i915/display/intel_display.c
+++ b/drivers/gpu/drm/i915/display/intel_display.c
@@ -32,6 +32,7 @@
 #include 
 #include 
 #include 
+#include 
 
 #include 
 #include 
@@ -12690,6 +12691,18 @@ void intel_modeset_driver_remove_nogem(struct 
drm_i915_private *i915)
intel_bios_driver_remove(i915);
 }
 
+bool intel_modeset_probe_defer(struct pci_dev *pdev)
+{
+   /*
+* apple-gmux is needed on dual GPU MacBook Pro
+* to probe the panel if we're the inactive GPU.
+*/
+   if (vga_switcheroo_client_probe_defer(pdev))
+   return true;
+
+   return false;
+}
+
 void intel_display_driver_register(struct drm_i915_private *i915)
 {
if (!HAS_DISPLAY(i915))
diff --git a/drivers/gpu/drm/i915/display/intel_display.h 
b/drivers/gpu/drm/i915/display/intel_display.h
index 3028072c2cf3..d3d34acb6c08 100644
--- a/drivers/gpu/drm/i915/display/intel_display.h
+++ b/drivers/gpu/drm/i915/display/intel_display.h
@@ -633,6 +633,7 @@ void intel_display_driver_register(struct drm_i915_private 
*i915);
 void intel_display_driver_unregister(struct drm_i915_private *i915);
 
 /* modesetting */
+bool intel_modeset_probe_defer(struct pci_dev *pdev);
 void intel_modeset_init_hw(struct drm_i915_private *i915);
 int intel_modeset_init_noirq(struct drm_i915_private *i915);
 int intel_modeset_init_nogem(struct drm_i915_private *i915);
diff --git a/drivers/gpu/drm/i915/i915_pci.c b/drivers/gpu/drm/i915/i915_pci.c
index d4a6a9dcf182..cf4ad648b742 100644
--- a/drivers/gpu/drm/i915/i915_pci.c
+++ b/drivers/gpu/drm/i915/i915_pci.c
@@ -22,8 +22,6 @@
  *
  */
 
-#include 
-
 #include 
 #include 
 
@@ -1187,11 +1185,8 @@ static int i915_pci_probe(struct pci_dev *pdev, const 
struct pci_device_id *ent)
if (PCI_FUNC(pdev->devfn))
return -ENODEV;
 
-   /*
-* apple-gmux is needed on dual GPU MacBook Pro
-* to probe the panel if we're the inactive GPU.
-*/
-   if (vga_switcheroo_client_probe_defer(pdev))
+   /* Detect if we need to wait for other drivers early on */
+   if (intel_modeset_probe_defer(pdev))
return -EPROBE_DEFER;
 
err = i915_driver_probe(pdev, ent);
-- 
2.31.1



[PATCH 10/10] drm/i915: Add privacy-screen support (v2)

2021-10-02 Thread Hans de Goede
Add support for eDP panels with a built-in privacy screen using the
new drm_privacy_screen class.

Changes in v2:
- Call drm_connector_update_privacy_screen() from
  intel_enable_ddi_dp() / intel_ddi_update_pipe_dp() instead of adding a
  for_each_new_connector_in_state() loop to intel_atomic_commit_tail()
- Move the probe-deferral check to the intel_modeset_probe_defer() helper

Signed-off-by: Hans de Goede 
---
 drivers/gpu/drm/i915/display/intel_atomic.c  |  1 +
 drivers/gpu/drm/i915/display/intel_ddi.c |  3 +++
 drivers/gpu/drm/i915/display/intel_display.c | 10 ++
 drivers/gpu/drm/i915/display/intel_dp.c  | 10 ++
 4 files changed, 24 insertions(+)

diff --git a/drivers/gpu/drm/i915/display/intel_atomic.c 
b/drivers/gpu/drm/i915/display/intel_atomic.c
index b4e7ac51aa31..a62550711e98 100644
--- a/drivers/gpu/drm/i915/display/intel_atomic.c
+++ b/drivers/gpu/drm/i915/display/intel_atomic.c
@@ -139,6 +139,7 @@ int intel_digital_connector_atomic_check(struct 
drm_connector *conn,
new_conn_state->base.picture_aspect_ratio != 
old_conn_state->base.picture_aspect_ratio ||
new_conn_state->base.content_type != 
old_conn_state->base.content_type ||
new_conn_state->base.scaling_mode != 
old_conn_state->base.scaling_mode ||
+   new_conn_state->base.privacy_screen_sw_state != 
old_conn_state->base.privacy_screen_sw_state ||
!drm_connector_atomic_hdr_metadata_equal(old_state, new_state))
crtc_state->mode_changed = true;
 
diff --git a/drivers/gpu/drm/i915/display/intel_ddi.c 
b/drivers/gpu/drm/i915/display/intel_ddi.c
index 51cd0420e00e..e4496c830a35 100644
--- a/drivers/gpu/drm/i915/display/intel_ddi.c
+++ b/drivers/gpu/drm/i915/display/intel_ddi.c
@@ -25,6 +25,7 @@
  *
  */
 
+#include 
 #include 
 
 #include "i915_drv.h"
@@ -3022,6 +3023,7 @@ static void intel_enable_ddi_dp(struct intel_atomic_state 
*state,
if (port == PORT_A && DISPLAY_VER(dev_priv) < 9)
intel_dp_stop_link_train(intel_dp, crtc_state);
 
+   drm_connector_update_privacy_screen(conn_state);
intel_edp_backlight_on(crtc_state, conn_state);
 
if (!dig_port->lspcon.active || dig_port->dp.has_hdmi_sink)
@@ -3247,6 +3249,7 @@ static void intel_ddi_update_pipe_dp(struct 
intel_atomic_state *state,
intel_drrs_update(intel_dp, crtc_state);
 
intel_backlight_update(state, encoder, crtc_state, conn_state);
+   drm_connector_update_privacy_screen(conn_state);
 }
 
 void intel_ddi_update_pipe(struct intel_atomic_state *state,
diff --git a/drivers/gpu/drm/i915/display/intel_display.c 
b/drivers/gpu/drm/i915/display/intel_display.c
index e67f3207ba54..9a5dbe51458d 100644
--- a/drivers/gpu/drm/i915/display/intel_display.c
+++ b/drivers/gpu/drm/i915/display/intel_display.c
@@ -42,6 +42,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -12693,6 +12694,8 @@ void intel_modeset_driver_remove_nogem(struct 
drm_i915_private *i915)
 
 bool intel_modeset_probe_defer(struct pci_dev *pdev)
 {
+   struct drm_privacy_screen *privacy_screen;
+
/*
 * apple-gmux is needed on dual GPU MacBook Pro
 * to probe the panel if we're the inactive GPU.
@@ -12700,6 +12703,13 @@ bool intel_modeset_probe_defer(struct pci_dev *pdev)
if (vga_switcheroo_client_probe_defer(pdev))
return true;
 
+   /* If the LCD panel has a privacy-screen, wait for it */
+   privacy_screen = drm_privacy_screen_get(>dev, NULL);
+   if (IS_ERR(privacy_screen) && PTR_ERR(privacy_screen) == -EPROBE_DEFER)
+   return true;
+
+   drm_privacy_screen_put(privacy_screen);
+
return false;
 }
 
diff --git a/drivers/gpu/drm/i915/display/intel_dp.c 
b/drivers/gpu/drm/i915/display/intel_dp.c
index 74a657ae131a..91207310dc0d 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"
@@ -4808,6 +4809,7 @@ static bool intel_edp_init_connector(struct intel_dp 
*intel_dp,
struct drm_connector *connector = _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;
@@ -4902,6 +4904,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->dev, NULL);
+   if (!IS_ERR(privacy_screen)) {
+   drm_connector_attach_privacy_screen_provider(connector,
+privacy_screen);
+   } else if (PTR_ERR(pr

[PATCH 07/10] platform/x86: thinkpad_acpi: Get privacy-screen / lcdshadow ACPI handles only once

2021-10-02 Thread Hans de Goede
Get the privacy-screen / lcdshadow ACPI handles once and cache them,
instead of retrieving them every time we need them.

Reviewed-by: Emil Velikov 
Reviewed-by: Lyude Paul 
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 83c88a8ebaf2..b8f2556c4797 100644
--- a/drivers/platform/x86/thinkpad_acpi.c
+++ b/drivers/platform/x86/thinkpad_acpi.c
@@ -9819,19 +9819,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, "", 
_shadow_handle))) {
-   pr_warn("Thinkpad ACPI has no %s interface.\n", "");
-   return -EIO;
-   }
-
-   if (!acpi_evalf(set_shadow_handle, , NULL, "dd", (int)state))
+   if (!acpi_evalf(lcdshadow_set_handle, , NULL, "dd", (int)state))
return -EIO;
 
lcdshadow_state = state;
@@ -9849,15 +9845,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", 
_shadow_handle))) {
+   status1 = acpi_get_handle(hkey_handle, "GSSS", _get_handle);
+   status2 = acpi_get_handle(hkey_handle, "", _set_handle);
+   if (ACPI_FAILURE(status1) || ACPI_FAILURE(status2)) {
lcdshadow_state = -ENODEV;
return 0;
}
 
-   if (!acpi_evalf(get_shadow_handle, , NULL, "dd", 0)) {
+   if (!acpi_evalf(lcdshadow_get_handle, , NULL, "dd", 0)) {
lcdshadow_state = -EIO;
return -EIO;
}
-- 
2.31.1



[PATCH 05/10] drm/connector: Add a drm_connector privacy-screen helper functions (v2)

2021-10-02 Thread Hans de Goede
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(), update the privacy-screen's
sw_state if the connector has a privacy-screen.

Changes in v2:
- Do not update connector->state->privacy_screen_sw_state on
  atomic-commits.
- Change drm_connector_update_privacy_screen() to take drm_connector_state
  as argument instead of a full drm_atomic_state. This allows the helper
  to be called by drivers when they are enabling crtcs/encoders/connectors.

Reviewed-by: Emil Velikov 
Reviewed-by: Lyude Paul 
Signed-off-by: Hans de Goede 
---
 drivers/gpu/drm/drm_connector.c | 102 
 include/drm/drm_connector.h |  11 
 2 files changed, 113 insertions(+)

diff --git a/drivers/gpu/drm/drm_connector.c b/drivers/gpu/drm/drm_connector.c
index b2f1f1b1bfb4..00cf3b6135f6 100644
--- a/drivers/gpu/drm/drm_connector.c
+++ b/drivers/gpu/drm/drm_connector.c
@@ -28,6 +28,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 
 #include 
@@ -462,6 +463,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;
@@ -543,6 +549,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,
+  >privacy_screen_notifier);
+
mutex_lock(_list_lock);
list_add_tail(>global_connector_list_entry, _list);
mutex_unlock(_list_lock);
@@ -578,6 +588,11 @@ void drm_connector_unregister(struct drm_connector 
*connector)
list_del_init(>global_connector_list_entry);
mutex_unlock(_list_lock);
 
+   if (connector->privacy_screen)
+   drm_privacy_screen_unregister_notifier(
+   connector->privacy_screen,
+   >privacy_screen_notifier);
+
if (connector->funcs->early_unregister)
connector->funcs->early_unregister(connector);
 
@@ -2442,6 +2457,93 @@ 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, bool set_sw_state)
+{
+   enum drm_privacy_screen_status sw_state, hw_state;
+
+   drm_privacy_screen_get_state(connector->privacy_screen,
+_state, _state);
+
+   if (set_sw_state)
+   connector->state->privacy_screen_sw_state = sw_state;
+   drm_object_property_set_value(>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(>mode_config.connection_mutex, NULL);
+   drm_connector_update_privacy_screen_properties(connector, true);
+   drm_modeset_unlock(>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(
+

[PATCH 04/10] drm/privacy-screen: Add notifier support (v2)

2021-10-02 Thread Hans de Goede
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.

Changes in v2:
- Drop WARN_ON(mutex_is_locked(>lock)) check in
  drm_privacy_screen_call_notifier_chain() it may be locked by
  another thread, which would lead to a false-positive triggering
  of the check

Reviewed-by: Emil Velikov 
Reviewed-by: Lyude Paul 
Signed-off-by: Hans de Goede 
---
 drivers/gpu/drm/drm_privacy_screen.c  | 64 +++
 include/drm/drm_privacy_screen_consumer.h | 15 ++
 include/drm/drm_privacy_screen_driver.h   |  4 ++
 3 files changed, 83 insertions(+)

diff --git a/drivers/gpu/drm/drm_privacy_screen.c 
b/drivers/gpu/drm/drm_privacy_screen.c
index 183a6011adf0..beaf99e9120a 100644
--- a/drivers/gpu/drm/drm_privacy_screen.c
+++ b/drivers/gpu/drm/drm_privacy_screen.c
@@ -257,6 +257,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(>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(>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,
@@ -354,6 +397,7 @@ struct drm_privacy_screen *drm_privacy_screen_register(
return ERR_PTR(-ENOMEM);
 
mutex_init(>lock);
+   BLOCKING_INIT_NOTIFIER_HEAD(>notifier_head);
 
priv->dev.class = drm_class;
priv->dev.type = _privacy_screen_type;
@@ -401,3 +445,23 @@ void drm_privacy_screen_unregister(struct 
drm_privacy_screen *priv)
device_unregister(>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)
+{
+   blocking_notifier_call_chain(>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 0cbd23b0453d..7f66a90d15b7 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(stru

[PATCH 03/10] drm/privacy-screen: Add X86 specific arch init code

2021-10-02 Thread Hans de Goede
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.

Reviewed-by: Emil Velikov 
Reviewed-by: Lyude Paul 
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 788fc37096f6..12997ca5670d 100644
--- a/drivers/gpu/drm/Makefile
+++ b/drivers/gpu/drm/Makefile
@@ -32,7 +32,7 @@ drm-$(CONFIG_OF) += drm_of.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
 
 obj-$(CONFIG_DRM_DP_AUX_BUS) += drm_dp_aux_bus.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 = , };
+   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, _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", , );
+   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(_lookup);
+   break;
+   }
+}
+
+void drm_privacy_screen_lookup_exit(void)
+{
+   if (arch_lookup.provider)
+   drm_privacy_screen_lookup_remove(_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



[PATCH 01/10] drm/connector: Add support for privacy-screen properties (v4)

2021-10-02 Thread Hans de Goede
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 
Acked-by: Pekka Paalanen 
Reviewed-by: Mario Limonciello 
Reviewed-by: Emil Velikov 
Reviewed-by: Lyude Paul 
Co-developed-by: Hans de Goede 
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 1ef7951ded5e..d14bf1c35d7e 100644
--- a/Documentation/gpu/drm-kms.rst
+++ b/Documentation/gpu/drm-kms.rst
@@ -506,6 +506,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 909f31833181..cdd31fc78bfc 100644
--- a/drivers/gpu/drm/drm_atomic_uapi.c
+++ b/drivers/gpu/drm/drm_atomic_uapi.c
@@ -797,6 +797,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);
@@ -874,6 +876,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 3bc782b630b9..b2f1f1b1bfb4 100644
--- a/drivers/gpu/drm/drm_connector.c
+++ b/drivers/gpu/drm/drm_connector.c
@@ -1264,6 +1264,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
+ * 

[PATCH 02/10] drm: Add privacy-screen class (v4)

2021-10-02 Thread Hans de Goede
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

Changes in v3:
- Make the static inline drm_privacy_screen_get_state() stub set sw_state
  and hw_state to PRIVACY_SCREEN_DISABLED to squelch an uninitialized
  variable warning when CONFIG_DRM_PRIVICAY_SCREEN is not set

Changes in v4:
- Make drm_privacy_screen_set_sw_state() skip calling out to the hw if
  hw_state == new_sw_state

Reviewed-by: Emil Velikov 
Reviewed-by: Lyude Paul 
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  | 403 ++
 include/drm/drm_privacy_screen_consumer.h |  50 +++
 include/drm/drm_privacy_screen_driver.h   |  80 +
 include/drm/drm_privacy_screen_machine.h  |  41 +++
 9 files changed, 606 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 ec2f65b31930..5bb55ec1b9b5 100644
--- a/Documentation/gpu/drm-kms-helpers.rst
+++ b/Documentation/gpu/drm-kms-helpers.rst
@@ -435,3 +435,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 e3556c63081d..0e70c81d3ddc 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -6421,6 +6421,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 2a926d0de423..c686c08447ac 100644
--- a/drivers/gpu/drm/Kconfig
+++ b/drivers/gpu/drm/Kconfig
@@ -481,3 +481,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 0dff40bb863c..788fc37096f6 100644
--- a/drivers/gpu/drm/Makefile
+++ b/drivers/gpu/drm/Makefile
@@ -32,6 +32,7 @@ drm-$(CONFIG_OF) += drm_of.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
 
 obj-$(CONFIG_DRM_DP_AUX_BUS) += drm_dp_aux_bus.o
 
diff --git a/drivers/gpu/drm/drm_drv.c b/drivers/gpu/drm/drm_drv.c
index 7a5097467ba5..dc293b771c3f 100644
--- a/drivers/gpu/drm/drm_drv.c
+++ b/drivers/gpu/drm/drm_drv.c
@@ -43,6 +43,7 @@
 #include 
 #include 
 #include 
+#include 
 
 #include "drm_crtc_internal.h"
 #include "drm_internal.h"
@@ -1029,6 +1030,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 &

[PATCH 00/10] drm: Add privacy-screen class and connector properties

2021-10-02 Thread Hans de Goede
Hi all,

Here is a new version of my privacy-screen series, addressing the
(few) review-remarks from the version posted on September 6th.
This new version contains the following changes:

- drm: Add privacy-screen class (v4)
 - Make drm_privacy_screen_set_sw_state() skip calling out to the hw if
   hw_state == new_sw_state

- drm/privacy-screen: Add notifier support (v2)
 - Drop WARN_ON(mutex_is_locked(>lock)) check in
   drm_privacy_screen_call_notifier_chain() it may be locked by
   another thread, which would lead to a false-positive triggering
   of the check (change requested by Lyude)

- drm/connector: Add a drm_connector privacy-screen helper functions (v2)
 - Do not update connector->state->privacy_screen_sw_state on
   atomic-commits (change requested by Ville)
 - Change drm_connector_update_privacy_screen() to take drm_connector_state
   as argument instead of a full drm_atomic_state. This allows the helper
   to be called by drivers when they are enabling crtcs/encoders/connectors.

- platform/x86: thinkpad_acpi: Register a privacy-screen device (v3)
 - On receiving a TP_HKEY_EV_PRIVACYGUARD_TOGGLE event only call
   drm_privacy_screen_call_notifier_chain() if the privacy-screen state
   has actually changed

- drm/i915: Add intel_modeset_probe_defer() helper
 - New patch in this version of the series (change requested by Jani)

- drm/i915: Add privacy-screen support (v2)
 - Call drm_connector_update_privacy_screen() from
   intel_enable_ddi_dp() / intel_ddi_update_pipe_dp() instead of adding a
   for_each_new_connector_in_state() loop to intel_atomic_commit_tail()
   (change requested by Ville)
 - Move the probe-deferral check to the intel_modeset_probe_defer() helper
   (change requested by Jani)

With these changes I believe that this series now is fully ready for
merging, but the last 2 patches need to be (re)reviewed.

Here is some more info from the previous cover-letters:

The first userspace consumer of the new properties is now fully ready
for merging (it is just waiting for the kernel bits to land first):

 - https://gitlab.gnome.org/GNOME/gsettings-desktop-schemas/-/merge_requests/49
 - https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1952
 - https://gitlab.gnome.org/GNOME/gnome-control-center/-/merge_requests/1032

The new API works as designed and 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 (9):
  drm: Add privacy-screen class (v4)
  drm/privacy-screen: Add X86 specific arch init code
  drm/privacy-screen: Add notifier support (v2)
  drm/connector: Add a drm_connector privacy-screen helper functions
(v2)
  platform/x86: thinkpad_acpi: Add hotkey_notify_extended_hotkey()
helper
  platform/x86: thinkpad_acpi:

Re: [Intel-gfx] [PATCH v2 0/4] drm/dp, drm/i915: Finish basic PWM support for VESA backlight helpers

2021-10-02 Thread Hans de Goede
Hi Lyude,

On 10/2/21 12:53 AM, Lyude Paul wrote:
> When I originally moved all of the VESA backlight code in i915 into DRM
> helpers, one of the things I didn't have the hardware or time for
> testing was machines that used a combination of PWM and DPCD in order to
> control their backlights. This has since then caused some breakages and
> resulted in us disabling DPCD backlight support on such machines. This
> works fine, unless you have a machine that actually needs this
> functionality for backlight controls to work at all. Additionally, we
> will need to support PWM for when we start adding support for VESA's
> product (as in the product of multiplication) control mode for better
> brightness ranges.
> 
> So - let's finally finish up implementing basic support for these types
> of backlights to solve these problems in our DP helpers, along with
> implementing support for this in i915. And since digging into this issue
> solved the last questions we really had about probing backlights in i915
> for the most part, let's update some of the comments around that as
> well!

Backlight control is a topic which I'm reasonably familiar with,
do you want me to review this series for you ?

Regards,

Hans



> 
> Changes:
> * Fixup docs
> * Add patch to stop us from breaking nouveau
> 
> Lyude Paul (4):
>   drm/i915: Add support for panels with VESA backlights with PWM
> enable/disable
>   drm/nouveau/kms/nv50-: Explicitly check DPCD backlights for aux
> enable/brightness
>   drm/dp, drm/i915: Add support for VESA backlights using PWM for
> brightness control
>   drm/i915: Clarify probing order in intel_dp_aux_init_backlight_funcs()
> 
>  drivers/gpu/drm/drm_dp_helper.c   | 75 +++--
>  .../drm/i915/display/intel_dp_aux_backlight.c | 80 ++-
>  drivers/gpu/drm/nouveau/nouveau_backlight.c   |  5 +-
>  include/drm/drm_dp_helper.h   |  7 +-
>  4 files changed, 122 insertions(+), 45 deletions(-)
> 



Re: Handling DRM master transitions cooperatively

2021-09-23 Thread Hans de Goede
Hi,

On 9/23/21 10:23 AM, Pekka Paalanen wrote:
> On Wed, 22 Sep 2021 11:21:16 +0200
> Hans de Goede  wrote:
> 
>> Hi,
>>
>> On 9/22/21 10:56 AM, Pekka Paalanen wrote:
>>> On Tue, 14 Sep 2021 15:45:21 +0200
>>> Daniel Vetter  wrote:
>>>   
>>>> On Thu, Sep 09, 2021 at 10:37:03AM +0300, Pekka Paalanen wrote:  
>>>>> On Wed, 8 Sep 2021 18:27:09 +0200
>>>>> Daniel Vetter  wrote:
>>>>> 
>>>>>> On Wed, Sep 8, 2021 at 9:36 AM Pekka Paalanen  
>>>>>> wrote:
>>>>>>>
>>>>>>> On Tue, 7 Sep 2021 14:42:56 +0200
>>>>>>> Hans de Goede  wrote:
>>>>>>>  
>>>>>>>> Hi,
>>>>>>>>
>>>>>>>> On 9/7/21 12:07 PM, Pekka Paalanen wrote:  
>>>>>>>>> On Fri, 3 Sep 2021 21:08:21 +0200
>>>>>>>>> Dennis Filder  wrote:
>>>>>>>>>  
>>>>>>>>>> Hans de Goede asked me to take a topic from a private discussion 
>>>>>>>>>> here.
>>>>>>>>>> I must also preface that I'm not a graphics person and my knowledge 
>>>>>>>>>> of
>>>>>>>>>> DRI/DRM is cursory at best.
>>>>>>>>>>
>>>>>>>>>> I initiated the conversation with de Goede after learning that the X
>>>>>>>>>> server now supports being started with an open DRM file descriptor
>>>>>>>>>> (this was added for Keith Packard's xlease project).  I wondered if
>>>>>>>>>> that could be used to smoothen the Plymouth->X transition somehow and
>>>>>>>>>> asked de Goede if there were any such plans.  He denied, but 
>>>>>>>>>> mentioned
>>>>>>>>>> that a new ioctl is in the works to prevent the kernel from wiping 
>>>>>>>>>> the
>>>>>>>>>> contents of a frame buffer after a device is closed, and that this
>>>>>>>>>> would help to keep transitions smooth.  
>>>>>>>>>
>>>>>>>>> Hi,
>>>>>>>>>
>>>>>>>>> I believe the kernel is not wiping anything on device close. If
>>>>>>>>> something in the KMS state is wiped, it originates in userspace:
>>>>>>>>>
>>>>>>>>> - Plymouth doing something (e.g. RmFB on an in-use FB will turn the
>>>>>>>>>   output off, you need to be careful to "leak" your FB if you want a
>>>>>>>>>   smooth hand-over)  
>>>>>>>>
>>>>>>>> The "kernel is not wiping anything on device close" is not true,
>>>>>>>> when closing /dev/dri/card# any remaining FBs from the app closing
>>>>>>>> it will be dealt with as if they were RmFB-ed, causing the screen
>>>>>>>> to show what I call "the fallback fb", at least with the i915 driver.  
>>>>>>>> 
>>>>>>>
>>>>>>> No, that's not what should happen AFAIK.
>>>>>>>
>>>>>>> True, all FBs that are not referenced by active CRTCs or planes will
>>>>>>> get freed, since their refcount drops to zero, but those CRTCs and
>>>>>>> planes that are active will remain active and therefore keep their
>>>>>>> reference to the respective FBs and so the FBs remain until replaced or
>>>>>>> turned off explicitly (by e.g. fbcon if you switch to that rather than
>>>>>>> another userspace KMS client). I believe that is the whole reason why
>>>>>>> e.g. DRM_IOCTL_MODE_GETFB2 can be useful, otherwise the next KMS client
>>>>>>> would not have anything to scrape.
>>>>>>>
>>>>>>> danvet, what is the DRM core intention?  
>>>>>>
>>>>>> Historical accidents mostly. There's two things that foil easy
>>>>>> handover to the next compositor:
>>>>>> - RMFB instead of CLOSEFB semantics, especially when closing the
>>>>>> drmfd. This is uapi, so anything we change needs to be opt-in
>>>>>
>>>>> What 

Re: Handling DRM master transitions cooperatively

2021-09-22 Thread Hans de Goede
Hi,

On 9/22/21 10:56 AM, Pekka Paalanen wrote:
> On Tue, 14 Sep 2021 15:45:21 +0200
> Daniel Vetter  wrote:
> 
>> On Thu, Sep 09, 2021 at 10:37:03AM +0300, Pekka Paalanen wrote:
>>> On Wed, 8 Sep 2021 18:27:09 +0200
>>> Daniel Vetter  wrote:
>>>   
>>>> On Wed, Sep 8, 2021 at 9:36 AM Pekka Paalanen  wrote: 
>>>>  
>>>>>
>>>>> On Tue, 7 Sep 2021 14:42:56 +0200
>>>>> Hans de Goede  wrote:
>>>>>
>>>>>> Hi,
>>>>>>
>>>>>> On 9/7/21 12:07 PM, Pekka Paalanen wrote:
>>>>>>> On Fri, 3 Sep 2021 21:08:21 +0200
>>>>>>> Dennis Filder  wrote:
>>>>>>>
>>>>>>>> Hans de Goede asked me to take a topic from a private discussion here.
>>>>>>>> I must also preface that I'm not a graphics person and my knowledge of
>>>>>>>> DRI/DRM is cursory at best.
>>>>>>>>
>>>>>>>> I initiated the conversation with de Goede after learning that the X
>>>>>>>> server now supports being started with an open DRM file descriptor
>>>>>>>> (this was added for Keith Packard's xlease project).  I wondered if
>>>>>>>> that could be used to smoothen the Plymouth->X transition somehow and
>>>>>>>> asked de Goede if there were any such plans.  He denied, but mentioned
>>>>>>>> that a new ioctl is in the works to prevent the kernel from wiping the
>>>>>>>> contents of a frame buffer after a device is closed, and that this
>>>>>>>> would help to keep transitions smooth.
>>>>>>>
>>>>>>> Hi,
>>>>>>>
>>>>>>> I believe the kernel is not wiping anything on device close. If
>>>>>>> something in the KMS state is wiped, it originates in userspace:
>>>>>>>
>>>>>>> - Plymouth doing something (e.g. RmFB on an in-use FB will turn the
>>>>>>>   output off, you need to be careful to "leak" your FB if you want a
>>>>>>>   smooth hand-over)
>>>>>>
>>>>>> The "kernel is not wiping anything on device close" is not true,
>>>>>> when closing /dev/dri/card# any remaining FBs from the app closing
>>>>>> it will be dealt with as if they were RmFB-ed, causing the screen
>>>>>> to show what I call "the fallback fb", at least with the i915 driver.
>>>>>
>>>>> No, that's not what should happen AFAIK.
>>>>>
>>>>> True, all FBs that are not referenced by active CRTCs or planes will
>>>>> get freed, since their refcount drops to zero, but those CRTCs and
>>>>> planes that are active will remain active and therefore keep their
>>>>> reference to the respective FBs and so the FBs remain until replaced or
>>>>> turned off explicitly (by e.g. fbcon if you switch to that rather than
>>>>> another userspace KMS client). I believe that is the whole reason why
>>>>> e.g. DRM_IOCTL_MODE_GETFB2 can be useful, otherwise the next KMS client
>>>>> would not have anything to scrape.
>>>>>
>>>>> danvet, what is the DRM core intention?
>>>>
>>>> Historical accidents mostly. There's two things that foil easy
>>>> handover to the next compositor:
>>>> - RMFB instead of CLOSEFB semantics, especially when closing the
>>>> drmfd. This is uapi, so anything we change needs to be opt-in  
>>>
>>> What does this mean and refer to?
>>>
>>> Are you trying to say, that closing the DRM device fd (freeing the file
>>> description) causes an implicit RmFB on all the FBs tied to that DRM
>>> device file description?
>>>
>>> I never realised that before.  
>>
>> Yes, final close does iterate over fb and do an RMFB. Which is why we've
>> had this discussion whether closefb semantics should be an ADDFB2 flag at
>> creation time instead.
> 
> Hi Daniel,
> 
> such flag would make sense to me.

Hmm, I was thinking having a separate call to mark a FB to switch to
closefb semantics. But both plymouth (because of end of animation)
and GNOME (because a mostly empty gnome-shell needs to be rendered
to avoid leaking privacy sensitive info) will need to prepare a
special FB on exit anyways, so then an ADDFB2 flag would work fine.

I would be happy to work on the plymouth side of this, so that we
have at least one consumer of such a flag lined up for merging.

Regards,

Hans



Re: [PATCH 0/5] lib: devres: Add managed helpers for write-combine setup

2021-09-20 Thread Hans de Goede
Hi,

On 9/20/21 10:01 AM, Thomas Zimmermann wrote:
> Hi
> 
> Am 17.09.21 um 16:47 schrieb Hans de Goede:
>> Hi,
>>
>> On 9/16/21 8:15 PM, Thomas Zimmermann wrote:
>>> Add devm_arch_phys_wc_add() and devm_arch_io_reserve_memtype_wc() for
>>> automatic cleanup of writecombine setup.
>>>
>>> Several DRM drivers use the non-managed functions for setting their
>>> framebuffer memory to write-combine access. Convert ast, mgag200 and
>>> vboxvideo. Remove rsp clean-up code form drivers.
>>>
>>> Tested on mgag200 hardware.
>>>
>>> Thomas Zimmermann (5):
>>>    lib: devres: Add managed arch_phys_wc_add()
>>>    lib: devres: Add managed arch_io_reserve_memtype_wc()
>>>    drm/ast: Use managed interfaces for framebuffer write combining
>>>    drm/mgag200: Use managed interfaces for framebuffer write combining
>>>    drm/vboxvideo: Use managed interfaces for framebuffer write combining
>>
>> Thanks, the entire series looks good to me:
>>
>> Reviewed-by: Hans de Goede 
>>
>> For the series.
> 
> Thanks. Let me know if I can review some DRM code for you, as Daniel 
> suggested.

Thank you for the offer, ATM I don't have anything queued up in need of review,
but I will probably make use of your offer in the future :)
Regards,

Hans



Re: [PATCH 9/9] drm/i915: Add privacy-screen support

2021-09-17 Thread Hans de Goede
Hi,

On 9/17/21 6:25 PM, Ville Syrjälä wrote:
> On Fri, Sep 17, 2021 at 04:37:14PM +0200, Hans de Goede wrote:
>> Hi,
>>
>> On 9/16/21 3:45 PM, Ville Syrjälä wrote:
>>> On Mon, Sep 06, 2021 at 09:35:19AM +0200, Hans de Goede wrote:
>>>> 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(>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.
>>>
>>> Pretty sure the full atomic state is plumbed all the way
>>> down these days.
>>
>> Including the old state? AFAICT the old-state is being thrown away
>> from drm_atomic_helper_swap_state(),
> 
> No. That's just when those annoying foo_state->state pointers get
> clobbered. We've been moving away from using those and just
> plumbing the entire atomic state everywhere.
> 
> Nothing actually gets freed until the whole drm_atomic_state gets
> nuked after the commit is done.
> 
>> so if we do this in a different
>> place then we don't have access to the old-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.
>>>
>>> I doubt anyone is going to care about a bit of overhead for a modeset.
>>
>> But this is not a modeset, this is more like changing the backlight 
>> brightness,
>> atm the code does not set the needs_modeset when only the privacy-screen
>> sw-state has changed.
>>
>> Also in my experience the firmware (AML) code which we end up calling
>> for this is not the highest quality code, often it has interesting
>> issues / unhandled corner cases. So in my experience with ACPI we
>> really should try to avoid these calls unless we absolutely must make them,
>> but I guess not making unnecessary calls is something which could be handled
>> inside the actual privacy-screen driver instead.
>>
>>> The usual rule is that a modeset doesn't skip anything. That way we
>>> can be 100% sure we remeber to update everythinbg. For fastsets I guess
>>> one could argue skipping it if not needed, but not sure even that is
>>> warranted.
>>
>> Right, but again this is not a full modeset.
> 
> In general fastset is is just an optimized modeset. Userspace asked
> for a modeset, but we noticed it doesn't need it. I don't think
> there is a particular expectation that it's super fast.
> 
> But if this is really annoyingly slow in some actual usecase

Yeah these acpi-calls might take like a 100 ms easily, so
we really want to avoid it if it is not necessary.

> then
> one way to avoid that need to compare against the old state is just
> introduce another foo_changed flag.

Ok, so I have the feeling that you have an idea of how you think this
should be done / how this code should look instead of what I have
currently.

Can you perhaps provide a rough sketch / description of how you
think this should be done (instead of the current implementation) ?

Should I do the update from the the encoder update_pipe (for fast-sets)
and enable (for full modesets) callbacks instead as I mention in
the commit message ?

And since I still only want to do the call if there is an actual
change, where could I best do the old / new sw_state change cmp to
set the new foo_changed flag?




> 
>>
>>>
>>> The current code you have in there is cettainly 110% dodgy. Since the
>>> sw_state is stored in the connector state I presume it's at least
>>> trying to be an atomic property, which means you shouldn't go poking
>>> at it after the swap_state ever.
>>
>> It is not being poked,

Re: [PATCH 0/5] lib: devres: Add managed helpers for write-combine setup

2021-09-17 Thread Hans de Goede
Hi,

On 9/16/21 8:15 PM, Thomas Zimmermann wrote:
> Add devm_arch_phys_wc_add() and devm_arch_io_reserve_memtype_wc() for
> automatic cleanup of writecombine setup.
> 
> Several DRM drivers use the non-managed functions for setting their
> framebuffer memory to write-combine access. Convert ast, mgag200 and
> vboxvideo. Remove rsp clean-up code form drivers.
> 
> Tested on mgag200 hardware.
> 
> Thomas Zimmermann (5):
>   lib: devres: Add managed arch_phys_wc_add()
>   lib: devres: Add managed arch_io_reserve_memtype_wc()
>   drm/ast: Use managed interfaces for framebuffer write combining
>   drm/mgag200: Use managed interfaces for framebuffer write combining
>   drm/vboxvideo: Use managed interfaces for framebuffer write combining

Thanks, the entire series looks good to me:

Reviewed-by: Hans de Goede 

For the series.

Regards,

Hans



Re: [PATCH 9/9] drm/i915: Add privacy-screen support

2021-09-17 Thread Hans de Goede
Hi,

On 9/16/21 3:45 PM, Ville Syrjälä wrote:
> On Mon, Sep 06, 2021 at 09:35:19AM +0200, Hans de Goede wrote:
>> 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(>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.
> 
> Pretty sure the full atomic state is plumbed all the way
> down these days.

Including the old state? AFAICT the old-state is being thrown away
from drm_atomic_helper_swap_state(), so if we do this in a different
place then we don't have access to the old-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.
> 
> I doubt anyone is going to care about a bit of overhead for a modeset.

But this is not a modeset, this is more like changing the backlight brightness,
atm the code does not set the needs_modeset when only the privacy-screen
sw-state has changed.

Also in my experience the firmware (AML) code which we end up calling
for this is not the highest quality code, often it has interesting
issues / unhandled corner cases. So in my experience with ACPI we
really should try to avoid these calls unless we absolutely must make them,
but I guess not making unnecessary calls is something which could be handled
inside the actual privacy-screen driver instead.

> The usual rule is that a modeset doesn't skip anything. That way we
> can be 100% sure we remeber to update everythinbg. For fastsets I guess
> one could argue skipping it if not needed, but not sure even that is
> warranted.

Right, but again this is not a full modeset.

> 
> The current code you have in there is cettainly 110% dodgy. Since the
> sw_state is stored in the connector state I presume it's at least
> trying to be an atomic property, which means you shouldn't go poking
> at it after the swap_state ever.

It is not being poked, it is only being read, also this is happening
before swap_state.

Note I'm open for suggestions to handle this differently,
including changing the drm_connector_update_privacy_screen()
helper which currently relies on being passed the state before swap_state
is called:

void drm_connector_update_privacy_screen(struct drm_connector *connector,
 struct drm_atomic_state *state)
{
struct drm_connector_state *new_connector_state, *old_connector_state;
int ret;

if (!connector->privacy_screen)
return;

new_connector_state = drm_atomic_get_new_connector_state(state, 
connector);
old_connector_state = drm_atomic_get_old_connector_state(state, 
connector);

if (new_connector_state->privacy_screen_sw_state ==
old_connector_state->privacy_screen_sw_state)
return;

ret = drm_privacy_screen_set_sw_state(connector->privacy_screen,
new_connector_state->privacy_screen_sw_state);
if (ret) {
drm_err(connector->dev, "Error updating privacy-screen 
sw_state\n");
return;
}

So if you have any suggestions how to do this differently, please let me know
and I will take a shot at implementing those suggestions.

Please keep in mind that the drm_privacy_screen_set_sw_state() call also
needs to happens when just the connector_state->privacy_screen_sw_state changes,
which is not a reason to do a full modeset (iow needs_modeset maybe 0 during
the commit)

Regards,

Hans





Re: [PATCH 9/9] drm/i915: Add privacy-screen support

2021-09-17 Thread Hans de Goede
Hi,

On 9/16/21 4:04 PM, Ville Syrjälä wrote:
> On Thu, Sep 16, 2021 at 12:40:11PM +0300, Jani Nikula wrote:
>>
>> Cc: Ville for input here, see question inline.
>>
>> On Mon, 06 Sep 2021, Hans de Goede  wrote:
>>> 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(>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.
>>>
>>> Reviewed-by: Emil Velikov 
>>> 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 5560d2f4c352..7285873d329a 100644
>>> --- a/drivers/gpu/drm/i915/display/intel_display.c
>>> +++ b/drivers/gpu/drm/i915/display/intel_display.c
>>> @@ -10140,6 +10140,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;
>>> @@ -10237,6 +10239,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(>base, connector, 
>>> new_connector_state, i)
>>> +   drm_connector_update_privacy_screen(connector, >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 7f8e8865048f..3aa2072cccf6 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"
>>> @@ -5217,6 +5218,7 @@ static bool intel_edp_init_connector(struct intel_dp 
>>> *intel_dp,
>>> struct drm_connector *connector = _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;
>>> @@ -5308,6 +5310,14 @@ static bool intel_edp_init_connector(struct intel_dp 
>>> *intel_dp,
>>> fixed_mode->hdisplay, fixed

Re: [PATCH 5/5] drm/vboxvideo: Use managed interfaces for framebuffer write combining

2021-09-16 Thread Hans de Goede
Hi,

On 9/16/21 8:16 PM, Thomas Zimmermann wrote:
> Replace arch_phys_wc_add() with the rsp managed function. Allows for
> removing the cleanup code for memory management
> 
> Signed-off-by: Thomas Zimmermann 

Thanks, patch looks good to me:

Reviewed-by: Hans de Goede 

Regards,

Hans


> ---
>  drivers/gpu/drm/vboxvideo/vbox_drv.c |  5 +
>  drivers/gpu/drm/vboxvideo/vbox_drv.h |  1 -
>  drivers/gpu/drm/vboxvideo/vbox_ttm.c | 17 -
>  3 files changed, 9 insertions(+), 14 deletions(-)
> 
> diff --git a/drivers/gpu/drm/vboxvideo/vbox_drv.c 
> b/drivers/gpu/drm/vboxvideo/vbox_drv.c
> index 2b81cb259d23..a6c81af37345 100644
> --- a/drivers/gpu/drm/vboxvideo/vbox_drv.c
> +++ b/drivers/gpu/drm/vboxvideo/vbox_drv.c
> @@ -69,7 +69,7 @@ static int vbox_pci_probe(struct pci_dev *pdev, const 
> struct pci_device_id *ent)
>  
>   ret = vbox_mode_init(vbox);
>   if (ret)
> - goto err_mm_fini;
> + goto err_hw_fini;
>  
>   ret = vbox_irq_init(vbox);
>   if (ret)
> @@ -87,8 +87,6 @@ static int vbox_pci_probe(struct pci_dev *pdev, const 
> struct pci_device_id *ent)
>   vbox_irq_fini(vbox);
>  err_mode_fini:
>   vbox_mode_fini(vbox);
> -err_mm_fini:
> - vbox_mm_fini(vbox);
>  err_hw_fini:
>   vbox_hw_fini(vbox);
>   return ret;
> @@ -101,7 +99,6 @@ static void vbox_pci_remove(struct pci_dev *pdev)
>   drm_dev_unregister(>ddev);
>   vbox_irq_fini(vbox);
>   vbox_mode_fini(vbox);
> - vbox_mm_fini(vbox);
>   vbox_hw_fini(vbox);
>  }
>  
> diff --git a/drivers/gpu/drm/vboxvideo/vbox_drv.h 
> b/drivers/gpu/drm/vboxvideo/vbox_drv.h
> index 4903b91d7fe4..e77bd6512eb1 100644
> --- a/drivers/gpu/drm/vboxvideo/vbox_drv.h
> +++ b/drivers/gpu/drm/vboxvideo/vbox_drv.h
> @@ -139,7 +139,6 @@ void vbox_mode_fini(struct vbox_private *vbox);
>  void vbox_report_caps(struct vbox_private *vbox);
>  
>  int vbox_mm_init(struct vbox_private *vbox);
> -void vbox_mm_fini(struct vbox_private *vbox);
>  
>  /* vbox_irq.c */
>  int vbox_irq_init(struct vbox_private *vbox);
> diff --git a/drivers/gpu/drm/vboxvideo/vbox_ttm.c 
> b/drivers/gpu/drm/vboxvideo/vbox_ttm.c
> index fd8a53a4d8d6..dc24c2172fd4 100644
> --- a/drivers/gpu/drm/vboxvideo/vbox_ttm.c
> +++ b/drivers/gpu/drm/vboxvideo/vbox_ttm.c
> @@ -13,22 +13,21 @@
>  int vbox_mm_init(struct vbox_private *vbox)
>  {
>   int ret;
> + resource_size_t base, size;
>   struct drm_device *dev = >ddev;
>   struct pci_dev *pdev = to_pci_dev(dev->dev);
>  
> - ret = drmm_vram_helper_init(dev, pci_resource_start(pdev, 0),
> -vbox->available_vram_size);
> + base = pci_resource_start(pdev, 0);
> + size = pci_resource_len(pdev, 0);
> +
> + /* Don't fail on errors, but performance might be reduced. */
> + devm_arch_phys_wc_add(>dev, base, size);
> +
> + ret = drmm_vram_helper_init(dev, base, vbox->available_vram_size);
>   if (ret) {
>   DRM_ERROR("Error initializing VRAM MM; %d\n", ret);
>   return ret;
>   }
>  
> - vbox->fb_mtrr = arch_phys_wc_add(pci_resource_start(pdev, 0),
> -  pci_resource_len(pdev, 0));
>   return 0;
>  }
> -
> -void vbox_mm_fini(struct vbox_private *vbox)
> -{
> - arch_phys_wc_del(vbox->fb_mtrr);
> -}
> 



Re: [PATCH 8/8] usb: typec: altmodes/displayport: Notify drm subsys of hotplug events

2021-09-16 Thread Hans de Goede
Hi,

On 9/16/21 5:20 AM, Stephen Boyd wrote:
> Quoting Hans de Goede (2021-08-17 14:52:01)
>> 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
>> @@ -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 = _altmode_ops;
>>
>> +   fwnode = dev_fwnode(alt->dev.parent->parent); /* typec_port fwnode */
>> +   dp->connector_fwnode = fwnode_find_reference(fwnode, "displayport", 
>> 0);
> 
> I'm trying to figure out how to translate this over to DT bindings.

First of all let me say that it is great that people are looking
into using this functionality outside of the niche application
for which I wrote it.

> Is
> there a binding document for this fwnode reference? If not, can you
> please update
> Documentation/devicetree/bindings/connector/usb-connector.yaml with this
> property?

My use case is some Intel Cherry Trail based mini-laptops which use a
Intel Whiskey Cove PMIC with a FUSB302 Type-C controller + a
PI3USB30532 USB switch, specifically the GPD Win and GPD Pocket
(first generation of each).

These are ACPI/X86 devices so devicetree is not used there, the
connector_fwnode checked here is actually sw_node, this sw_node
reference gets setup here:

drivers/platform/x86/intel/int33fe/intel_cht_int33fe_typec.c

The setup/use of a sw_node reference for this was actually
designed by Heikki (in the Cc already), so he might be a better
person to answer your questions.

With that said, as to your question if I can document this in
usb-connector.yaml, no I cannot (sorry). Since this is a sw_node
setup by X86 code and not a normal devicetree fwnode reference,
atm this is purely a kernel internal API/binding really and the
DT-binding maintainers have repeatedly told me that I should NOT
submit DT-binding updates for these. Only once a real devicetree
user for this shows up will the accept DT-bindings patches for this.

The good news here though is, that if this turns out to be
non-ideal for the devicetree case we can still change things
as long as drivers/platform/x86/intel/int33fe/intel_cht_int33fe_typec.c
also gets updated so as to not break things.

> I think this means that the type-c node would have a 'displayport =
> <_phandle>' property in it that points to the display port hardware
> device that's pumping out the DisplayPort data?

It points to a fwnode belonging to the drm-connector for the DisplayPort
connector/pins to which the Type-C data-lines mux/switch is connected, see:

https://cgit.freedesktop.org/drm-misc/commit/?id=48c429c6d18db115c277b75000152d8fa4cd35d0
https://cgit.freedesktop.org/drm-misc/commit/?id=3d3f7c1e68691574c1d87cd0f9f2348323bc0199
https://cgit.freedesktop.org/drm-intel/commit/?id=a481d0e80eabbc3fed666103744aeaf47f63e708

So this get working with devicetree you would need something like this:

1. Have devicetree-node-s describing video-output connectors, similar
to how we have usb-connector nodes to describe usb-connectors

2. Have your drm/kms driver lookup these video-output-connector of_node-s
and assign them to drm_connector.fwnode, at least for the DP video-output
used.

3. Have the usb-connector node for your Type-C connector (the same of_node
as which has the source-pdos, sink-pdos, etc props) have 

Re: [PATCH 9/9] drm/i915: Add privacy-screen support

2021-09-16 Thread Hans de Goede
Hi,

On 9/16/21 11:40 AM, Jani Nikula wrote:
> 
> Cc: Ville for input here, see question inline.
> 
> On Mon, 06 Sep 2021, Hans de Goede  wrote:
>> 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(>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.
>>
>> Reviewed-by: Emil Velikov 
>> 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 5560d2f4c352..7285873d329a 100644
>> --- a/drivers/gpu/drm/i915/display/intel_display.c
>> +++ b/drivers/gpu/drm/i915/display/intel_display.c
>> @@ -10140,6 +10140,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;
>> @@ -10237,6 +10239,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(>base, connector, 
>> new_connector_state, i)
>> +drm_connector_update_privacy_screen(connector, >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 7f8e8865048f..3aa2072cccf6 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"
>> @@ -5217,6 +5218,7 @@ static bool intel_edp_init_connector(struct intel_dp 
>> *intel_dp,
>>  struct drm_connector *connector = _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;
>> @@ -5308,6 +5310,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->dev, NULL);
>> +if (!IS_ERR(privacy_screen)) {
>> +drm_connector_attach_privacy_screen_provider(connector,
>> + privacy_screen);
>> +} else if (PTR_ERR(privacy_screen) != -ENODEV) 

Re: [PATCH 0/9] drm: Add privacy-screen class and connector properties

2021-09-16 Thread Hans de Goede
Hi,

On 9/15/21 11:12 PM, Lyude Paul wrote:
> OK! Looked over all of these patches. Patches 2 and 4 have some comments that
> should be addressed, but otherwise this series is:
> 
> Reviewed-by: Lyude Paul 

Thank you!

> Let me know when/if you need help pushing this upstream

My plan was to just straight forward push the entire series to
drm-misc-next. The only non drm bits are the 
drivers/platform/x86/thinkpad_acpi.c
changes and I'm the drivers/platform/x86 subsys-maintainer and this
plan has my blessing :)

That only leaves the last patch in the series:
"drm/i915: Add privacy-screen support" 

As something which could potentially be troublesome. I can also
leave that out, while pushing the test to drm-misc-next and then
push the i915 patch after a drm-misc-next merge into drm-intel-next.

Jani, how would you like to handle the single i915 patch in this
series?

Regards,

Hans





> 
> On Mon, 2021-09-06 at 09:35 +0200, Hans de Goede wrote:
>> Hi all,
>>
>> Here is the privacy-screen related code which I last posted in April 2021
>> 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).
>>
>> This is unchanged (except for a rebase on drm-tip), what has changed is
>> that the first userspace consumer of the new properties is now fully ready
>> for merging (it is just waiting for the kernel bits to land first):
>>
>>  -
>> https://gitlab.gnome.org/GNOME/gsettings-desktop-schemas/-/merge_requests/49
>>  - https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1952
>>  - https://gitlab.gnome.org/GNOME/gnome-control-center/-/merge_requests/1032
>>
>> Having a userspace-consumer of the API fully ready for merging, clears the
>> last blocker for this series. It has already has been reviewed before
>> by Emil Velikov, but it could really do with another review.
>>
>> The new API works as designed and 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 (v3)
>>   drm/privacy-screen: Add X86 specific a

Re: [PATCH 3/9] drm/privacy-screen: Add X86 specific arch init code

2021-09-16 Thread Hans de Goede
Hi,

On 9/16/21 10:51 AM, Jani Nikula wrote:
> On Mon, 06 Sep 2021, Hans de Goede  wrote:
>> 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.
>>
>> Reviewed-by: Emil Velikov 
>> 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 788fc37096f6..12997ca5670d 100644
>> --- a/drivers/gpu/drm/Makefile
>> +++ b/drivers/gpu/drm/Makefile
>> @@ -32,7 +32,7 @@ drm-$(CONFIG_OF) += drm_of.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
> 
> Would be nice to avoid building drm_privacy_screen_x86.o altogether for
> CONFIG_X86=n, and avoid...

Right unfortunately AFAIK I cannot write something like:

drm-$(CONFIG_DRM_PRIVACY_SCREEN && CONFIG_X86) += drm_privacy_screen_x86.o

So this would require adding a (non user selectable)
CONFIG_DRM_PRIVACY_SCREEN_X86 in Kconfig looking something
like this:

config DRM_PRIVACY_SCREEN
bool
default n
select DRM_PRIVACY_SCREEN_X86 if X86

config DRM_PRIVACY_SCREEN_X86
bool
default n

Which is also not really pretty. 


>>  obj-$(CONFIG_DRM_DP_AUX_BUS) += drm_dp_aux_bus.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 0000..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
> 
> ...ifdefs that cover the entire file. This can be a future improvement,
> though.

Thanks I would be happy to do a follow-up patch if we can come-up with
a better solution which we all like.

For now I would indeed prefer to move forward with this patch-set as is
because it has been rather long in the making, so it will be good if
I can finally get it upstream.

Regards,

Hans


> 
>> +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 = , };
>> +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, _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", , );
>> +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",
>> +},
>> +.detec

Re: [PATCH 9/9] drm/i915: Add privacy-screen support

2021-09-16 Thread Hans de Goede
Hi,

On 9/15/21 11:11 PM, Lyude Paul wrote:
> On Mon, 2021-09-06 at 09:35 +0200, Hans de Goede wrote:
>> 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(>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.
> 
> I was going to suggest that you workaround this simply by adding a variable
> that corresponds to the most recently committed privacy screen state somewhere
> in a driver private structure. But, then I realized that's basically the same
> as what you're doing now except that your current solution stores said state
> in a shared struct. So, I think you probably do have the right idea here as
> long as we don't get any non-ACPI providers in the future. This also seems
> like something that wouldn't be difficult to fixup down the line if that ends
> up changing.

Ack, this is all kernel internal stuff so we can always rework it if necessary.

Regards,

Hans




> 
>>
>> 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.
>>
>> Reviewed-by: Emil Velikov 
>> 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 5560d2f4c352..7285873d329a 100644
>> --- a/drivers/gpu/drm/i915/display/intel_display.c
>> +++ b/drivers/gpu/drm/i915/display/intel_display.c
>> @@ -10140,6 +10140,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;
>> @@ -10237,6 +10239,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(>base, connector,
>> new_connector_state, i)
>> +   drm_connector_update_privacy_screen(connector, 
>>> 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 7f8e8865048f..3aa2072cccf6 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"
>> @@ -5217,6 +5218,7 @@ static bool intel_edp_init_connector(struct intel_dp
>> *intel_dp,
>> struct drm_connector *connector = _connector->base;
>> struct drm_display_mode *fixed_mode = NULL;
>> struct drm_display_mode 

Re: [PATCH 8/9] platform/x86: thinkpad_acpi: Register a privacy-screen device

2021-09-16 Thread Hans de Goede
Hi,

On 9/15/21 10:55 PM, Lyude Paul wrote:
> On Mon, 2021-09-06 at 09:35 +0200, Hans de Goede wrote:
>> 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
> 
> Looks like a typo here --^

Ack I will fix this before pushing this out.

> 
>> interface which all user-space code should use to query and control
>> the privacy-screen.
>>
>> Reviewed-by: Emil Velikov 
>> 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 d12db6c316ea..ae00a27f9f95 100644
>> --- a/drivers/platform/x86/Kconfig
>> +++ b/drivers/platform/x86/Kconfig
>> @@ -509,7 +509,9 @@ config THINKPAD_ACPI
>> depends on ACPI_VIDEO || ACPI_VIDEO = n
>> depends on BACKLIGHT_CLASS_DEVICE
>> depends on I2C
>> +   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 b8f2556c4797..044b238730ba 100644
>> --- a/drivers/platform/x86/thinkpad_acpi.c
>> +++ b/drivers/platform/x86/thinkpad_acpi.c
>> @@ -73,6 +73,7 @@
>>  #include 
>>  #include 
>>  #include 
>> +#include 
>>  #include "dual_accel_detect.h"
>>  
>>  /* ThinkPad CMOS commands */
>> @@ -157,6 +158,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 */
>> @@ -3889,6 +3891,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.
>> @@ -9819,30 +9827,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(>lock)))
>> +   return -EIO;
>> +
>> if (!acpi_evalf(lcdshadow_set_handle, , 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_s

Re: [PATCH 4/9] drm/privacy-screen: Add notifier support

2021-09-16 Thread Hans de Goede
Hi,

On 9/15/21 10:26 PM, Lyude Paul wrote:
> On Mon, 2021-09-06 at 09:35 +0200, Hans de Goede wrote:
>> 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.
>>
>> Reviewed-by: Emil Velikov 
>> 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(>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(>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(>lock);
>> +   BLOCKING_INIT_NOTIFIER_HEAD(>notifier_head);
>>  
>> priv->dev.class = drm_class;
>> priv->dev.type = _privacy_screen_type;
>> @@ -399,3 +443,26 @@ void drm_privacy_screen_unregister(struct
>> drm_privacy_screen *priv)
>> device_unregister(>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_notif

Re: [PATCH 2/9] drm: Add privacy-screen class (v3)

2021-09-16 Thread Hans de Goede
Hi Lyude,

Thank you very much for the review of this series.

On 9/15/21 10:01 PM, Lyude Paul wrote:
> On Mon, 2021-09-06 at 09:35 +0200, Hans de Goede wrote:
>> 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
>>
>> Changes in v3:
>> - Make the static inline drm_privacy_screen_get_state() stub set sw_state
>>   and hw_state to PRIVACY_SCREEN_DISABLED to squelch an uninitialized
>>   variable warning when CONFIG_DRM_PRIVICAY_SCREEN is not set
>>
>> Reviewed-by: Emil Velikov 
>> 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 |  50 +++
>>  include/drm/drm_privacy_screen_driver.h   |  80 +
>>  include/drm/drm_privacy_screen_machine.h  |  41 +++
>>  9 files changed, 604 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 ede4a37a53b3..a272ca600f98 100644
>> --- a/MAINTAINERS
>> +++ b/MAINTAINERS
>> @@ -6376,6 +6376,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 b17e231ca6f7..7249b010ab90 100644
>> --- a/drivers/gpu/drm/Kconfig
>> +++ b/drivers/gpu/drm/Kconfig
>> @@ -481,3 +481,7 @@ config DRM_PANEL_ORIENTATION_QUIRKS
>>  config DRM_LIB_RANDOM
>> bool
>> default n
>> +
>> +config DRM_PRIVACY_SCREEN
>> +   bool
>> +   default n
> 
> This is probably worth documenting for folks configuring their kernels to
> explain what this actually does (something simple like "Controls programmable
> privacy screens found on some devices, if unsure select Y" would probably be
> f

Re: [GIT PULL] drm-misc + drm-intel: Add support for out-of-band hotplug notification

2021-09-13 Thread Hans de Goede
Hi,

On 8/26/21 1:43 PM, Vivi, Rodrigo wrote:
> On Thu, 2021-08-26 at 10:23 +0200, Maxime Ripard wrote:
>> On Wed, Aug 25, 2021 at 04:03:43PM +, Vivi, Rodrigo wrote:
>>> On Tue, 2021-08-24 at 18:48 +0200, Hans de Goede wrote:
>>>> 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.)
>>>
>>> Just to be clear and avoid confusion: This pull request does apply
>>> cleanly on drm-misc-next nd drm-intel-next right now.
>>>
>>> I'm just waiting for drm-misc-next maintainers to pull this to drm-
>>> misc-next so I can pull it to drm-intel-next.
>>>
>>> Maxime, is that your round now?
>>> or Thomas?
>>
>> That's me, I just pushed it to drm-misc-next
> 
> Thank you!
> I also pushed to drm-intel-next.

Thanks, I pushed the remaining 2 i915 patches depending on this
to drm-intel-next last week (but I forgot to reply to this email then).

Regards,

Hans



Re: [PATCH] drm: panel-orientation-quirks: Add quirk for the Chuwi HiBook

2021-09-12 Thread Hans de Goede
Hi,

On 9/9/21 5:50 PM, Thierry Reding wrote:
> On Sun, Sep 05, 2021 at 03:05:01PM +0200, Hans de Goede wrote:
>> The Chuwi HiBook uses a panel which has been mounted
>> 90 degrees rotated. Add a quirk for this.
>>
>> Signed-off-by: Hans de Goede 
>> ---
>>  drivers/gpu/drm/drm_panel_orientation_quirks.c | 8 
>>  1 file changed, 8 insertions(+)
> 
> I'm not very familiar with these quirks, but this looks correct and
> inline with other entries in this table.
> 
>> diff --git a/drivers/gpu/drm/drm_panel_orientation_quirks.c 
>> b/drivers/gpu/drm/drm_panel_orientation_quirks.c
>> index 4e965b0f5502..7e0f581a360e 100644
>> --- a/drivers/gpu/drm/drm_panel_orientation_quirks.c
>> +++ b/drivers/gpu/drm/drm_panel_orientation_quirks.c
>> @@ -140,6 +140,14 @@ static const struct dmi_system_id orientation_data[] = {
>>DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "T103HAF"),
>>  },
>>  .driver_data = (void *)_rightside_up,
>> +}, {/* Chuwi HiBook (CWI514) */
>> +.matches = {
>> +DMI_MATCH(DMI_BOARD_VENDOR, "Hampoo"),
>> +DMI_MATCH(DMI_BOARD_NAME, "Cherry Trail CR"),
>> +/* Above matches are too generic, add bios-date match */
>> +DMI_MATCH(DMI_BIOS_DATE, "05/07/2016"),
>> +},
>> +.driver_data = (void *)_rightside_up,
>>  }, {/* Chuwi Hi10 Pro (CWI529) */
>>  .matches = {
>>DMI_EXACT_MATCH(DMI_BOARD_VENDOR, "Hampoo"),
> 
> One thing I noticed is that there doesn't seem to be an entry for Chuwi
> Hi10 anywhere in linux-next. Perhaps that's from a different patch in
> your local tree, or it's based on some other tree that already has that.
> In any case, I trust that this can be resolved when applying, so this
> seems okay:
> 
> Reviewed-by: Thierry Reding 

Thank you, I've pushed this to drm-misc-next now.

Regards,

Hans



Re: [PATCH] drm/panel-orientation-quirks: add Valve Steam Deck

2021-09-12 Thread Hans de Goede
Hi,

On 9/11/21 8:54 PM, Sam Ravnborg wrote:
> Hi Simon,
> On Sat, Sep 11, 2021 at 10:24:40AM +, Simon Ser wrote:
>> Valve's Steam Deck has a 800x1280 LCD screen.
>>
>> Signed-off-by: Simon Ser 
>> Cc: Jared Baldridge 
>> Cc: Emil Velikov 
>> Cc: Daniel Vetter 
>> Cc: Hans de Goede 
> 
> 
> The sorting is off - "Valve Steam Deck" comes before "VIOS LTH17"
> 
> With the sorting fixed:
> 
> Acked-by: Sam Ravnborg 
> 
> (Not that I know this code, but I wanted to avoid this patch meeting the
> same fate as the patch from Hans that was left with no feedback for a
> long time).

Sam thank you for Ack-ing this, I also notices the ordering
issue and I've fixed this up while applying this.

I'm doing a test-build now and then I will push out the fixed-up
version to drm-misc-next.

Regards,

Hans



 
>> ---
>>  drivers/gpu/drm/drm_panel_orientation_quirks.c | 7 +++
>>  1 file changed, 7 insertions(+)
>>
>> diff --git a/drivers/gpu/drm/drm_panel_orientation_quirks.c 
>> b/drivers/gpu/drm/drm_panel_orientation_quirks.c
>> index f6bdec7fa925..3018d1dcd271 100644
>> --- a/drivers/gpu/drm/drm_panel_orientation_quirks.c
>> +++ b/drivers/gpu/drm/drm_panel_orientation_quirks.c
>> @@ -231,6 +231,13 @@ static const struct dmi_system_id orientation_data[] = {
>>DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "LTH17"),
>>  },
>>  .driver_data = (void *)_rightside_up,
>> +}, {/* Valve Steam Deck */
>> +.matches = {
>> +  DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Valve"),
>> +  DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "Jupiter"),
>> +  DMI_EXACT_MATCH(DMI_PRODUCT_VERSION, "1"),
>> +},
>> +.driver_data = (void *)_rightside_up,
>>  },
>>  {}
>>  };
>> -- 
>> 2.33.0
>>
> 



Re: [PATCH] drm: panel-orientation-quirks: Add quirk for the Chuwi HiBook

2021-09-09 Thread Hans de Goede
Hi,

On 9/9/21 5:50 PM, Thierry Reding wrote:
> On Sun, Sep 05, 2021 at 03:05:01PM +0200, Hans de Goede wrote:
>> The Chuwi HiBook uses a panel which has been mounted
>> 90 degrees rotated. Add a quirk for this.
>>
>> Signed-off-by: Hans de Goede 
>> ---
>>  drivers/gpu/drm/drm_panel_orientation_quirks.c | 8 
>>  1 file changed, 8 insertions(+)
> 
> I'm not very familiar with these quirks, but this looks correct and
> inline with other entries in this table.
> 
>> diff --git a/drivers/gpu/drm/drm_panel_orientation_quirks.c 
>> b/drivers/gpu/drm/drm_panel_orientation_quirks.c
>> index 4e965b0f5502..7e0f581a360e 100644
>> --- a/drivers/gpu/drm/drm_panel_orientation_quirks.c
>> +++ b/drivers/gpu/drm/drm_panel_orientation_quirks.c
>> @@ -140,6 +140,14 @@ static const struct dmi_system_id orientation_data[] = {
>>DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "T103HAF"),
>>  },
>>  .driver_data = (void *)_rightside_up,
>> +}, {/* Chuwi HiBook (CWI514) */
>> +.matches = {
>> +DMI_MATCH(DMI_BOARD_VENDOR, "Hampoo"),
>> +DMI_MATCH(DMI_BOARD_NAME, "Cherry Trail CR"),
>> +/* Above matches are too generic, add bios-date match */
>> +DMI_MATCH(DMI_BIOS_DATE, "05/07/2016"),
>> +},
>> +.driver_data = (void *)_rightside_up,
>>  }, {/* Chuwi Hi10 Pro (CWI529) */
>>  .matches = {
>>DMI_EXACT_MATCH(DMI_BOARD_VENDOR, "Hampoo"),
> 
> One thing I noticed is that there doesn't seem to be an entry for Chuwi
> Hi10 anywhere in linux-next. Perhaps that's from a different patch in
> your local tree, or it's based on some other tree that already has that.

It is based on drm-misc-next, which has a recent patch adding the Hi 10 Pro:

https://cgit.freedesktop.org/drm-misc/commit/?id=072e70d52372c44df90b44fb4cd949a709bb5bef

I guess this is not in linux-next yet because of the merge-window.

> In any case, I trust that this can be resolved when applying, so this
> seems okay:
> 
> Reviewed-by: Thierry Reding 

Thank you.

Regards,

Hans



Re: Handling DRM master transitions cooperatively

2021-09-08 Thread Hans de Goede
Hi,

On 9/8/21 9:36 AM, Pekka Paalanen wrote:
> On Tue, 7 Sep 2021 14:42:56 +0200
> Hans de Goede  wrote:
> 
>> Hi,
>>
>> On 9/7/21 12:07 PM, Pekka Paalanen wrote:
>>> On Fri, 3 Sep 2021 21:08:21 +0200
>>> Dennis Filder  wrote:
>>>   
>>>> Hans de Goede asked me to take a topic from a private discussion here.
>>>> I must also preface that I'm not a graphics person and my knowledge of
>>>> DRI/DRM is cursory at best.
>>>>
>>>> I initiated the conversation with de Goede after learning that the X
>>>> server now supports being started with an open DRM file descriptor
>>>> (this was added for Keith Packard's xlease project).  I wondered if
>>>> that could be used to smoothen the Plymouth->X transition somehow and
>>>> asked de Goede if there were any such plans.  He denied, but mentioned
>>>> that a new ioctl is in the works to prevent the kernel from wiping the
>>>> contents of a frame buffer after a device is closed, and that this
>>>> would help to keep transitions smooth.  
>>>
>>> Hi,
>>>
>>> I believe the kernel is not wiping anything on device close. If
>>> something in the KMS state is wiped, it originates in userspace:
>>>
>>> - Plymouth doing something (e.g. RmFB on an in-use FB will turn the
>>>   output off, you need to be careful to "leak" your FB if you want a
>>>   smooth hand-over)  
>>
>> The "kernel is not wiping anything on device close" is not true,
>> when closing /dev/dri/card# any remaining FBs from the app closing
>> it will be dealt with as if they were RmFB-ed, causing the screen
>> to show what I call "the fallback fb", at least with the i915 driver.
> 
> No, that's not what should happen AFAIK.

I'm pretty sure that that is what is happening though.

But hopefully someone else can either confirm or deny this :)

> True, all FBs that are not referenced by active CRTCs or planes will
> get freed, since their refcount drops to zero, but those CRTCs and
> planes that are active will remain active and therefore keep their
> reference to the respective FBs and so the FBs remain until replaced or
> turned off explicitly (by e.g. fbcon if you switch to that rather than
> another userspace KMS client). I believe that is the whole reason why
> e.g. DRM_IOCTL_MODE_GETFB2 can be useful, otherwise the next KMS client
> would not have anything to scrape.
> 
> danvet, what is the DRM core intention?
> 
> Or am I confused because display servers do not tend to close the DRM
> device fd on switch-out but Plymouth does (too early)?
> 
> If so, why can't Plymouth keep the device open longer and quit only
> when the hand-off is complete? Not quitting too early would be a
> prerequisite for any explicit hand-off protocol as well.

plymouth is actually keeping the device open longer for exactly this
reason, the following happens:

1. plmouth starts
2. gdm starts and tells plymouth to "deactivate" which will stop it from
making drm ioctls and drop its drm master rights, while keeping the fb around
3. gdm waits for the greeter process to tell it that it has successfully
taken over the screen
4. gdm tells plymouth to quit

And something similar is happening on gdm greeter -> gnome user session
handover.

But we need the new ioctl at least on shutdown / reboot to avoid the
"fallback fb" (typically the EFI/BIOS setup fb which i915 inherited at boot)
showing for a brief moment when plymouth quits at shutdown / reboot and
there is nothing to hand-over the fb to in that case.

And the new ioctl would also make the above handover a lot simpler.

And we currently also have a flicker when going from user-session to
gdm on logout or from gdm/user-session to plymout on shutdown/reboot.

Basically we have quite a few transitions and currently only the
boot + login path is smooth and the rest needs more work, which either
requires a standardized handover method (instead of the current
hardcoded plymouth -> gdm stuff), or just allowing the FB to sit
around until the next drm-client installs its FB, which would be
much more KISS, so that has my preference.

And this KISS method will also work with transitions to a new
console-owner process which is not aware of any handover protocols,
as long as the old process uses the ioctl the transition will be
smooth. So e.g. gdm -> i3 on Xorg session will be smooth (1)

Regards,

Hans


1) I think this actually already is smooth because in this case gdm
just sleeps for 5 seconds before killing the greeter I believe, but
with the ioctl we could remove this hack




Re: Handling DRM master transitions cooperatively

2021-09-07 Thread Hans de Goede
Hi,

On 9/7/21 12:07 PM, Pekka Paalanen wrote:
> On Fri, 3 Sep 2021 21:08:21 +0200
> Dennis Filder  wrote:
> 
>> Hans de Goede asked me to take a topic from a private discussion here.
>> I must also preface that I'm not a graphics person and my knowledge of
>> DRI/DRM is cursory at best.
>>
>> I initiated the conversation with de Goede after learning that the X
>> server now supports being started with an open DRM file descriptor
>> (this was added for Keith Packard's xlease project).  I wondered if
>> that could be used to smoothen the Plymouth->X transition somehow and
>> asked de Goede if there were any such plans.  He denied, but mentioned
>> that a new ioctl is in the works to prevent the kernel from wiping the
>> contents of a frame buffer after a device is closed, and that this
>> would help to keep transitions smooth.
> 
> Hi,
> 
> I believe the kernel is not wiping anything on device close. If
> something in the KMS state is wiped, it originates in userspace:
> 
> - Plymouth doing something (e.g. RmFB on an in-use FB will turn the
>   output off, you need to be careful to "leak" your FB if you want a
>   smooth hand-over)

The "kernel is not wiping anything on device close" is not true,
when closing /dev/dri/card# any remaining FBs from the app closing
it will be dealt with as if they were RmFB-ed, causing the screen
to show what I call "the fallback fb", at least with the i915 driver.

> - Xorg doing something (e.g. resetting instead of inheriting KMS state)
> 
> - Something missed in the hand-off sequence which allows fbcon to
>   momentarily take over between Plymouth and Xorg. This would need to
>   be fixed between Plymouth and Xorg.
> 
> - Maybe systemd-logind does something odd to the KMS device? It has
>   pretty wild code there. Or maybe it causes fbcon to take over.
> 
> What is the new ioctl you referred to?

It is an ioctl to mark a FB to not have it auto-removed on device-close,
instead leaving it in place until some some kernel/userspace client
actively installs another FB. This was proposed by Rob Clark quite
a while ago, but it never got anywhere because of lack of userspace
actually interested in using it.

I've been thinking about reviving Rob's patch, since at least for
plymouth this would be pretty useful to have.

Regards,

Hans



[PATCH 9/9] drm/i915: Add privacy-screen support

2021-09-06 Thread Hans de Goede
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(>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.

Reviewed-by: Emil Velikov 
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 5560d2f4c352..7285873d329a 100644
--- a/drivers/gpu/drm/i915/display/intel_display.c
+++ b/drivers/gpu/drm/i915/display/intel_display.c
@@ -10140,6 +10140,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;
@@ -10237,6 +10239,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(>base, connector, 
new_connector_state, i)
+   drm_connector_update_privacy_screen(connector, >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 7f8e8865048f..3aa2072cccf6 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"
@@ -5217,6 +5218,7 @@ static bool intel_edp_init_connector(struct intel_dp 
*intel_dp,
struct drm_connector *connector = _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;
@@ -5308,6 +5310,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->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(_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 146f7e39182a..d6913f567a1c 100644
--- a/drivers/gpu/drm/i915/i915_pci.c
+++ b/drivers/gpu/drm/i915/i915_pci.c
@@ -25,6 +25,7 @@
 #include 
 
 #include 
+#include 
 #include 
 
 #include "i915_drv.h"
@@ -1167,6 +1168,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 &&
@@ -1195,7 +1197,17 @@ static int i915_pci_probe(struct pci_dev *pdev, const 
struct pci_device_id *ent)
if (vga_switcheroo_client_probe_defer(

[PATCH 8/9] platform/x86: thinkpad_acpi: Register a privacy-screen device

2021-09-06 Thread Hans de Goede
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.

Reviewed-by: Emil Velikov 
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 d12db6c316ea..ae00a27f9f95 100644
--- a/drivers/platform/x86/Kconfig
+++ b/drivers/platform/x86/Kconfig
@@ -509,7 +509,9 @@ config THINKPAD_ACPI
depends on ACPI_VIDEO || ACPI_VIDEO = n
depends on BACKLIGHT_CLASS_DEVICE
depends on I2C
+   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 b8f2556c4797..044b238730ba 100644
--- a/drivers/platform/x86/thinkpad_acpi.c
+++ b/drivers/platform/x86/thinkpad_acpi.c
@@ -73,6 +73,7 @@
 #include 
 #include 
 #include 
+#include 
 #include "dual_accel_detect.h"
 
 /* ThinkPad CMOS commands */
@@ -157,6 +158,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 */
@@ -3889,6 +3891,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.
@@ -9819,30 +9827,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(>lock)))
+   return -EIO;
+
if (!acpi_evalf(lcdshadow_set_handle, , 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, , 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;
@@ -9850,36 +9868,44 @@ static int tpacpi_lcdshadow_init(struct ibm_init_struct 
*iibm)
 
status1 = acpi_get_handle(hkey_handle, "GSSS", _get_handle);
status2 = acpi_get_handle(hkey_handle, "", _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, , NULL, "dd", 0)) {
-   lcdshadow_state = -EIO;
+   

[PATCH 7/9] platform/x86: thinkpad_acpi: Get privacy-screen / lcdshadow ACPI handles only once

2021-09-06 Thread Hans de Goede
Get the privacy-screen / lcdshadow ACPI handles once and cache them,
instead of retrieving them every time we need them.

Reviewed-by: Emil Velikov 
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 83c88a8ebaf2..b8f2556c4797 100644
--- a/drivers/platform/x86/thinkpad_acpi.c
+++ b/drivers/platform/x86/thinkpad_acpi.c
@@ -9819,19 +9819,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, "", 
_shadow_handle))) {
-   pr_warn("Thinkpad ACPI has no %s interface.\n", "");
-   return -EIO;
-   }
-
-   if (!acpi_evalf(set_shadow_handle, , NULL, "dd", (int)state))
+   if (!acpi_evalf(lcdshadow_set_handle, , NULL, "dd", (int)state))
return -EIO;
 
lcdshadow_state = state;
@@ -9849,15 +9845,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", 
_shadow_handle))) {
+   status1 = acpi_get_handle(hkey_handle, "GSSS", _get_handle);
+   status2 = acpi_get_handle(hkey_handle, "", _set_handle);
+   if (ACPI_FAILURE(status1) || ACPI_FAILURE(status2)) {
lcdshadow_state = -ENODEV;
return 0;
}
 
-   if (!acpi_evalf(get_shadow_handle, , NULL, "dd", 0)) {
+   if (!acpi_evalf(lcdshadow_get_handle, , NULL, "dd", 0)) {
lcdshadow_state = -EIO;
return -EIO;
}
-- 
2.31.1



[PATCH 6/9] platform/x86: thinkpad_acpi: Add hotkey_notify_extended_hotkey() helper

2021-09-06 Thread Hans de Goede
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...).

Reviewed-by: Emil Velikov 
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 50ff04c84650..83c88a8ebaf2 100644
--- a/drivers/platform/x86/thinkpad_acpi.c
+++ b/drivers/platform/x86/thinkpad_acpi.c
@@ -3885,6 +3885,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)
@@ -3919,17 +3937,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



[PATCH 5/9] drm/connector: Add a drm_connector privacy-screen helper functions

2021-09-06 Thread Hans de Goede
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.

Reviewed-by: Emil Velikov 
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 dd1ca68881ba..8af678652e69 100644
--- a/drivers/gpu/drm/drm_connector.c
+++ b/drivers/gpu/drm/drm_connector.c
@@ -21,6 +21,7 @@
  */
 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -28,6 +29,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 
 #include 
@@ -462,6 +464,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;
@@ -543,6 +550,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,
+  >privacy_screen_notifier);
+
mutex_lock(_list_lock);
list_add_tail(>global_connector_list_entry, _list);
mutex_unlock(_list_lock);
@@ -578,6 +589,11 @@ void drm_connector_unregister(struct drm_connector 
*connector)
list_del_init(>global_connector_list_entry);
mutex_unlock(_list_lock);
 
+   if (connector->privacy_screen)
+   drm_privacy_screen_unregister_notifier(
+   connector->privacy_screen,
+   >privacy_screen_notifier);
+
if (connector->funcs->early_unregister)
connector->funcs->early_unregister(connector);
 
@@ -2442,6 +2458,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,
+_state, _state);
+
+   connector->state->privacy_screen_sw_state = sw_state;
+   drm_object_property_set_value(>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(>mode_config.connection_mutex, NULL);
+   drm_connector_update_privacy_screen_properties(connector);
+   drm_modeset_unlock(>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_connecto

[PATCH 4/9] drm/privacy-screen: Add notifier support

2021-09-06 Thread Hans de Goede
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.

Reviewed-by: Emil Velikov 
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(>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(>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(>lock);
+   BLOCKING_INIT_NOTIFIER_HEAD(>notifier_head);
 
priv->dev.class = drm_class;
priv->dev.type = _privacy_screen_type;
@@ -399,3 +443,26 @@ void drm_privacy_screen_unregister(struct 
drm_privacy_screen *priv)
device_unregister(>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(>lock)))
+   return;
+
+   blocking_notifier_call_chain(>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 0cbd23b0453d..7f66a90d15b7 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 drm_privacy_screen_unregister_notifier(stru

[PATCH 3/9] drm/privacy-screen: Add X86 specific arch init code

2021-09-06 Thread Hans de Goede
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.

Reviewed-by: Emil Velikov 
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 788fc37096f6..12997ca5670d 100644
--- a/drivers/gpu/drm/Makefile
+++ b/drivers/gpu/drm/Makefile
@@ -32,7 +32,7 @@ drm-$(CONFIG_OF) += drm_of.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
 
 obj-$(CONFIG_DRM_DP_AUX_BUS) += drm_dp_aux_bus.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 = , };
+   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, _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", , );
+   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(_lookup);
+   break;
+   }
+}
+
+void drm_privacy_screen_lookup_exit(void)
+{
+   if (arch_lookup.provider)
+   drm_privacy_screen_lookup_remove(_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



[PATCH 2/9] drm: Add privacy-screen class (v3)

2021-09-06 Thread Hans de Goede
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

Changes in v3:
- Make the static inline drm_privacy_screen_get_state() stub set sw_state
  and hw_state to PRIVACY_SCREEN_DISABLED to squelch an uninitialized
  variable warning when CONFIG_DRM_PRIVICAY_SCREEN is not set

Reviewed-by: Emil Velikov 
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 |  50 +++
 include/drm/drm_privacy_screen_driver.h   |  80 +
 include/drm/drm_privacy_screen_machine.h  |  41 +++
 9 files changed, 604 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 ede4a37a53b3..a272ca600f98 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -6376,6 +6376,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 b17e231ca6f7..7249b010ab90 100644
--- a/drivers/gpu/drm/Kconfig
+++ b/drivers/gpu/drm/Kconfig
@@ -481,3 +481,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 0dff40bb863c..788fc37096f6 100644
--- a/drivers/gpu/drm/Makefile
+++ b/drivers/gpu/drm/Makefile
@@ -32,6 +32,7 @@ drm-$(CONFIG_OF) += drm_of.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
 
 obj-$(CONFIG_DRM_DP_AUX_BUS) += drm_dp_aux_bus.o
 
diff --git a/drivers/gpu/drm/drm_drv.c b/drivers/gpu/drm/drm_drv.c
index 7a5097467ba5..dc293b771c3f 100644
--- a/drivers/gpu/drm/drm_drv.c
+++ b/drivers/gpu/drm/drm_drv.c
@@ -43,6 +43,7 @@
 #include 
 #include 
 #include 
+#include 
 
 #include "drm_crtc_internal.h"
 #include "drm_internal.h"
@@ -1029,6 +1030,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("Initial

[PATCH 1/9] drm/connector: Add support for privacy-screen properties (v4)

2021-09-06 Thread Hans de Goede
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 
Reviewed-by: Emil Velikov 
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 1ef7951ded5e..d14bf1c35d7e 100644
--- a/Documentation/gpu/drm-kms.rst
+++ b/Documentation/gpu/drm-kms.rst
@@ -506,6 +506,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 909f31833181..cdd31fc78bfc 100644
--- a/drivers/gpu/drm/drm_atomic_uapi.c
+++ b/drivers/gpu/drm/drm_atomic_uapi.c
@@ -797,6 +797,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);
@@ -874,6 +876,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 e0a30e0ee86a..dd1ca68881ba 100644
--- a/drivers/gpu/drm/drm_connector.c
+++ b/drivers/gpu/drm/drm_connector.c
@@ -1264,6 +1264,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 i

[PATCH 0/9] drm: Add privacy-screen class and connector properties

2021-09-06 Thread Hans de Goede
Hi all,

Here is the privacy-screen related code which I last posted in April 2021
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).

This is unchanged (except for a rebase on drm-tip), what has changed is
that the first userspace consumer of the new properties is now fully ready
for merging (it is just waiting for the kernel bits to land first):

 - https://gitlab.gnome.org/GNOME/gsettings-desktop-schemas/-/merge_requests/49
 - https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1952
 - https://gitlab.gnome.org/GNOME/gnome-control-center/-/merge_requests/1032

Having a userspace-consumer of the API fully ready for merging, clears the
last blocker for this series. It has already has been reviewed before
by Emil Velikov, but it could really do with another review.

The new API works as designed and 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 (v3)
  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|  65 +++
 include/drm/drm_privacy_screen_driver.h  |  84 
 include/drm/drm_privacy_screen_machine.h |  46 ++
 19 files changed, 1175 insertions(+), 42 deletions(-)
 create mode 100644 drive

[PATCH] drm: panel-orientation-quirks: Add quirk for the Chuwi HiBook

2021-09-05 Thread Hans de Goede
The Chuwi HiBook uses a panel which has been mounted
90 degrees rotated. Add a quirk for this.

Signed-off-by: Hans de Goede 
---
 drivers/gpu/drm/drm_panel_orientation_quirks.c | 8 
 1 file changed, 8 insertions(+)

diff --git a/drivers/gpu/drm/drm_panel_orientation_quirks.c 
b/drivers/gpu/drm/drm_panel_orientation_quirks.c
index 4e965b0f5502..7e0f581a360e 100644
--- a/drivers/gpu/drm/drm_panel_orientation_quirks.c
+++ b/drivers/gpu/drm/drm_panel_orientation_quirks.c
@@ -140,6 +140,14 @@ static const struct dmi_system_id orientation_data[] = {
  DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "T103HAF"),
},
.driver_data = (void *)_rightside_up,
+   }, {/* Chuwi HiBook (CWI514) */
+   .matches = {
+   DMI_MATCH(DMI_BOARD_VENDOR, "Hampoo"),
+   DMI_MATCH(DMI_BOARD_NAME, "Cherry Trail CR"),
+   /* Above matches are too generic, add bios-date match */
+   DMI_MATCH(DMI_BIOS_DATE, "05/07/2016"),
+   },
+   .driver_data = (void *)_rightside_up,
}, {/* Chuwi Hi10 Pro (CWI529) */
.matches = {
  DMI_EXACT_MATCH(DMI_BOARD_VENDOR, "Hampoo"),
-- 
2.31.1



Re: [GIT PULL] drm-misc + drm-intel: Add support for out-of-band hotplug notification

2021-08-24 Thread Hans de Goede
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(-)
>>
> 



[GIT PULL] drm-misc + drm-intel: Add support for out-of-band hotplug notification

2021-08-20 Thread Hans de Goede
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(-)



[PATCH 8/8] usb: typec: altmodes/displayport: Notify drm subsys of hotplug events

2021-08-17 Thread Hans de Goede
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 = _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(>dev.kobj, _altmode_group);
cancel_work_sync(>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



[PATCH 7/8] usb: typec: altmodes/displayport: Make dp_altmode_notify() more generic

2021-08-17 Thread Hans de Goede
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),
-  >data);
+   return typec_altmode_notify(dp->alt, conf, >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(>alt->dev.kobj, "displayport", "configuration");
-
-   if (!dp->data.conf)
-   return typec_altmode_notify(dp->alt, TYPEC_STATE_USB,
-   >data);
-
-   ret = dp_altmode_notify(dp);
-   if (ret)
-   return ret;
-
sysfs_notify(>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, , 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,
->data);
-   }
+   if (ret)
+   dp_altmode_notify(dp);
 
return ret;
 }
-- 
2.31.1



[PATCH 6/8] drm/i915/dp: Add support for out-of-bound hotplug events

2021-08-17 Thread Hans de Goede
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(>irq_lock);
+   i915->hotplug.event_bits |= BIT(encoder->hpd_pin);
+   spin_unlock_irq(>irq_lock);
+   queue_delayed_work(system_wq, >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 5/8] drm/i915: Associate ACPI connector nodes with connector entries (v2)

2021-08-17 Thread Hans de Goede
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(_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 = >drm;
+   struct fwnode_handle *fwnode = NULL;
+   struct drm_connector *connector;
+   struct acpi_device *adev;
+
+   drm_connector_list_iter_begin(drm_dev, _iter);
+   drm_for_each_connector_iter(connector, _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(_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 +12561,7 @@ int intel_modeset_init_nogem(struct drm_i

[PATCH 4/8] drm/connector: Add support for out-of-band hotplug notification (v3)

2021-08-17 Thread Hans de Goede
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 3/8] drm/connector: Add drm_connector_find_by_fwnode() function (v3)

2021-08-17 Thread Hans de Goede
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(>global_connector_list_entry);
INIT_LIST_HEAD(>probed_modes);
INIT_LIST_HEAD(>modes);
mutex_init(>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(_list_lock);
+   list_add_tail(>global_connector_list_entry, _list);
+   mutex_unlock(_list_lock);
goto unlock;
 
 err_debugfs:
@@ -562,6 +574,10 @@ void drm_connector_unregister(struct drm_connector 
*connector)
return;
}
 
+   mutex_lock(_list_lock);
+   list_del_init(>global_connector_list_entry);
+   mutex_unlock(_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(_list_lock);
+
+   list_for_each_entry(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(_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 list_head head;
 
+   /**
+* @global_connector_list_entry:
+*
+* Connector entry in the global connector-list, used by
+* drm_connector_find_by_fwnode().
+   

[PATCH 2/8] drm/connector: Add a fwnode pointer to drm_connector and register with ACPI (v2)

2021-08-17 Thread Hans de Goede
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, >base);
kfree(connector->name);
connector->name = NULL;
+   fwnode_handle_put(connector->fwnode);
+   connector->fwnode = NULL;
spin_lock_irq(>mode_config.connector_list_lock);
list_del(>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 == _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(_connector_acpi_bus);
+}
+
+static void drm_sysfs_acpi_unregister(void)
+{
+   unregister_acpi_bus_type(_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, _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 1/8] drm/connector: Give connector sysfs devices there own device_type

2021-08-17 Thread Hans de Goede
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 = _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(>kdev->kobj,
 >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 0/8] drm + usb-type-c: Add support for out-of-band hotplug notification (v4 resend)

2021-08-17 Thread Hans de Goede
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



Re: [PATCH] drm/vbox: Convert to Linux IRQ interfaces

2021-08-02 Thread Hans de Goede
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 = _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(>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 = >ddev;
> + struct pci_dev *pdev = to_pci_dev(dev->dev);
>  
>   INIT_WORK(>hotplug_work, vbox_hotplug_worker);
>   vbox_update_mode_hints(vbox);
>  
> - return drm_irq_install(>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(>ddev);
> + struct drm_device *dev = >ddev;
> + struct pci_dev *pdev = to_pci_dev(dev->dev);
> +
> + free_irq(pdev->irq, dev);
>   flush_work(>hotplug_work);
>  }
> 



Re: [PATCH 0/8] drm + usb-type-c: Add support for out-of-band hotplug notification (v4)

2021-06-15 Thread Hans de Goede
Hi,

On 6/15/21 9:40 AM, Greg Kroah-Hartman wrote:
> On Fri, Jun 04, 2021 at 09:48:32PM +0200, Hans de Goede wrote:
>> Here is v3 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:
>> - 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.
> 
> No objection from me, I've replied with reviewed-by for those USB
> patches now.

Great, thank you.

drm-devs, can I get an ack / reviewed-by for the rest of the series
so that I can push this to drm-misc-next ?

Regards,

Hans



Re: Computation of return value being discarded in get_cpu_power() in drivers/platform/x86/intel_ips.c

2021-06-10 Thread Hans de Goede
Hi,

On 6/10/21 1:55 PM, Joonas Lahtinen wrote:
> (Address for Hans was corrupt in previous message, which confused my mail
> client. Sorry for duplicate message, the other is without From: field).
> 
> + Jesse
> 
> Quoting Colin Ian King (2021-06-09 14:50:07)
>> Hi,
>>
>> I was reviewing some old unassigned variable warnings from static
>> analysis by Coverity and found an issue introduced with the following
>> commit:
>>
>> commit aa7ffc01d254c91a36bf854d57a14049c6134c72
>> Author: Jesse Barnes 
>> Date:   Fri May 14 15:41:14 2010 -0700
>>
>> x86 platform driver: intelligent power sharing driver
>>
>> The analysis is as follows:
>>
>> drivers/platform/x86/intel_ips.c
>>
>>  871 static u32 get_cpu_power(struct ips_driver *ips, u32 *last, int period)
>>  872 {
>>  873u32 val;
>>  874u32 ret;
>>  875
>>  876/*
>>  877 * CEC is in joules/65535.  Take difference over time to
>>  878 * get watts.
>>  879 */
>>  880val = thm_readl(THM_CEC);
>>  881
>>  882/* period is in ms and we want mW */
>>  883ret = (((val - *last) * 1000) / period);
>>
>> Unused value (UNUSED_VALUE)
>> assigned_value:  Assigning value from ret * 1000U / 65535U to ret here,
>> but that stored value is not used.
>>
>>  884ret = (ret * 1000) / 65535;
>>  885*last = val;
>>  886
>>  887return 0;
>>  888 }
>>
>> I'm really not sure why ret is being calculated on lines 883,884 and not
>> being used. Should that be *last = ret on line 885? Looks suspect anyhow.

This has already been fixed (yesterday actually) in linux-next:

https://git.kernel.org/pub/scm/linux/kernel/git/pdx86/platform-drivers-x86.git/commit/?h=for-next=13c3b4f76073d73dd81e418295902676153f6cb5

Regards,

Hans



[PATCH 8/8] usb: typec: altmodes/displayport: Notify drm subsys of hotplug events

2021-06-04 Thread Hans de Goede
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 = _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(>dev.kobj, _altmode_group);
cancel_work_sync(>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



[PATCH 7/8] usb: typec: altmodes/displayport: Make dp_altmode_notify() more generic

2021-06-04 Thread Hans de Goede
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),
-  >data);
+   return typec_altmode_notify(dp->alt, conf, >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(>alt->dev.kobj, "displayport", "configuration");
-
-   if (!dp->data.conf)
-   return typec_altmode_notify(dp->alt, TYPEC_STATE_USB,
-   >data);
-
-   ret = dp_altmode_notify(dp);
-   if (ret)
-   return ret;
-
sysfs_notify(>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, , 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,
->data);
-   }
+   if (ret)
+   dp_altmode_notify(dp);
 
return ret;
 }
-- 
2.31.1



[PATCH 6/8] drm/i915/dp: Add support for out-of-bound hotplug events

2021-06-04 Thread Hans de Goede
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 5c983044..5d6cf2657fa3 100644
--- a/drivers/gpu/drm/i915/display/intel_dp.c
+++ b/drivers/gpu/drm/i915/display/intel_dp.c
@@ -4598,6 +4598,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(>irq_lock);
+   i915->hotplug.event_bits |= BIT(encoder->hpd_pin);
+   spin_unlock_irq(>irq_lock);
+   queue_delayed_work(system_wq, >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,
@@ -4608,6 +4619,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 5/8] drm/i915: Associate ACPI connector nodes with connector entries (v2)

2021-06-04 Thread Hans de Goede
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 833d0c1be4f1..37077b19cf58 100644
--- a/drivers/gpu/drm/i915/display/intel_acpi.c
+++ b/drivers/gpu/drm/i915/display/intel_acpi.c
@@ -263,3 +263,49 @@ void intel_acpi_device_id_update(struct drm_i915_private 
*dev_priv)
}
drm_connector_list_iter_end(_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 = >drm;
+   struct fwnode_handle *fwnode = NULL;
+   struct drm_connector *connector;
+   struct acpi_device *adev;
+
+   drm_connector_list_iter_begin(drm_dev, _iter);
+   drm_for_each_connector_iter(connector, _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(_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 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 caf0414e0b50..4133f657f6a0 100644
--- a/drivers/gpu/drm/i915/display/intel_display.c
+++ b/drivers/gpu/drm/i915/display/intel_display.c
@@ -12381,6 +12381,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_c

[PATCH 4/8] drm/connector: Add support for out-of-band hotplug notification (v3)

2021-06-04 Thread Hans de Goede
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 14644053a678..88ff7a011002 100644
--- a/drivers/gpu/drm/drm_connector.c
+++ b/drivers/gpu/drm/drm_connector.c
@@ -2592,6 +2592,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 b4b08c7a538e..1d896a8e3fa7 100644
--- a/include/drm/drm_connector.h
+++ b/include/drm/drm_connector.h
@@ -1079,6 +1079,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);
 };
 
 /**
@@ -1661,6 +1669,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



<    1   2   3   4   5   6   7   8   9   10   >