* Re: [PATCH v2 1/4] dt-bindings: mfd: Add Gateworks System Controller bindings
From: Fabio Estevam @ 2018-03-10 13:57 UTC (permalink / raw)
To: Tim Harvey
Cc: Lee Jones, Rob Herring, Mark Rutland, Mark Brown, Dmitry Torokhov,
linux-kernel,
open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS,
moderated list:ARM/FREESCALE IMX / MXC ARM ARCHITECTURE,
linux-hwmon, linux-input
In-Reply-To: <1520287361-12569-2-git-send-email-tharvey@gateworks.com>
Hi Tim,
On Mon, Mar 5, 2018 at 7:02 PM, Tim Harvey <tharvey@gateworks.com> wrote:
> +
> + hwmon@1 { /* A1: Input Voltage */
> + type = <1>;
> + reg = <0x02>;
Unit address (@1) does not match the 'reg' value.
If someone build this example with W=1 a warning will be shown.
Same problem happens in other places of this example.
^ permalink raw reply
* [PATCH v2] Input: stmpe-keypad - remove VLA usage
From: Gustavo A. R. Silva @ 2018-03-10 3:36 UTC (permalink / raw)
To: Dmitry Torokhov; +Cc: linux-input, linux-kernel, Gustavo A. R. Silva
In preparation to enabling -Wvla, remove VLA and replace it
with a fixed-length array instead.
Fixed as part of the directive to remove all VLAs from
the kernel: https://lkml.org/lkml/2018/3/7/621
Signed-off-by: Gustavo A. R. Silva <gustavo@embeddedor.com>
---
Changes in v2:
- Update the code based on Dmitry Torokhov comments. Thanks Dmitry.
drivers/input/keyboard/stmpe-keypad.c | 16 ++++++++++++----
1 file changed, 12 insertions(+), 4 deletions(-)
diff --git a/drivers/input/keyboard/stmpe-keypad.c b/drivers/input/keyboard/stmpe-keypad.c
index 8c6c0b9..d69e631 100644
--- a/drivers/input/keyboard/stmpe-keypad.c
+++ b/drivers/input/keyboard/stmpe-keypad.c
@@ -48,6 +48,14 @@
#define STMPE_KEYPAD_KEYMAP_MAX_SIZE \
(STMPE_KEYPAD_MAX_ROWS * STMPE_KEYPAD_MAX_COLS)
+
+#define STMPE1601_NUM_DATA 5
+#define STMPE2401_NUM_DATA 3
+#define STMPE2403_NUM_DATA 5
+
+/* Make sure it covers all cases above */
+#define MAX_NUM_DATA 5
+
/**
* struct stmpe_keypad_variant - model-specific attributes
* @auto_increment: whether the KPC_DATA_BYTE register address
@@ -74,7 +82,7 @@ struct stmpe_keypad_variant {
static const struct stmpe_keypad_variant stmpe_keypad_variants[] = {
[STMPE1601] = {
.auto_increment = true,
- .num_data = 5,
+ .num_data = STMPE1601_NUM_DATA,
.num_normal_data = 3,
.max_cols = 8,
.max_rows = 8,
@@ -84,7 +92,7 @@ static const struct stmpe_keypad_variant stmpe_keypad_variants[] = {
[STMPE2401] = {
.auto_increment = false,
.set_pullup = true,
- .num_data = 3,
+ .num_data = STMPE2401_NUM_DATA,
.num_normal_data = 2,
.max_cols = 8,
.max_rows = 12,
@@ -94,7 +102,7 @@ static const struct stmpe_keypad_variant stmpe_keypad_variants[] = {
[STMPE2403] = {
.auto_increment = true,
.set_pullup = true,
- .num_data = 5,
+ .num_data = STMPE2403_NUM_DATA,
.num_normal_data = 3,
.max_cols = 8,
.max_rows = 12,
@@ -156,7 +164,7 @@ static irqreturn_t stmpe_keypad_irq(int irq, void *dev)
struct stmpe_keypad *keypad = dev;
struct input_dev *input = keypad->input;
const struct stmpe_keypad_variant *variant = keypad->variant;
- u8 fifo[variant->num_data];
+ u8 fifo[MAX_NUM_DATA];
int ret;
int i;
--
2.7.4
^ permalink raw reply related
* Re: [PATCH] Input: stmpe-keypad - remove VLA usage
From: Gustavo A. R. Silva @ 2018-03-10 3:32 UTC (permalink / raw)
To: Dmitry Torokhov; +Cc: linux-input, linux-kernel
In-Reply-To: <20180309233235.GC60941@dtor-ws>
Hi Dmitry,
On 03/09/2018 05:32 PM, Dmitry Torokhov wrote:
> On Fri, Mar 09, 2018 at 04:42:08PM -0600, Gustavo A. R. Silva wrote:
>> In preparation to enabling -Wvla, remove VLA and replace it
>> with a fixed-length array instead.
>>
>> Fixed as part of the directive to remove all VLAs from
>> the kernel: https://lkml.org/lkml/2018/3/7/621
>>
>> Signed-off-by: Gustavo A. R. Silva <garsilva@embeddedor.com>
>> ---
>> drivers/input/keyboard/stmpe-keypad.c | 10 ++++++----
>> 1 file changed, 6 insertions(+), 4 deletions(-)
>>
>> diff --git a/drivers/input/keyboard/stmpe-keypad.c b/drivers/input/keyboard/stmpe-keypad.c
>> index 8c6c0b9..cfa1dbe 100644
>> --- a/drivers/input/keyboard/stmpe-keypad.c
>> +++ b/drivers/input/keyboard/stmpe-keypad.c
>> @@ -48,6 +48,8 @@
>> #define STMPE_KEYPAD_KEYMAP_MAX_SIZE \
>> (STMPE_KEYPAD_MAX_ROWS * STMPE_KEYPAD_MAX_COLS)
>>
>> +#define MAX_NUM_DATA 5
>> +
>> /**
>> * struct stmpe_keypad_variant - model-specific attributes
>> * @auto_increment: whether the KPC_DATA_BYTE register address
>> @@ -74,7 +76,7 @@ struct stmpe_keypad_variant {
>> static const struct stmpe_keypad_variant stmpe_keypad_variants[] = {
>> [STMPE1601] = {
>> .auto_increment = true,
>> - .num_data = 5,
>> + .num_data = MAX_NUM_DATA,
>> .num_normal_data = 3,
>> .max_cols = 8,
>> .max_rows = 8,
>> @@ -84,7 +86,7 @@ static const struct stmpe_keypad_variant stmpe_keypad_variants[] = {
>> [STMPE2401] = {
>> .auto_increment = false,
>> .set_pullup = true,
>> - .num_data = 3,
>> + .num_data = MAX_NUM_DATA - 2,
>
> Logically MAX_NUM_DATA - 2 does not mean anything, it is simply a way
> for you to get to 3, so I'd rather we did not do that.
>
Yeah. I agree.
> Can we do
>
> #define STMPE1601_NUM_DATA 5
> #define STMPE2401_NUM_DATA 3
> #define STMPE2403_NUM_DATA 5
> #define MAX_NUM_DATA max3(STMPE1601_NUM_DATA, \
> STMPE2401_NUM_DATA, \
> STMPE2403_NUM_DATA)
>
>
> or simply
>
> /* Make sure it covers all cases above */
> #define MAX_NUM_DATA 5
This one works just fine.
I'll send v2 of this patch shortly.
Thanks for the feedback.
I appreciate it.
--
Gustavo
>
>> .num_normal_data = 2,
>> .max_cols = 8,
>> .max_rows = 12,
>> @@ -94,7 +96,7 @@ static const struct stmpe_keypad_variant stmpe_keypad_variants[] = {
>> [STMPE2403] = {
>> .auto_increment = true,
>> .set_pullup = true,
>> - .num_data = 5,
>> + .num_data = MAX_NUM_DATA,
>> .num_normal_data = 3,
>> .max_cols = 8,
>> .max_rows = 12,
>> @@ -156,7 +158,7 @@ static irqreturn_t stmpe_keypad_irq(int irq, void *dev)
>> struct stmpe_keypad *keypad = dev;
>> struct input_dev *input = keypad->input;
>> const struct stmpe_keypad_variant *variant = keypad->variant;
>> - u8 fifo[variant->num_data];
>> + u8 fifo[MAX_NUM_DATA];
>> int ret;
>> int i;
>>
>> --
>> 2.7.4
>>
>
> Thanks.
>
^ permalink raw reply
* Re: [PATCH] Input: stmpe-keypad - remove VLA usage
From: Dmitry Torokhov @ 2018-03-09 23:32 UTC (permalink / raw)
To: Gustavo A. R. Silva; +Cc: linux-input, linux-kernel
In-Reply-To: <20180309224208.GA7080@embeddedor.com>
On Fri, Mar 09, 2018 at 04:42:08PM -0600, Gustavo A. R. Silva wrote:
> In preparation to enabling -Wvla, remove VLA and replace it
> with a fixed-length array instead.
>
> Fixed as part of the directive to remove all VLAs from
> the kernel: https://lkml.org/lkml/2018/3/7/621
>
> Signed-off-by: Gustavo A. R. Silva <garsilva@embeddedor.com>
> ---
> drivers/input/keyboard/stmpe-keypad.c | 10 ++++++----
> 1 file changed, 6 insertions(+), 4 deletions(-)
>
> diff --git a/drivers/input/keyboard/stmpe-keypad.c b/drivers/input/keyboard/stmpe-keypad.c
> index 8c6c0b9..cfa1dbe 100644
> --- a/drivers/input/keyboard/stmpe-keypad.c
> +++ b/drivers/input/keyboard/stmpe-keypad.c
> @@ -48,6 +48,8 @@
> #define STMPE_KEYPAD_KEYMAP_MAX_SIZE \
> (STMPE_KEYPAD_MAX_ROWS * STMPE_KEYPAD_MAX_COLS)
>
> +#define MAX_NUM_DATA 5
> +
> /**
> * struct stmpe_keypad_variant - model-specific attributes
> * @auto_increment: whether the KPC_DATA_BYTE register address
> @@ -74,7 +76,7 @@ struct stmpe_keypad_variant {
> static const struct stmpe_keypad_variant stmpe_keypad_variants[] = {
> [STMPE1601] = {
> .auto_increment = true,
> - .num_data = 5,
> + .num_data = MAX_NUM_DATA,
> .num_normal_data = 3,
> .max_cols = 8,
> .max_rows = 8,
> @@ -84,7 +86,7 @@ static const struct stmpe_keypad_variant stmpe_keypad_variants[] = {
> [STMPE2401] = {
> .auto_increment = false,
> .set_pullup = true,
> - .num_data = 3,
> + .num_data = MAX_NUM_DATA - 2,
Logically MAX_NUM_DATA - 2 does not mean anything, it is simply a way
for you to get to 3, so I'd rather we did not do that.
Can we do
#define STMPE1601_NUM_DATA 5
#define STMPE2401_NUM_DATA 3
#define STMPE2403_NUM_DATA 5
#define MAX_NUM_DATA max3(STMPE1601_NUM_DATA, \
STMPE2401_NUM_DATA, \
STMPE2403_NUM_DATA)
or simply
/* Make sure it covers all cases above */
#define MAX_NUM_DATA 5
> .num_normal_data = 2,
> .max_cols = 8,
> .max_rows = 12,
> @@ -94,7 +96,7 @@ static const struct stmpe_keypad_variant stmpe_keypad_variants[] = {
> [STMPE2403] = {
> .auto_increment = true,
> .set_pullup = true,
> - .num_data = 5,
> + .num_data = MAX_NUM_DATA,
> .num_normal_data = 3,
> .max_cols = 8,
> .max_rows = 12,
> @@ -156,7 +158,7 @@ static irqreturn_t stmpe_keypad_irq(int irq, void *dev)
> struct stmpe_keypad *keypad = dev;
> struct input_dev *input = keypad->input;
> const struct stmpe_keypad_variant *variant = keypad->variant;
> - u8 fifo[variant->num_data];
> + u8 fifo[MAX_NUM_DATA];
> int ret;
> int i;
>
> --
> 2.7.4
>
Thanks.
--
Dmitry
^ permalink raw reply
* Re: [PATCH v5 1/3] Input: gpio-keys - add support for wakeup event action
From: Rob Herring @ 2018-03-09 23:27 UTC (permalink / raw)
To: Jeffy Chen
Cc: linux-kernel, briannorris, heiko, dtor, dianders, devicetree,
Guenter Roeck, Thomas Gleixner, Joseph Lo, stephen lu,
Dmitry Torokhov, Kate Stewart, linux-input, Greg Kroah-Hartman,
Mark Rutland, Philippe Ombredanne, Arvind Yadav
In-Reply-To: <20180308073213.8419-2-jeffy.chen@rock-chips.com>
On Thu, Mar 08, 2018 at 03:32:11PM +0800, Jeffy Chen wrote:
> Add support for specifying event actions to trigger wakeup when using
> the gpio-keys input device as a wakeup source.
>
> This would allow the device to configure when to wakeup the system. For
> example a gpio-keys input device for pen insert, may only want to wakeup
> the system when ejecting the pen.
>
> Suggested-by: Brian Norris <briannorris@chromium.org>
> Signed-off-by: Jeffy Chen <jeffy.chen@rock-chips.com>
> ---
>
> Changes in v5:
> Remove unneeded irq_wake flag as Andy suggested.
>
> Changes in v4:
> Add dt-binding gpio-keys.h, stop saving irq trigger type, add enable/disable wakeup helpers as Dmitry suggested.
>
> Changes in v3:
> Adding more comments as Brian suggested.
>
> Changes in v2:
> Specify wakeup event action instead of irq trigger type as Brian
> suggested.
>
> drivers/input/keyboard/gpio_keys.c | 63 +++++++++++++++++++++++++++++++++--
> include/dt-bindings/input/gpio-keys.h | 13 ++++++++
This file should be in the binding patch.
> include/linux/gpio_keys.h | 2 ++
> 3 files changed, 75 insertions(+), 3 deletions(-)
> create mode 100644 include/dt-bindings/input/gpio-keys.h
^ permalink raw reply
* Re: [PATCH v2 1/4] dt-bindings: mfd: Add Gateworks System Controller bindings
From: Rob Herring @ 2018-03-09 23:14 UTC (permalink / raw)
To: Tim Harvey
Cc: Lee Jones, Mark Rutland, Mark Brown, Dmitry Torokhov,
linux-kernel, devicetree, linux-arm-kernel, linux-hwmon,
linux-input
In-Reply-To: <1520287361-12569-2-git-send-email-tharvey@gateworks.com>
On Mon, Mar 05, 2018 at 02:02:38PM -0800, Tim Harvey wrote:
> This patch adds documentation of device-tree bindings for the
> Gateworks System Controller (GSC).
>
> Signed-off-by: Tim Harvey <tharvey@gateworks.com>
> ---
> Documentation/devicetree/bindings/mfd/gsc.txt | 159 ++++++++++++++++++++++++++
> 1 file changed, 159 insertions(+)
> create mode 100644 Documentation/devicetree/bindings/mfd/gsc.txt
>
> diff --git a/Documentation/devicetree/bindings/mfd/gsc.txt b/Documentation/devicetree/bindings/mfd/gsc.txt
> new file mode 100644
> index 0000000..fe5d114
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/mfd/gsc.txt
> @@ -0,0 +1,159 @@
> +Gateworks System Controller multi-function device
> +
> +The GSC is a Multifunction I2C slave device with the following submodules:
> +- WDT
> +- GPIO
> +- Pushbutton controller
> +- HWMON
> +
> +Required properties:
> +- compatible : Must be "gw,gsc_v1", "gw,gsc_v2", "gw,gsc_v3"
s/_/-/
> +- reg: I2C address of the device
> +- interrupts: interrupt triggered by GSC_IRQ# signal
> +- interrupt-parent: Interrupt controller GSC is connected to
> +- #interrupt-cells: should be <1>, index of the interrupt within the
> + controller, in accordance with the "one cell" variant of
> + <devicetree/bindings/interrupt-controller/interrupt.txt>
> +
> +Optional nodes:
> +* watchdog:
> +The GSC provides a Watchdog monitor which can power cycle the board's
> +primary power supply on most board models when tripped.
> +
> +Required properties:
> +- compatible: must be "gw,gsc-watchdog"
> +
> +* input:
> +The GSC provides an input device capable of dispatching Linux Input events
Linux details that are not relevant to the binding.
> +for user pushbutton events, tamper switch events, etc.
> +
> +Required properties:
> +- compatible: must be "gw,gsc-input"
> +
> +* hwmon:
> +The GSC provides a set of Analog to Digitcal Converter (ADC) pins used for
> +temperature and/or voltage monitoring.
> +
> +Required properties:
> +- compatible: must be "gw,gsc-hwmon"
> +
> +Example:
> +
> + gsc: gsc@20 {
> + compatible = "gw,gsc_v2";
> + reg = <0x20>;
> + interrupt-parent = <&gpio1>;
> + interrupts = <4 GPIO_ACTIVE_LOW>;
> + interrupt-controller;
> + #interrupt-cells = <1>;
> +
> + gsc_input {
input {
> + compatible = "gw,gsc-input";
> + };
> +
> + gsc_watchdog {
watchdog {
> + compatible = "gw,gsc-watchdog";
> + };
> +
> + gsc_hwmon {
hwmon {
> + compatible = "gw,gsc-hwmon";
> + #address-cells = <1>;
> + #size-cells = <0>;
> +
> + hwmon@0 { /* A0: Board Temperature */
> + type = <0>;
Not documented.
> + reg = <0x00>;
> + label = "temp";
> + };
> +
> + hwmon@1 { /* A1: Input Voltage */
> + type = <1>;
> + reg = <0x02>;
> + label = "Vin";
> + };
> +
> + hwmon@2 { /* A2: 5P0 */
> + type = <1>;
> + reg = <0x0b>;
> + label = "5P0";
> + };
> +
> + hwmon@4 { /* A4: 0-5V input */
> + type = <1>;
> + reg = <0x14>;
> + label = "ANL0";
> + };
> +
> + hwmon@5 { /* A5: 2P5 PCIe/GigE */
> + type = <1>;
> + reg = <0x23>;
> + label = "2P5";
> + };
> +
> + hwmon@6 { /* A6: 1P8 Aud/Vid */
> + type = <1>;
> + reg = <0x1d>;
> + label = "1P8";
> + };
> +
> + hwmon@7 { /* A7: GPS */
> + type = <1>;
> + reg = <0x26>;
> + label = "GPS";
> + };
> +
> + hwmon@12 { /* A12: VDD_CORE */
> + type = <1>;
> + reg = <0x3>;
> + label = "VDD_CORE";
> + };
> +
> + hwmon@13 { /* A13: VDD_SOC */
> + type = <1>;
> + reg = <0x11>;
> + label = "VDD_SOC";
> + };
> +
> + hwmon@14 { /* A14: 1P0 PCIe SW */
> + type = <1>;
> + reg = <0x20>;
> + label = "1P0";
> + };
> +
> + hwmon@15 { /* fan0 */
> + type = <2>;
> + reg = <0x2c>;
> + label = "fan_50p";
> + };
> +
> + hwmon@16 { /* fan1 */
> + type = <2>;
> + reg = <0x2e>;
> + label = "fan_60p";
> + };
> +
> + hwmon@17 { /* fan2 */
> + type = <2>;
> + reg = <0x30>;
> + label = "fan_70p";
> + };
> +
> + hwmon@18 { /* fan3 */
> + type = <2>;
> + reg = <0x32>;
> + label = "fan_80p";
> + };
> +
> + hwmon@19 { /* fan4 */
> + type = <2>;
> + reg = <0x34>;
> + label = "fan_90p";
> + };
> +
> + hwmon@20 { /* fan5 */
> + type = <2>;
> + reg = <0x36>;
> + label = "fan_100p";
> + };
> + };
> + };
> --
> 2.7.4
>
^ permalink raw reply
* [PATCH] Input: stmpe-keypad - remove VLA usage
From: Gustavo A. R. Silva @ 2018-03-09 22:42 UTC (permalink / raw)
To: Dmitry Torokhov; +Cc: linux-input, linux-kernel, Gustavo A. R. Silva
In preparation to enabling -Wvla, remove VLA and replace it
with a fixed-length array instead.
Fixed as part of the directive to remove all VLAs from
the kernel: https://lkml.org/lkml/2018/3/7/621
Signed-off-by: Gustavo A. R. Silva <garsilva@embeddedor.com>
---
drivers/input/keyboard/stmpe-keypad.c | 10 ++++++----
1 file changed, 6 insertions(+), 4 deletions(-)
diff --git a/drivers/input/keyboard/stmpe-keypad.c b/drivers/input/keyboard/stmpe-keypad.c
index 8c6c0b9..cfa1dbe 100644
--- a/drivers/input/keyboard/stmpe-keypad.c
+++ b/drivers/input/keyboard/stmpe-keypad.c
@@ -48,6 +48,8 @@
#define STMPE_KEYPAD_KEYMAP_MAX_SIZE \
(STMPE_KEYPAD_MAX_ROWS * STMPE_KEYPAD_MAX_COLS)
+#define MAX_NUM_DATA 5
+
/**
* struct stmpe_keypad_variant - model-specific attributes
* @auto_increment: whether the KPC_DATA_BYTE register address
@@ -74,7 +76,7 @@ struct stmpe_keypad_variant {
static const struct stmpe_keypad_variant stmpe_keypad_variants[] = {
[STMPE1601] = {
.auto_increment = true,
- .num_data = 5,
+ .num_data = MAX_NUM_DATA,
.num_normal_data = 3,
.max_cols = 8,
.max_rows = 8,
@@ -84,7 +86,7 @@ static const struct stmpe_keypad_variant stmpe_keypad_variants[] = {
[STMPE2401] = {
.auto_increment = false,
.set_pullup = true,
- .num_data = 3,
+ .num_data = MAX_NUM_DATA - 2,
.num_normal_data = 2,
.max_cols = 8,
.max_rows = 12,
@@ -94,7 +96,7 @@ static const struct stmpe_keypad_variant stmpe_keypad_variants[] = {
[STMPE2403] = {
.auto_increment = true,
.set_pullup = true,
- .num_data = 5,
+ .num_data = MAX_NUM_DATA,
.num_normal_data = 3,
.max_cols = 8,
.max_rows = 12,
@@ -156,7 +158,7 @@ static irqreturn_t stmpe_keypad_irq(int irq, void *dev)
struct stmpe_keypad *keypad = dev;
struct input_dev *input = keypad->input;
const struct stmpe_keypad_variant *variant = keypad->variant;
- u8 fifo[variant->num_data];
+ u8 fifo[MAX_NUM_DATA];
int ret;
int i;
--
2.7.4
^ permalink raw reply related
* [PATCH v5 36/36] drm/rockchip: psr: Remove flush by CRTC
From: Enric Balletbo i Serra @ 2018-03-09 22:23 UTC (permalink / raw)
To: architt, inki.dae, thierry.reding, hjc, seanpaul, airlied, tfiga,
heiko
Cc: dri-devel, dianders, a.hajda, ykk, kernel, m.szyprowski,
linux-samsung-soc, jy0922.shim, rydberg, krzk, linux-rockchip,
kgene, linux-input, orjan.eide, wxt, jeffy.chen, linux-arm-kernel,
mark.yao, wzz, hl, jingoohan1, sw0312.kim, linux-kernel,
kyungmin.park, Laurent.pinchart, kuankuan.y, hshi,
Enric Balletbo i Serra
In-Reply-To: <20180309222327.18689-1-enric.balletbo@collabora.com>
From: Tomasz Figa <tfiga@chromium.org>
It is not used anymore after last changes and it was not even correct to
begin with as it assumed a 1:1 relation between a CRTC and encoder,
while in fact a CRTC can be attached to multiple encoders.
Signed-off-by: Tomasz Figa <tfiga@chromium.org>
Signed-off-by: Thierry Escande <thierry.escande@collabora.com>
Signed-off-by: Enric Balletbo i Serra <enric.balletbo@collabora.com>
Tested-by: Marek Szyprowski <m.szyprowski@samsung.com>
---
drivers/gpu/drm/rockchip/rockchip_drm_psr.c | 35 -----------------------------
drivers/gpu/drm/rockchip/rockchip_drm_psr.h | 1 -
2 files changed, 36 deletions(-)
diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_psr.c b/drivers/gpu/drm/rockchip/rockchip_drm_psr.c
index 1bf5cba9a64d..b1988ac758d5 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_psr.c
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_psr.c
@@ -40,23 +40,6 @@ struct psr_drv {
int (*set)(struct drm_encoder *encoder, bool enable);
};
-static struct psr_drv *find_psr_by_crtc(struct drm_crtc *crtc)
-{
- struct rockchip_drm_private *drm_drv = crtc->dev->dev_private;
- struct psr_drv *psr;
-
- mutex_lock(&drm_drv->psr_list_lock);
- list_for_each_entry(psr, &drm_drv->psr_list, list) {
- if (psr->encoder->crtc == crtc)
- goto out;
- }
- psr = ERR_PTR(-ENODEV);
-
-out:
- mutex_unlock(&drm_drv->psr_list_lock);
- return psr;
-}
-
static struct psr_drv *find_psr_by_encoder(struct drm_encoder *encoder)
{
struct rockchip_drm_private *drm_drv = encoder->dev->dev_private;
@@ -173,24 +156,6 @@ static void rockchip_drm_do_flush(struct psr_drv *psr)
mutex_unlock(&psr->lock);
}
-/**
- * rockchip_drm_psr_flush - flush a single pipe
- * @crtc: CRTC of the pipe to flush
- *
- * Returns:
- * 0 on success, -errno on fail
- */
-int rockchip_drm_psr_flush(struct drm_crtc *crtc)
-{
- struct psr_drv *psr = find_psr_by_crtc(crtc);
- if (IS_ERR(psr))
- return PTR_ERR(psr);
-
- rockchip_drm_do_flush(psr);
- return 0;
-}
-EXPORT_SYMBOL(rockchip_drm_psr_flush);
-
/**
* rockchip_drm_psr_flush_all - force to flush all registered PSR encoders
* @dev: drm device
diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_psr.h b/drivers/gpu/drm/rockchip/rockchip_drm_psr.h
index 40e026c14168..860c62494496 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_psr.h
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_psr.h
@@ -16,7 +16,6 @@
#define __ROCKCHIP_DRM_PSR___
void rockchip_drm_psr_flush_all(struct drm_device *dev);
-int rockchip_drm_psr_flush(struct drm_crtc *crtc);
int rockchip_drm_psr_inhibit_put(struct drm_encoder *encoder);
int rockchip_drm_psr_inhibit_get(struct drm_encoder *encoder);
--
2.16.1
^ permalink raw reply related
* [PATCH v5 35/36] drm/rockchip: Disallow PSR for the whole atomic commit
From: Enric Balletbo i Serra @ 2018-03-09 22:23 UTC (permalink / raw)
To: architt, inki.dae, thierry.reding, hjc, seanpaul, airlied, tfiga,
heiko
Cc: dri-devel, dianders, a.hajda, ykk, kernel, m.szyprowski,
linux-samsung-soc, jy0922.shim, rydberg, krzk, linux-rockchip,
kgene, linux-input, orjan.eide, wxt, jeffy.chen, linux-arm-kernel,
mark.yao, wzz, hl, jingoohan1, sw0312.kim, linux-kernel,
kyungmin.park, Laurent.pinchart, kuankuan.y, hshi,
Kristian H . Kristensen, Enric Balletbo i Serra
In-Reply-To: <20180309222327.18689-1-enric.balletbo@collabora.com>
From: Tomasz Figa <tfiga@chromium.org>
Currently PSR flush is triggered from CRTC's .atomic_begin() callback,
which is executed after modeset disables and enables and before plane
updates are committed. Since PSR flush and re-enable can be triggered
asynchronously by external sources (input event, delayed work), it can
race with hardware programming done in the aforementioned stages.
This patch blocks the PSR completely before hardware programming part
begins and unblock after it ends. This relies on reference counted PSR
disable introduced with previous patch.
Cc: Kristian H. Kristensen <hoegsberg@chromium.org>
Signed-off-by: Tomasz Figa <tfiga@chromium.org>
Signed-off-by: Sean Paul <seanpaul@chromium.org>
Signed-off-by: Thierry Escande <thierry.escande@collabora.com>
Signed-off-by: Enric Balletbo i Serra <enric.balletbo@collabora.com>
Tested-by: Marek Szyprowski <m.szyprowski@samsung.com>
---
drivers/gpu/drm/rockchip/rockchip_drm_fb.c | 61 ++++++++++++++++++++++++++++-
drivers/gpu/drm/rockchip/rockchip_drm_vop.c | 7 ----
2 files changed, 60 insertions(+), 8 deletions(-)
diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_fb.c b/drivers/gpu/drm/rockchip/rockchip_drm_fb.c
index e266539e04e5..d4f4118b482d 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_fb.c
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_fb.c
@@ -167,8 +167,67 @@ rockchip_user_fb_create(struct drm_device *dev, struct drm_file *file_priv,
return ERR_PTR(ret);
}
+static void
+rockchip_drm_psr_inhibit_get_state(struct drm_atomic_state *state)
+{
+ struct drm_crtc *crtc;
+ struct drm_crtc_state *crtc_state;
+ struct drm_encoder *encoder;
+ u32 encoder_mask = 0;
+ int i;
+
+ for_each_old_crtc_in_state(state, crtc, crtc_state, i) {
+ encoder_mask |= crtc_state->encoder_mask;
+ encoder_mask |= crtc->state->encoder_mask;
+ }
+
+ drm_for_each_encoder_mask(encoder, state->dev, encoder_mask)
+ rockchip_drm_psr_inhibit_get(encoder);
+}
+
+static void
+rockchip_drm_psr_inhibit_put_state(struct drm_atomic_state *state)
+{
+ struct drm_crtc *crtc;
+ struct drm_crtc_state *crtc_state;
+ struct drm_encoder *encoder;
+ u32 encoder_mask = 0;
+ int i;
+
+ for_each_old_crtc_in_state(state, crtc, crtc_state, i) {
+ encoder_mask |= crtc_state->encoder_mask;
+ encoder_mask |= crtc->state->encoder_mask;
+ }
+
+ drm_for_each_encoder_mask(encoder, state->dev, encoder_mask)
+ rockchip_drm_psr_inhibit_put(encoder);
+}
+
+static void
+rockchip_atomic_helper_commit_tail_rpm(struct drm_atomic_state *old_state)
+{
+ struct drm_device *dev = old_state->dev;
+
+ rockchip_drm_psr_inhibit_get_state(old_state);
+
+ drm_atomic_helper_commit_modeset_disables(dev, old_state);
+
+ drm_atomic_helper_commit_modeset_enables(dev, old_state);
+
+ drm_atomic_helper_commit_planes(dev, old_state,
+ DRM_PLANE_COMMIT_ACTIVE_ONLY);
+
+ rockchip_drm_psr_inhibit_put_state(old_state);
+
+ drm_atomic_helper_commit_hw_done(old_state);
+
+ drm_atomic_helper_wait_for_vblanks(dev, old_state);
+
+ drm_atomic_helper_cleanup_planes(dev, old_state);
+}
+
static const struct drm_mode_config_helper_funcs rockchip_mode_config_helpers = {
- .atomic_commit_tail = drm_atomic_helper_commit_tail_rpm,
+ .atomic_commit_tail = rockchip_atomic_helper_commit_tail_rpm,
};
static const struct drm_mode_config_funcs rockchip_drm_mode_config_funcs = {
diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
index e2c9ee3204f4..27e37b653b61 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
@@ -1027,16 +1027,9 @@ static void vop_crtc_atomic_flush(struct drm_crtc *crtc,
}
}
-static void vop_crtc_atomic_begin(struct drm_crtc *crtc,
- struct drm_crtc_state *old_crtc_state)
-{
- rockchip_drm_psr_flush(crtc);
-}
-
static const struct drm_crtc_helper_funcs vop_crtc_helper_funcs = {
.mode_fixup = vop_crtc_mode_fixup,
.atomic_flush = vop_crtc_atomic_flush,
- .atomic_begin = vop_crtc_atomic_begin,
.atomic_enable = vop_crtc_atomic_enable,
.atomic_disable = vop_crtc_atomic_disable,
};
--
2.16.1
^ permalink raw reply related
* [PATCH v5 34/36] drm/rockchip: Disable PSR from reboot notifier
From: Enric Balletbo i Serra @ 2018-03-09 22:23 UTC (permalink / raw)
To: architt, inki.dae, thierry.reding, hjc, seanpaul, airlied, tfiga,
heiko
Cc: dri-devel, dianders, a.hajda, ykk, kernel, m.szyprowski,
linux-samsung-soc, jy0922.shim, rydberg, krzk, linux-rockchip,
kgene, linux-input, orjan.eide, wxt, jeffy.chen, linux-arm-kernel,
mark.yao, wzz, hl, jingoohan1, sw0312.kim, linux-kernel,
kyungmin.park, Laurent.pinchart, kuankuan.y, hshi,
Enric Balletbo i Serra
In-Reply-To: <20180309222327.18689-1-enric.balletbo@collabora.com>
From: Tomasz Figa <tfiga@chromium.org>
It looks like the driver subsystem detaches devices from power domains
at shutdown without consent of the drivers. This means that we might have
our power domain turned off behind our back and the only way to avoid
problems is to stop doing any hardware programming at some point before
the power is cut. A reboot notifier, despite being a misnomer and
handling shutdowns as well, is a good place to do it.
Signed-off-by: Tomasz Figa <tfiga@chromium.org>
Signed-off-by: Thierry Escande <thierry.escande@collabora.com>
Signed-off-by: Enric Balletbo i Serra <enric.balletbo@collabora.com>
Tested-by: Marek Szyprowski <m.szyprowski@samsung.com>
---
drivers/gpu/drm/rockchip/rockchip_drm_psr.c | 24 ++++++++++++++++++++++++
1 file changed, 24 insertions(+)
diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_psr.c b/drivers/gpu/drm/rockchip/rockchip_drm_psr.c
index e7e16d92d5a1..1bf5cba9a64d 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_psr.c
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_psr.c
@@ -13,6 +13,7 @@
*/
#include <linux/input.h>
+#include <linux/reboot.h>
#include <drm/drmP.h>
#include <drm/drm_crtc_helper.h>
@@ -33,6 +34,7 @@ struct psr_drv {
struct delayed_work flush_work;
struct work_struct disable_work;
+ struct notifier_block reboot_nb;
struct input_handler input_handler;
int (*set)(struct drm_encoder *encoder, bool enable);
@@ -309,6 +311,24 @@ static const struct input_device_id psr_ids[] = {
{ },
};
+static int rockchip_drm_psr_reboot_notifier(struct notifier_block *nb,
+ unsigned long action, void *data)
+{
+ struct psr_drv *psr = container_of(nb, struct psr_drv, reboot_nb);
+
+ /*
+ * It looks like the driver subsystem detaches devices from power
+ * domains at shutdown without consent of the drivers. This means
+ * that we might have our power domain turned off behind our back
+ * and the only way to avoid problems is to stop doing any hardware
+ * programming after this point, which is achieved by the unbalanced
+ * call below.
+ */
+ rockchip_drm_psr_inhibit_get(psr->encoder);
+
+ return 0;
+}
+
/**
* rockchip_drm_psr_register - register encoder to psr driver
* @encoder: encoder that obtain the PSR function
@@ -361,6 +381,9 @@ int rockchip_drm_psr_register(struct drm_encoder *encoder,
if (error)
goto err1;
+ psr->reboot_nb.notifier_call = rockchip_drm_psr_reboot_notifier;
+ register_reboot_notifier(&psr->reboot_nb);
+
mutex_lock(&drm_drv->psr_list_lock);
list_add_tail(&psr->list, &drm_drv->psr_list);
mutex_unlock(&drm_drv->psr_list_lock);
@@ -403,6 +426,7 @@ void rockchip_drm_psr_unregister(struct drm_encoder *encoder)
WARN_ON(psr->inhibit_count != 1);
list_del(&psr->list);
+ unregister_reboot_notifier(&psr->reboot_nb);
input_unregister_handler(&psr->input_handler);
kfree(psr->input_handler.name);
kfree(psr);
--
2.16.1
^ permalink raw reply related
* [PATCH v5 33/36] drm/rockchip: psr: Sanitize semantics of allow/disallow API
From: Enric Balletbo i Serra @ 2018-03-09 22:23 UTC (permalink / raw)
To: architt, inki.dae, thierry.reding, hjc, seanpaul, airlied, tfiga,
heiko
Cc: dri-devel, dianders, a.hajda, ykk, kernel, m.szyprowski,
linux-samsung-soc, jy0922.shim, rydberg, krzk, linux-rockchip,
kgene, linux-input, orjan.eide, wxt, jeffy.chen, linux-arm-kernel,
mark.yao, wzz, hl, jingoohan1, sw0312.kim, linux-kernel,
kyungmin.park, Laurent.pinchart, kuankuan.y, hshi,
Enric Balletbo i Serra
In-Reply-To: <20180309222327.18689-1-enric.balletbo@collabora.com>
From: Tomasz Figa <tfiga@chromium.org>
Currently both rockchip_drm_psr_activate() and _deactivate() only set the
boolean "active" flag without actually making sure that hardware state
complies with it.
Since we are going to extend the usage of this API to properly lock PSR
for the duration of atomic commits, we change the semantics in following
way:
- a counter is used to track the number of disallow requests,
- PSR is actually disabled in hardware on first disallow request,
- PSR enable work is scheduled on last disallow request.
The above allows using the API as a way to deterministically synchronize
PSR state changes with other DRM events, i.e. atomic commits and cursor
updates. As a nice side effect, the naming is sorted out and we have
"inhibit" for stopping the software logic and "enable" for hardware
state.
Signed-off-by: Tomasz Figa <tfiga@chromium.org>
Signed-off-by: Thierry Escande <thierry.escande@collabora.com>
Signed-off-by: Enric Balletbo i Serra <enric.balletbo@collabora.com>
Tested-by: Marek Szyprowski <m.szyprowski@samsung.com>
---
drivers/gpu/drm/rockchip/analogix_dp-rockchip.c | 4 +-
drivers/gpu/drm/rockchip/rockchip_drm_psr.c | 57 ++++++++++++++++++-------
drivers/gpu/drm/rockchip/rockchip_drm_psr.h | 4 +-
3 files changed, 46 insertions(+), 19 deletions(-)
diff --git a/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c b/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c
index 6d45d62466b3..080f05352195 100644
--- a/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c
+++ b/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c
@@ -134,7 +134,7 @@ static int rockchip_dp_poweron_end(struct analogix_dp_plat_data *plat_data)
{
struct rockchip_dp_device *dp = to_dp(plat_data);
- return rockchip_drm_psr_activate(&dp->encoder);
+ return rockchip_drm_psr_inhibit_put(&dp->encoder);
}
static int rockchip_dp_powerdown(struct analogix_dp_plat_data *plat_data)
@@ -142,7 +142,7 @@ static int rockchip_dp_powerdown(struct analogix_dp_plat_data *plat_data)
struct rockchip_dp_device *dp = to_dp(plat_data);
int ret;
- ret = rockchip_drm_psr_deactivate(&dp->encoder);
+ ret = rockchip_drm_psr_inhibit_get(&dp->encoder);
if (ret != 0)
return ret;
diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_psr.c b/drivers/gpu/drm/rockchip/rockchip_drm_psr.c
index 448c5fde241c..e7e16d92d5a1 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_psr.c
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_psr.c
@@ -27,7 +27,7 @@ struct psr_drv {
struct drm_encoder *encoder;
struct mutex lock;
- bool active;
+ int inhibit_count;
bool enabled;
struct delayed_work flush_work;
@@ -76,7 +76,7 @@ static int psr_set_state_locked(struct psr_drv *psr, bool enable)
{
int ret;
- if (!psr->active)
+ if (psr->inhibit_count > 0)
return -EINVAL;
if (enable == psr->enabled)
@@ -101,13 +101,18 @@ static void psr_flush_handler(struct work_struct *work)
}
/**
- * rockchip_drm_psr_activate - activate PSR on the given pipe
+ * rockchip_drm_psr_inhibit_put - release PSR inhibit on given encoder
* @encoder: encoder to obtain the PSR encoder
*
+ * Decrements PSR inhibit count on given encoder. Should be called only
+ * for a PSR inhibit count increment done before. If PSR inhibit counter
+ * reaches zero, PSR flush work is scheduled to make the hardware enter
+ * PSR mode in PSR_FLUSH_TIMEOUT_MS.
+ *
* Returns:
* Zero on success, negative errno on failure.
*/
-int rockchip_drm_psr_activate(struct drm_encoder *encoder)
+int rockchip_drm_psr_inhibit_put(struct drm_encoder *encoder)
{
struct psr_drv *psr = find_psr_by_encoder(encoder);
@@ -115,21 +120,29 @@ int rockchip_drm_psr_activate(struct drm_encoder *encoder)
return PTR_ERR(psr);
mutex_lock(&psr->lock);
- psr->active = true;
+ --psr->inhibit_count;
+ if (!psr->inhibit_count)
+ mod_delayed_work(system_wq, &psr->flush_work,
+ PSR_FLUSH_TIMEOUT_MS);
mutex_unlock(&psr->lock);
return 0;
}
-EXPORT_SYMBOL(rockchip_drm_psr_activate);
+EXPORT_SYMBOL(rockchip_drm_psr_inhibit_put);
/**
- * rockchip_drm_psr_deactivate - deactivate PSR on the given pipe
+ * rockchip_drm_psr_inhibit_get - acquire PSR inhibit on given encoder
* @encoder: encoder to obtain the PSR encoder
*
+ * Increments PSR inhibit count on given encoder. This function guarantees
+ * that after it returns PSR is turned off on given encoder and no PSR-related
+ * hardware state change occurs at least until a matching call to
+ * rockchip_drm_psr_inhibit_put() is done.
+ *
* Returns:
* Zero on success, negative errno on failure.
*/
-int rockchip_drm_psr_deactivate(struct drm_encoder *encoder)
+int rockchip_drm_psr_inhibit_get(struct drm_encoder *encoder)
{
struct psr_drv *psr = find_psr_by_encoder(encoder);
@@ -137,15 +150,15 @@ int rockchip_drm_psr_deactivate(struct drm_encoder *encoder)
return PTR_ERR(psr);
mutex_lock(&psr->lock);
- psr->active = false;
- psr->enabled = false;
+ psr_set_state_locked(psr, false);
+ ++psr->inhibit_count;
mutex_unlock(&psr->lock);
cancel_delayed_work_sync(&psr->flush_work);
cancel_work_sync(&psr->disable_work);
return 0;
}
-EXPORT_SYMBOL(rockchip_drm_psr_deactivate);
+EXPORT_SYMBOL(rockchip_drm_psr_inhibit_get);
static void rockchip_drm_do_flush(struct psr_drv *psr)
{
@@ -301,6 +314,11 @@ static const struct input_device_id psr_ids[] = {
* @encoder: encoder that obtain the PSR function
* @psr_set: call back to set PSR state
*
+ * The function returns with PSR inhibit counter initialized with one
+ * and the caller (typically encoder driver) needs to call
+ * rockchip_drm_psr_inhibit_put() when it becomes ready to accept PSR
+ * enable request.
+ *
* Returns:
* Zero on success, negative errno on failure.
*/
@@ -322,7 +340,7 @@ int rockchip_drm_psr_register(struct drm_encoder *encoder,
INIT_WORK(&psr->disable_work, psr_disable_handler);
mutex_init(&psr->lock);
- psr->active = false;
+ psr->inhibit_count = 1;
psr->enabled = false;
psr->encoder = encoder;
psr->set = psr_set;
@@ -362,6 +380,11 @@ EXPORT_SYMBOL(rockchip_drm_psr_register);
* @encoder: encoder that obtain the PSR function
* @psr_set: call back to set PSR state
*
+ * It is expected that the PSR inhibit counter is 1 when this function is
+ * called, which corresponds to a state when related encoder has been
+ * disconnected from any CRTCs and its driver called
+ * rockchip_drm_psr_inhibit_get() to stop the PSR logic.
+ *
* Returns:
* Zero on success, negative errno on failure.
*/
@@ -373,10 +396,14 @@ void rockchip_drm_psr_unregister(struct drm_encoder *encoder)
mutex_lock(&drm_drv->psr_list_lock);
list_for_each_entry_safe(psr, n, &drm_drv->psr_list, list) {
if (psr->encoder == encoder) {
- input_unregister_handler(&psr->input_handler);
- cancel_delayed_work_sync(&psr->flush_work);
- cancel_work_sync(&psr->disable_work);
+ /*
+ * Any other value would mean that the encoder
+ * is still in use.
+ */
+ WARN_ON(psr->inhibit_count != 1);
+
list_del(&psr->list);
+ input_unregister_handler(&psr->input_handler);
kfree(psr->input_handler.name);
kfree(psr);
}
diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_psr.h b/drivers/gpu/drm/rockchip/rockchip_drm_psr.h
index 06537ee27565..40e026c14168 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_psr.h
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_psr.h
@@ -18,8 +18,8 @@
void rockchip_drm_psr_flush_all(struct drm_device *dev);
int rockchip_drm_psr_flush(struct drm_crtc *crtc);
-int rockchip_drm_psr_activate(struct drm_encoder *encoder);
-int rockchip_drm_psr_deactivate(struct drm_encoder *encoder);
+int rockchip_drm_psr_inhibit_put(struct drm_encoder *encoder);
+int rockchip_drm_psr_inhibit_get(struct drm_encoder *encoder);
int rockchip_drm_psr_register(struct drm_encoder *encoder,
int (*psr_set)(struct drm_encoder *, bool enable));
--
2.16.1
^ permalink raw reply related
* [PATCH v5 32/36] drm/rockchip: psr: Avoid redundant calls to .set() callback
From: Enric Balletbo i Serra @ 2018-03-09 22:23 UTC (permalink / raw)
To: architt, inki.dae, thierry.reding, hjc, seanpaul, airlied, tfiga,
heiko
Cc: dri-devel, dianders, a.hajda, ykk, kernel, m.szyprowski,
linux-samsung-soc, jy0922.shim, rydberg, krzk, linux-rockchip,
kgene, linux-input, orjan.eide, wxt, jeffy.chen, linux-arm-kernel,
mark.yao, wzz, hl, jingoohan1, sw0312.kim, linux-kernel,
kyungmin.park, Laurent.pinchart, kuankuan.y, hshi,
Enric Balletbo i Serra
In-Reply-To: <20180309222327.18689-1-enric.balletbo@collabora.com>
From: Tomasz Figa <tfiga@chromium.org>
The first time after we call rockchip_drm_do_flush() after
rockchip_drm_psr_register(), we go from PSR_DISABLE to PSR_FLUSH. The
difference between PSR_DISABLE and PSR_FLUSH is whether or not we have a
delayed work pending - PSR is off in either state. However
psr_set_state() only catches the transition from PSR_FLUSH to
PSR_DISABLE (which never happens), while going from PSR_DISABLE to
PSR_FLUSH triggers a call to psr->set() to disable PSR while it's
already disabled. This triggers the eDP PHY power-on sequence without
being shut down first and this seems to occasionally leave the encoder
unable to later enable PSR. Let's just simplify the state machine and
simply consider PSR_DISABLE and PSR_FLUSH the same state. This lets us
represent the hardware state by a simple boolean called "enabled" and,
while at it, rename the misleading "active" boolean to "inhibit", which
represents the purpose much better.
Also, userspace can (and does) trigger the rockchip_drm_do_flush() path
from drmModeDirtyFB() at any time, whether or the encoder is active. If
no mode is set, we call into analogix_dp_psr_set() which returns -EINVAL
because encoder->crtc is NULL. Avoid this by starting out with
psr->allowed set to false.
Signed-off-by: Kristian H. Kristensen <hoegsberg@chromium.org>
Signed-off-by: Tomasz Figa <tfiga@chromium.org>
Signed-off-by: Thierry Escande <thierry.escande@collabora.com>
Signed-off-by: Enric Balletbo i Serra <enric.balletbo@collabora.com>
Tested-by: Marek Szyprowski <m.szyprowski@samsung.com>
---
drivers/gpu/drm/rockchip/rockchip_drm_psr.c | 79 +++++++++--------------------
1 file changed, 23 insertions(+), 56 deletions(-)
diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_psr.c b/drivers/gpu/drm/rockchip/rockchip_drm_psr.c
index c8655e625ba2..448c5fde241c 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_psr.c
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_psr.c
@@ -22,19 +22,13 @@
#define PSR_FLUSH_TIMEOUT_MS 100
-enum psr_state {
- PSR_FLUSH,
- PSR_ENABLE,
- PSR_DISABLE,
-};
-
struct psr_drv {
struct list_head list;
struct drm_encoder *encoder;
struct mutex lock;
bool active;
- enum psr_state state;
+ bool enabled;
struct delayed_work flush_work;
struct work_struct disable_work;
@@ -78,52 +72,22 @@ static struct psr_drv *find_psr_by_encoder(struct drm_encoder *encoder)
return psr;
}
-static void psr_set_state_locked(struct psr_drv *psr, enum psr_state state)
+static int psr_set_state_locked(struct psr_drv *psr, bool enable)
{
- /*
- * Allowed finite state machine:
- *
- * PSR_ENABLE < = = = = = > PSR_FLUSH
- * | ^ |
- * | | |
- * v | |
- * PSR_DISABLE < - - - - - - - - -
- */
- if (state == psr->state || !psr->active)
- return;
-
- /* Already disabled in flush, change the state, but not the hardware */
- if (state == PSR_DISABLE && psr->state == PSR_FLUSH) {
- psr->state = state;
- return;
- }
+ int ret;
- /* Actually commit the state change to hardware */
- switch (state) {
- case PSR_ENABLE:
- if (psr->set(psr->encoder, true))
- return;
- break;
-
- case PSR_DISABLE:
- case PSR_FLUSH:
- if (psr->set(psr->encoder, false))
- return;
- break;
-
- default:
- pr_err("%s: Unknown state %d\n", __func__, state);
- return;
- }
+ if (!psr->active)
+ return -EINVAL;
- psr->state = state;
-}
+ if (enable == psr->enabled)
+ return 0;
-static void psr_set_state(struct psr_drv *psr, enum psr_state state)
-{
- mutex_lock(&psr->lock);
- psr_set_state_locked(psr, state);
- mutex_unlock(&psr->lock);
+ ret = psr->set(psr->encoder, enable);
+ if (ret)
+ return ret;
+
+ psr->enabled = enable;
+ return 0;
}
static void psr_flush_handler(struct work_struct *work)
@@ -131,10 +95,8 @@ static void psr_flush_handler(struct work_struct *work)
struct psr_drv *psr = container_of(to_delayed_work(work),
struct psr_drv, flush_work);
- /* If the state has changed since we initiated the flush, do nothing */
mutex_lock(&psr->lock);
- if (psr->state == PSR_FLUSH)
- psr_set_state_locked(psr, PSR_ENABLE);
+ psr_set_state_locked(psr, true);
mutex_unlock(&psr->lock);
}
@@ -176,6 +138,7 @@ int rockchip_drm_psr_deactivate(struct drm_encoder *encoder)
mutex_lock(&psr->lock);
psr->active = false;
+ psr->enabled = false;
mutex_unlock(&psr->lock);
cancel_delayed_work_sync(&psr->flush_work);
cancel_work_sync(&psr->disable_work);
@@ -187,8 +150,12 @@ EXPORT_SYMBOL(rockchip_drm_psr_deactivate);
static void rockchip_drm_do_flush(struct psr_drv *psr)
{
cancel_delayed_work_sync(&psr->flush_work);
- psr_set_state(psr, PSR_FLUSH);
- mod_delayed_work(system_wq, &psr->flush_work, PSR_FLUSH_TIMEOUT_MS);
+
+ mutex_lock(&psr->lock);
+ if (!psr_set_state_locked(psr, false))
+ mod_delayed_work(system_wq, &psr->flush_work,
+ PSR_FLUSH_TIMEOUT_MS);
+ mutex_unlock(&psr->lock);
}
/**
@@ -355,8 +322,8 @@ int rockchip_drm_psr_register(struct drm_encoder *encoder,
INIT_WORK(&psr->disable_work, psr_disable_handler);
mutex_init(&psr->lock);
- psr->active = true;
- psr->state = PSR_DISABLE;
+ psr->active = false;
+ psr->enabled = false;
psr->encoder = encoder;
psr->set = psr_set;
--
2.16.1
^ permalink raw reply related
* [PATCH v5 31/36] drm/rockchip: Cancel PSR enable work before changing the state
From: Enric Balletbo i Serra @ 2018-03-09 22:23 UTC (permalink / raw)
To: architt, inki.dae, thierry.reding, hjc, seanpaul, airlied, tfiga,
heiko
Cc: dri-devel, dianders, a.hajda, ykk, kernel, m.szyprowski,
linux-samsung-soc, jy0922.shim, rydberg, krzk, linux-rockchip,
kgene, linux-input, orjan.eide, wxt, jeffy.chen, linux-arm-kernel,
mark.yao, wzz, hl, jingoohan1, sw0312.kim, linux-kernel,
kyungmin.park, Laurent.pinchart, kuankuan.y, hshi,
Enric Balletbo i Serra
In-Reply-To: <20180309222327.18689-1-enric.balletbo@collabora.com>
From: Tomasz Figa <tfiga@chromium.org>
If we change the state first and reschedule later, we might have the
work executed according to previous scheduled time and end up with PSR
re-enabled instantly. Let's cancel the work before changing the state.
While at it, consolidate psr_disable_handler() to just call
rockchip_drm_do_flush(), as they are both supposed to do the same.
Signed-off-by: Tomasz Figa <tfiga@chromium.org>
Signed-off-by: Thierry Escande <thierry.escande@collabora.com>
Signed-off-by: Enric Balletbo i Serra <enric.balletbo@collabora.com>
Tested-by: Marek Szyprowski <m.szyprowski@samsung.com>
---
drivers/gpu/drm/rockchip/rockchip_drm_psr.c | 20 ++++++++------------
1 file changed, 8 insertions(+), 12 deletions(-)
diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_psr.c b/drivers/gpu/drm/rockchip/rockchip_drm_psr.c
index a107845ba97c..c8655e625ba2 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_psr.c
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_psr.c
@@ -138,18 +138,6 @@ static void psr_flush_handler(struct work_struct *work)
mutex_unlock(&psr->lock);
}
-static void psr_disable_handler(struct work_struct *work)
-{
- struct psr_drv *psr = container_of(work, struct psr_drv, disable_work);
-
- /* If the state has changed since we initiated the flush, do nothing */
- mutex_lock(&psr->lock);
- if (psr->state == PSR_ENABLE)
- psr_set_state_locked(psr, PSR_FLUSH);
- mutex_unlock(&psr->lock);
- mod_delayed_work(system_wq, &psr->flush_work, PSR_FLUSH_TIMEOUT_MS);
-}
-
/**
* rockchip_drm_psr_activate - activate PSR on the given pipe
* @encoder: encoder to obtain the PSR encoder
@@ -198,6 +186,7 @@ EXPORT_SYMBOL(rockchip_drm_psr_deactivate);
static void rockchip_drm_do_flush(struct psr_drv *psr)
{
+ cancel_delayed_work_sync(&psr->flush_work);
psr_set_state(psr, PSR_FLUSH);
mod_delayed_work(system_wq, &psr->flush_work, PSR_FLUSH_TIMEOUT_MS);
}
@@ -244,6 +233,13 @@ void rockchip_drm_psr_flush_all(struct drm_device *dev)
}
EXPORT_SYMBOL(rockchip_drm_psr_flush_all);
+static void psr_disable_handler(struct work_struct *work)
+{
+ struct psr_drv *psr = container_of(work, struct psr_drv, disable_work);
+
+ rockchip_drm_do_flush(psr);
+}
+
static void psr_input_event(struct input_handle *handle,
unsigned int type, unsigned int code,
int value)
--
2.16.1
^ permalink raw reply related
* [PATCH v5 30/36] drm/rockchip: Disable PSR on input events
From: Enric Balletbo i Serra @ 2018-03-09 22:23 UTC (permalink / raw)
To: architt, inki.dae, thierry.reding, hjc, seanpaul, airlied, tfiga,
heiko
Cc: dri-devel, dianders, a.hajda, ykk, kernel, m.szyprowski,
linux-samsung-soc, jy0922.shim, rydberg, krzk, linux-rockchip,
kgene, linux-input, orjan.eide, wxt, jeffy.chen, linux-arm-kernel,
mark.yao, wzz, hl, jingoohan1, sw0312.kim, linux-kernel,
kyungmin.park, Laurent.pinchart, kuankuan.y, hshi,
Kristian H. Kristensen, Enric Balletbo i Serra
In-Reply-To: <20180309222327.18689-1-enric.balletbo@collabora.com>
From: "Kristian H. Kristensen" <hoegsberg@google.com>
To improve PSR exit latency, we speculatively start exiting when we
receive input events. Occasionally, this may lead to false positives,
but most of the time we get a head start on coming out of PSR. Depending
on how userspace takes to produce a new frame in response to the event,
this can completely hide the exit latency. In case of Chrome OS, we
typically get the input notifier 50ms or more before the dirty_fb
triggered exit.
Signed-off-by: Kristian H. Kristensen <hoegsberg@google.com>
Signed-off-by: Thierry Escande <thierry.escande@collabora.com>
Signed-off-by: Enric Balletbo i Serra <enric.balletbo@collabora.com>
Tested-by: Marek Szyprowski <m.szyprowski@samsung.com>
---
drivers/gpu/drm/rockchip/rockchip_drm_psr.c | 134 ++++++++++++++++++++++++++++
1 file changed, 134 insertions(+)
diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_psr.c b/drivers/gpu/drm/rockchip/rockchip_drm_psr.c
index 9376f4396b6b..a107845ba97c 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_psr.c
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_psr.c
@@ -12,6 +12,8 @@
* GNU General Public License for more details.
*/
+#include <linux/input.h>
+
#include <drm/drmP.h>
#include <drm/drm_crtc_helper.h>
@@ -35,6 +37,9 @@ struct psr_drv {
enum psr_state state;
struct delayed_work flush_work;
+ struct work_struct disable_work;
+
+ struct input_handler input_handler;
int (*set)(struct drm_encoder *encoder, bool enable);
};
@@ -133,6 +138,18 @@ static void psr_flush_handler(struct work_struct *work)
mutex_unlock(&psr->lock);
}
+static void psr_disable_handler(struct work_struct *work)
+{
+ struct psr_drv *psr = container_of(work, struct psr_drv, disable_work);
+
+ /* If the state has changed since we initiated the flush, do nothing */
+ mutex_lock(&psr->lock);
+ if (psr->state == PSR_ENABLE)
+ psr_set_state_locked(psr, PSR_FLUSH);
+ mutex_unlock(&psr->lock);
+ mod_delayed_work(system_wq, &psr->flush_work, PSR_FLUSH_TIMEOUT_MS);
+}
+
/**
* rockchip_drm_psr_activate - activate PSR on the given pipe
* @encoder: encoder to obtain the PSR encoder
@@ -173,6 +190,7 @@ int rockchip_drm_psr_deactivate(struct drm_encoder *encoder)
psr->active = false;
mutex_unlock(&psr->lock);
cancel_delayed_work_sync(&psr->flush_work);
+ cancel_work_sync(&psr->disable_work);
return 0;
}
@@ -226,6 +244,95 @@ void rockchip_drm_psr_flush_all(struct drm_device *dev)
}
EXPORT_SYMBOL(rockchip_drm_psr_flush_all);
+static void psr_input_event(struct input_handle *handle,
+ unsigned int type, unsigned int code,
+ int value)
+{
+ struct psr_drv *psr = handle->handler->private;
+
+ schedule_work(&psr->disable_work);
+}
+
+static int psr_input_connect(struct input_handler *handler,
+ struct input_dev *dev,
+ const struct input_device_id *id)
+{
+ struct input_handle *handle;
+ int error;
+
+ handle = kzalloc(sizeof(struct input_handle), GFP_KERNEL);
+ if (!handle)
+ return -ENOMEM;
+
+ handle->dev = dev;
+ handle->handler = handler;
+ handle->name = "rockchip-psr";
+
+ error = input_register_handle(handle);
+ if (error)
+ goto err2;
+
+ error = input_open_device(handle);
+ if (error)
+ goto err1;
+
+ return 0;
+
+err1:
+ input_unregister_handle(handle);
+err2:
+ kfree(handle);
+ return error;
+}
+
+static void psr_input_disconnect(struct input_handle *handle)
+{
+ input_close_device(handle);
+ input_unregister_handle(handle);
+ kfree(handle);
+}
+
+/* Same device ids as cpu-boost */
+static const struct input_device_id psr_ids[] = {
+ {
+ .flags = INPUT_DEVICE_ID_MATCH_EVBIT |
+ INPUT_DEVICE_ID_MATCH_ABSBIT,
+ .evbit = { BIT_MASK(EV_ABS) },
+ .absbit = { [BIT_WORD(ABS_MT_POSITION_X)] =
+ BIT_MASK(ABS_MT_POSITION_X) |
+ BIT_MASK(ABS_MT_POSITION_Y) },
+ }, /* multi-touch touchscreen */
+ {
+ .flags = INPUT_DEVICE_ID_MATCH_EVBIT,
+ .evbit = { BIT_MASK(EV_ABS) },
+ .absbit = { [BIT_WORD(ABS_X)] = BIT_MASK(ABS_X) }
+
+ }, /* stylus or joystick device */
+ {
+ .flags = INPUT_DEVICE_ID_MATCH_EVBIT,
+ .evbit = { BIT_MASK(EV_KEY) },
+ .keybit = { [BIT_WORD(BTN_LEFT)] = BIT_MASK(BTN_LEFT) },
+ }, /* pointer (e.g. trackpad, mouse) */
+ {
+ .flags = INPUT_DEVICE_ID_MATCH_EVBIT,
+ .evbit = { BIT_MASK(EV_KEY) },
+ .keybit = { [BIT_WORD(KEY_ESC)] = BIT_MASK(KEY_ESC) },
+ }, /* keyboard */
+ {
+ .flags = INPUT_DEVICE_ID_MATCH_EVBIT |
+ INPUT_DEVICE_ID_MATCH_KEYBIT,
+ .evbit = { BIT_MASK(EV_KEY) },
+ .keybit = {[BIT_WORD(BTN_JOYSTICK)] = BIT_MASK(BTN_JOYSTICK) },
+ }, /* joysticks not caught by ABS_X above */
+ {
+ .flags = INPUT_DEVICE_ID_MATCH_EVBIT |
+ INPUT_DEVICE_ID_MATCH_KEYBIT,
+ .evbit = { BIT_MASK(EV_KEY) },
+ .keybit = { [BIT_WORD(BTN_GAMEPAD)] = BIT_MASK(BTN_GAMEPAD) },
+ }, /* gamepad */
+ { },
+};
+
/**
* rockchip_drm_psr_register - register encoder to psr driver
* @encoder: encoder that obtain the PSR function
@@ -239,6 +346,7 @@ int rockchip_drm_psr_register(struct drm_encoder *encoder,
{
struct rockchip_drm_private *drm_drv = encoder->dev->dev_private;
struct psr_drv *psr;
+ int error;
if (!encoder || !psr_set)
return -EINVAL;
@@ -248,6 +356,7 @@ int rockchip_drm_psr_register(struct drm_encoder *encoder,
return -ENOMEM;
INIT_DELAYED_WORK(&psr->flush_work, psr_flush_handler);
+ INIT_WORK(&psr->disable_work, psr_disable_handler);
mutex_init(&psr->lock);
psr->active = true;
@@ -255,11 +364,33 @@ int rockchip_drm_psr_register(struct drm_encoder *encoder,
psr->encoder = encoder;
psr->set = psr_set;
+ psr->input_handler.event = psr_input_event;
+ psr->input_handler.connect = psr_input_connect;
+ psr->input_handler.disconnect = psr_input_disconnect;
+ psr->input_handler.name =
+ kasprintf(GFP_KERNEL, "rockchip-psr-%s", encoder->name);
+ if (!psr->input_handler.name) {
+ error = -ENOMEM;
+ goto err2;
+ }
+ psr->input_handler.id_table = psr_ids;
+ psr->input_handler.private = psr;
+
+ error = input_register_handler(&psr->input_handler);
+ if (error)
+ goto err1;
+
mutex_lock(&drm_drv->psr_list_lock);
list_add_tail(&psr->list, &drm_drv->psr_list);
mutex_unlock(&drm_drv->psr_list_lock);
return 0;
+
+ err1:
+ kfree(psr->input_handler.name);
+ err2:
+ kfree(psr);
+ return error;
}
EXPORT_SYMBOL(rockchip_drm_psr_register);
@@ -279,8 +410,11 @@ void rockchip_drm_psr_unregister(struct drm_encoder *encoder)
mutex_lock(&drm_drv->psr_list_lock);
list_for_each_entry_safe(psr, n, &drm_drv->psr_list, list) {
if (psr->encoder == encoder) {
+ input_unregister_handler(&psr->input_handler);
cancel_delayed_work_sync(&psr->flush_work);
+ cancel_work_sync(&psr->disable_work);
list_del(&psr->list);
+ kfree(psr->input_handler.name);
kfree(psr);
}
}
--
2.16.1
^ permalink raw reply related
* [PATCH v5 29/36] drm/rockchip: analogix_dp: Do not call Analogix code before bind
From: Enric Balletbo i Serra @ 2018-03-09 22:23 UTC (permalink / raw)
To: architt, inki.dae, thierry.reding, hjc, seanpaul, airlied, tfiga,
heiko
Cc: dri-devel, dianders, a.hajda, ykk, kernel, m.szyprowski,
linux-samsung-soc, jy0922.shim, rydberg, krzk, linux-rockchip,
kgene, linux-input, orjan.eide, wxt, jeffy.chen, linux-arm-kernel,
mark.yao, wzz, hl, jingoohan1, sw0312.kim, linux-kernel,
kyungmin.park, Laurent.pinchart, kuankuan.y, hshi,
Enric Balletbo i Serra
In-Reply-To: <20180309222327.18689-1-enric.balletbo@collabora.com>
From: Tomasz Figa <tfiga@chromium.org>
Driver callbacks, such as system suspend or resume can be called any
time, specifically they can be called before the component bind
callback. Let's use dp->adp pointer as a safeguard and skip calling
Analogix entry points if it is an ERR_PTR().
Signed-off-by: Tomasz Figa <tfiga@chromium.org>
Signed-off-by: Thierry Escande <thierry.escande@collabora.com>
Signed-off-by: Enric Balletbo i Serra <enric.balletbo@collabora.com>
Tested-by: Marek Szyprowski <m.szyprowski@samsung.com>
---
drivers/gpu/drm/rockchip/analogix_dp-rockchip.c | 9 +++++++++
1 file changed, 9 insertions(+)
diff --git a/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c b/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c
index 23317a2269e1..6d45d62466b3 100644
--- a/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c
+++ b/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c
@@ -368,6 +368,8 @@ static void rockchip_dp_unbind(struct device *dev, struct device *master,
analogix_dp_unbind(dp->adp);
rockchip_drm_psr_unregister(&dp->encoder);
dp->encoder.funcs->destroy(&dp->encoder);
+
+ dp->adp = ERR_PTR(-ENODEV);
}
static const struct component_ops rockchip_dp_component_ops = {
@@ -391,6 +393,7 @@ static int rockchip_dp_probe(struct platform_device *pdev)
return -ENOMEM;
dp->dev = dev;
+ dp->adp = ERR_PTR(-ENODEV);
dp->plat_data.panel = panel;
ret = rockchip_dp_of_probe(dp);
@@ -414,6 +417,9 @@ static int rockchip_dp_suspend(struct device *dev)
{
struct rockchip_dp_device *dp = dev_get_drvdata(dev);
+ if (IS_ERR(dp->adp))
+ return 0;
+
return analogix_dp_suspend(dp->adp);
}
@@ -421,6 +427,9 @@ static int rockchip_dp_resume(struct device *dev)
{
struct rockchip_dp_device *dp = dev_get_drvdata(dev);
+ if (IS_ERR(dp->adp))
+ return 0;
+
return analogix_dp_resume(dp->adp);
}
#endif
--
2.16.1
^ permalink raw reply related
* [PATCH v5 28/36] drm/bridge: analogix_dp: Split the platform-specific poweron in two parts
From: Enric Balletbo i Serra @ 2018-03-09 22:23 UTC (permalink / raw)
To: architt, inki.dae, thierry.reding, hjc, seanpaul, airlied, tfiga,
heiko
Cc: dri-devel, dianders, a.hajda, ykk, kernel, m.szyprowski,
linux-samsung-soc, jy0922.shim, rydberg, krzk, linux-rockchip,
kgene, linux-input, orjan.eide, wxt, jeffy.chen, linux-arm-kernel,
mark.yao, wzz, hl, jingoohan1, sw0312.kim, linux-kernel,
kyungmin.park, Laurent.pinchart, kuankuan.y, hshi,
Kristian H . Kristensen, Enric Balletbo i Serra
In-Reply-To: <20180309222327.18689-1-enric.balletbo@collabora.com>
From: Douglas Anderson <dianders@chromium.org>
Some of the platform-specific stuff in rockchip_dp_poweron() needs to
happen before the generic code. Some needs to happen after. Let's
split the callback in two.
Specifically we can't start doing PSR work until _after_ the whole
controller is up, so don't set the enable until the end.
Cc: Kristian H. Kristensen <hoegsberg@chromium.org>
Signed-off-by: Douglas Anderson <dianders@chromium.org>
[seanpaul added exynos change]
Signed-off-by: Sean Paul <seanpaul@chromium.org>
Signed-off-by: Thierry Escande <thierry.escande@collabora.com>
Reviewed-by: Andrzej Hajda <a.hajda@samsung.com>
Signed-off-by: Enric Balletbo i Serra <enric.balletbo@collabora.com>
Tested-by: Marek Szyprowski <m.szyprowski@samsung.com>
---
drivers/gpu/drm/bridge/analogix/analogix_dp_core.c | 7 +++++--
drivers/gpu/drm/exynos/exynos_dp.c | 2 +-
drivers/gpu/drm/rockchip/analogix_dp-rockchip.c | 12 ++++++++++--
include/drm/bridge/analogix_dp.h | 3 ++-
4 files changed, 18 insertions(+), 6 deletions(-)
diff --git a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
index eaf93cbd47a8..c527019daaa6 100644
--- a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
+++ b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
@@ -1260,8 +1260,8 @@ static int analogix_dp_set_bridge(struct analogix_dp_device *dp)
goto out_dp_clk_pre;
}
- if (dp->plat_data->power_on)
- dp->plat_data->power_on(dp->plat_data);
+ if (dp->plat_data->power_on_start)
+ dp->plat_data->power_on_start(dp->plat_data);
phy_power_on(dp->phy);
@@ -1286,6 +1286,9 @@ static int analogix_dp_set_bridge(struct analogix_dp_device *dp)
goto out_dp_init;
}
+ if (dp->plat_data->power_on_end)
+ dp->plat_data->power_on_end(dp->plat_data);
+
enable_irq(dp->irq);
return 0;
diff --git a/drivers/gpu/drm/exynos/exynos_dp.c b/drivers/gpu/drm/exynos/exynos_dp.c
index 964831dab102..86330f396784 100644
--- a/drivers/gpu/drm/exynos/exynos_dp.c
+++ b/drivers/gpu/drm/exynos/exynos_dp.c
@@ -162,7 +162,7 @@ static int exynos_dp_bind(struct device *dev, struct device *master, void *data)
dp->drm_dev = drm_dev;
dp->plat_data.dev_type = EXYNOS_DP;
- dp->plat_data.power_on = exynos_dp_poweron;
+ dp->plat_data.power_on_start = exynos_dp_poweron;
dp->plat_data.power_off = exynos_dp_poweroff;
dp->plat_data.attach = exynos_dp_bridge_attach;
dp->plat_data.get_modes = exynos_dp_get_modes;
diff --git a/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c b/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c
index b3f46ed24cdc..23317a2269e1 100644
--- a/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c
+++ b/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c
@@ -109,7 +109,7 @@ static int rockchip_dp_pre_init(struct rockchip_dp_device *dp)
return 0;
}
-static int rockchip_dp_poweron(struct analogix_dp_plat_data *plat_data)
+static int rockchip_dp_poweron_start(struct analogix_dp_plat_data *plat_data)
{
struct rockchip_dp_device *dp = to_dp(plat_data);
int ret;
@@ -127,6 +127,13 @@ static int rockchip_dp_poweron(struct analogix_dp_plat_data *plat_data)
return ret;
}
+ return ret;
+}
+
+static int rockchip_dp_poweron_end(struct analogix_dp_plat_data *plat_data)
+{
+ struct rockchip_dp_device *dp = to_dp(plat_data);
+
return rockchip_drm_psr_activate(&dp->encoder);
}
@@ -330,7 +337,8 @@ static int rockchip_dp_bind(struct device *dev, struct device *master,
dp->plat_data.encoder = &dp->encoder;
dp->plat_data.dev_type = dp->data->chip_type;
- dp->plat_data.power_on = rockchip_dp_poweron;
+ dp->plat_data.power_on_start = rockchip_dp_poweron_start;
+ dp->plat_data.power_on_end = rockchip_dp_poweron_end;
dp->plat_data.power_off = rockchip_dp_powerdown;
dp->plat_data.get_modes = rockchip_dp_get_modes;
diff --git a/include/drm/bridge/analogix_dp.h b/include/drm/bridge/analogix_dp.h
index e9a1116d2f8e..475b706b49de 100644
--- a/include/drm/bridge/analogix_dp.h
+++ b/include/drm/bridge/analogix_dp.h
@@ -33,7 +33,8 @@ struct analogix_dp_plat_data {
struct drm_connector *connector;
bool skip_connector;
- int (*power_on)(struct analogix_dp_plat_data *);
+ int (*power_on_start)(struct analogix_dp_plat_data *);
+ int (*power_on_end)(struct analogix_dp_plat_data *);
int (*power_off)(struct analogix_dp_plat_data *);
int (*attach)(struct analogix_dp_plat_data *, struct drm_bridge *,
struct drm_connector *);
--
2.16.1
^ permalink raw reply related
* [PATCH v5 27/36] drm/rockchip: pre dither down when output bpc is 8bit
From: Enric Balletbo i Serra @ 2018-03-09 22:23 UTC (permalink / raw)
To: architt, inki.dae, thierry.reding, hjc, seanpaul, airlied, tfiga,
heiko
Cc: dri-devel, dianders, a.hajda, ykk, kernel, m.szyprowski,
linux-samsung-soc, jy0922.shim, rydberg, krzk, linux-rockchip,
kgene, linux-input, orjan.eide, wxt, jeffy.chen, linux-arm-kernel,
mark.yao, wzz, hl, jingoohan1, sw0312.kim, linux-kernel,
kyungmin.park, Laurent.pinchart, kuankuan.y, hshi,
Enric Balletbo i Serra
In-Reply-To: <20180309222327.18689-1-enric.balletbo@collabora.com>
From: Mark Yao <mark.yao@rock-chips.com>
Some encoder have a crc verification check, crc check fail if
input and output data is not equal.
That means encoder input and output need use same color depth,
vop can output 10bit data to encoder, but some panel only support
8bit depth, that would make crc check die.
So pre dither down vop data to 8bit if panel's bpc is 8.
Signed-off-by: Mark Yao <mark.yao@rock-chips.com>
[seanpaul resolved conflict in rockchip_drm_vop.c]
Signed-off-by: Sean Paul <seanpaul@chromium.org>
Signed-off-by: Thierry Escande <thierry.escande@collabora.com>
Signed-off-by: Enric Balletbo i Serra <enric.balletbo@collabora.com>
Tested-by: Marek Szyprowski <m.szyprowski@samsung.com>
---
drivers/gpu/drm/rockchip/analogix_dp-rockchip.c | 2 ++
drivers/gpu/drm/rockchip/rockchip_drm_drv.h | 1 +
drivers/gpu/drm/rockchip/rockchip_drm_vop.c | 6 ++++++
drivers/gpu/drm/rockchip/rockchip_drm_vop.h | 1 +
drivers/gpu/drm/rockchip/rockchip_vop_reg.c | 1 +
5 files changed, 11 insertions(+)
diff --git a/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c b/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c
index 8c884f9ce713..b3f46ed24cdc 100644
--- a/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c
+++ b/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c
@@ -218,6 +218,7 @@ rockchip_dp_drm_encoder_atomic_check(struct drm_encoder *encoder,
struct drm_connector_state *conn_state)
{
struct rockchip_crtc_state *s = to_rockchip_crtc_state(crtc_state);
+ struct drm_display_info *di = &conn_state->connector->display_info;
/*
* The hardware IC designed that VOP must output the RGB10 video
@@ -229,6 +230,7 @@ rockchip_dp_drm_encoder_atomic_check(struct drm_encoder *encoder,
s->output_mode = ROCKCHIP_OUT_MODE_AAAA;
s->output_type = DRM_MODE_CONNECTOR_eDP;
+ s->output_bpc = di->bpc;
return 0;
}
diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_drv.h b/drivers/gpu/drm/rockchip/rockchip_drm_drv.h
index 9c064a40458b..3a6ebfc26036 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_drv.h
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_drv.h
@@ -36,6 +36,7 @@ struct rockchip_crtc_state {
struct drm_crtc_state base;
int output_type;
int output_mode;
+ int output_bpc;
};
#define to_rockchip_crtc_state(s) \
container_of(s, struct rockchip_crtc_state, base)
diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
index b601c59e76a8..e2c9ee3204f4 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
@@ -923,6 +923,12 @@ static void vop_crtc_atomic_enable(struct drm_crtc *crtc,
if (s->output_mode == ROCKCHIP_OUT_MODE_AAAA &&
!(vop_data->feature & VOP_FEATURE_OUTPUT_RGB10))
s->output_mode = ROCKCHIP_OUT_MODE_P888;
+
+ if (s->output_mode == ROCKCHIP_OUT_MODE_AAAA && s->output_bpc == 8)
+ VOP_REG_SET(vop, common, pre_dither_down, 1);
+ else
+ VOP_REG_SET(vop, common, pre_dither_down, 0);
+
VOP_REG_SET(vop, common, out_mode, s->output_mode);
VOP_REG_SET(vop, modeset, htotal_pw, (htotal << 16) | hsync_len);
diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.h b/drivers/gpu/drm/rockchip/rockchip_drm_vop.h
index 56bbd2e2a8ef..084acdd0019a 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.h
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.h
@@ -67,6 +67,7 @@ struct vop_common {
struct vop_reg cfg_done;
struct vop_reg dsp_blank;
struct vop_reg data_blank;
+ struct vop_reg pre_dither_down;
struct vop_reg dither_down;
struct vop_reg dither_up;
struct vop_reg gate_en;
diff --git a/drivers/gpu/drm/rockchip/rockchip_vop_reg.c b/drivers/gpu/drm/rockchip/rockchip_vop_reg.c
index 2e4eea3459fe..08023d3ecb76 100644
--- a/drivers/gpu/drm/rockchip/rockchip_vop_reg.c
+++ b/drivers/gpu/drm/rockchip/rockchip_vop_reg.c
@@ -264,6 +264,7 @@ static const struct vop_common rk3288_common = {
.standby = VOP_REG_SYNC(RK3288_SYS_CTRL, 0x1, 22),
.gate_en = VOP_REG(RK3288_SYS_CTRL, 0x1, 23),
.mmu_en = VOP_REG(RK3288_SYS_CTRL, 0x1, 20),
+ .pre_dither_down = VOP_REG(RK3288_DSP_CTRL1, 0x1, 1),
.dither_down = VOP_REG(RK3288_DSP_CTRL1, 0xf, 1),
.dither_up = VOP_REG(RK3288_DSP_CTRL1, 0x1, 6),
.data_blank = VOP_REG(RK3288_DSP_CTRL0, 0x1, 19),
--
2.16.1
^ permalink raw reply related
* [PATCH v5 26/36] drm/bridge: analogix_dp: Properly disable aux chan retries on rockchip
From: Enric Balletbo i Serra @ 2018-03-09 22:23 UTC (permalink / raw)
To: architt, inki.dae, thierry.reding, hjc, seanpaul, airlied, tfiga,
heiko
Cc: dri-devel, dianders, a.hajda, ykk, kernel, m.szyprowski,
linux-samsung-soc, jy0922.shim, rydberg, krzk, linux-rockchip,
kgene, linux-input, orjan.eide, wxt, jeffy.chen, linux-arm-kernel,
mark.yao, wzz, hl, jingoohan1, sw0312.kim, linux-kernel,
kyungmin.park, Laurent.pinchart, kuankuan.y, hshi,
Stéphane Marchesin, Enric Balletbo i Serra
In-Reply-To: <20180309222327.18689-1-enric.balletbo@collabora.com>
From: Douglas Anderson <dianders@chromium.org>
The comments in analogix_dp_init_aux() claim that we're disabling aux
channel retries, but then right below it for Rockchip it sets them to
3. If we actually need 3 retries for Rockchip then we could adjust
the comment, but it seems more likely that we want the same retry
behavior across all platforms.
Cc: Stéphane Marchesin <marcheu@chromium.org>
Cc: 征增 王 <wzz@rock-chips.com>
Signed-off-by: Douglas Anderson <dianders@chromium.org>
Signed-off-by: Sean Paul <seanpaul@chromium.org>
Signed-off-by: Thierry Escande <thierry.escande@collabora.com>
Signed-off-by: Enric Balletbo i Serra <enric.balletbo@collabora.com>
Tested-by: Marek Szyprowski <m.szyprowski@samsung.com>
---
drivers/gpu/drm/bridge/analogix/analogix_dp_reg.c | 15 ++++++++-------
1 file changed, 8 insertions(+), 7 deletions(-)
diff --git a/drivers/gpu/drm/bridge/analogix/analogix_dp_reg.c b/drivers/gpu/drm/bridge/analogix/analogix_dp_reg.c
index 58e8a28e99aa..a5f2763d72e4 100644
--- a/drivers/gpu/drm/bridge/analogix/analogix_dp_reg.c
+++ b/drivers/gpu/drm/bridge/analogix/analogix_dp_reg.c
@@ -481,15 +481,16 @@ void analogix_dp_init_aux(struct analogix_dp_device *dp)
analogix_dp_reset_aux(dp);
- /* Disable AUX transaction H/W retry */
+ /* AUX_BIT_PERIOD_EXPECTED_DELAY doesn't apply to Rockchip IP */
if (dp->plat_data && is_rockchip(dp->plat_data->dev_type))
- reg = AUX_BIT_PERIOD_EXPECTED_DELAY(0) |
- AUX_HW_RETRY_COUNT_SEL(3) |
- AUX_HW_RETRY_INTERVAL_600_MICROSECONDS;
+ reg = 0;
else
- reg = AUX_BIT_PERIOD_EXPECTED_DELAY(3) |
- AUX_HW_RETRY_COUNT_SEL(0) |
- AUX_HW_RETRY_INTERVAL_600_MICROSECONDS;
+ reg = AUX_BIT_PERIOD_EXPECTED_DELAY(3);
+
+ /* Disable AUX transaction H/W retry */
+ reg |= AUX_HW_RETRY_COUNT_SEL(0) |
+ AUX_HW_RETRY_INTERVAL_600_MICROSECONDS;
+
writel(reg, dp->reg_base + ANALOGIX_DP_AUX_HW_RETRY_CTL);
/* Receive AUX Channel DEFER commands equal to DEFFER_COUNT*64 */
--
2.16.1
^ permalink raw reply related
* [PATCH v5 25/36] drm/bridge: analogix_dp: Properly log AUX CH errors
From: Enric Balletbo i Serra @ 2018-03-09 22:23 UTC (permalink / raw)
To: architt, inki.dae, thierry.reding, hjc, seanpaul, airlied, tfiga,
heiko
Cc: dri-devel, dianders, a.hajda, ykk, kernel, m.szyprowski,
linux-samsung-soc, jy0922.shim, rydberg, krzk, linux-rockchip,
kgene, linux-input, orjan.eide, wxt, jeffy.chen, linux-arm-kernel,
mark.yao, wzz, hl, jingoohan1, sw0312.kim, linux-kernel,
kyungmin.park, Laurent.pinchart, kuankuan.y, hshi,
Enric Balletbo i Serra
In-Reply-To: <20180309222327.18689-1-enric.balletbo@collabora.com>
From: Douglas Anderson <dianders@chromium.org>
The code in analogix_dp_transfer() that was supposed to print out:
AUX CH error happened
Was actually dead code. That's because the previous check (whether
the interrupt status indicated any errors) would have hit for all
errors anyway.
Let's combine the two error checks so we can actually see AUX CH
errors. We'll also downgrade the message to a warning since some of
these types of errors might be expected for some displays. If this
gets too noisy we can downgrade again to debug.
Cc: 征增 王 <wzz@rock-chips.com>
Signed-off-by: Douglas Anderson <dianders@chromium.org>
Signed-off-by: Sean Paul <seanpaul@chromium.org>
Signed-off-by: Thierry Escande <thierry.escande@collabora.com>
Reviewed-by: Andrzej Hajda <a.hajda@samsung.com>
Signed-off-by: Enric Balletbo i Serra <enric.balletbo@collabora.com>
Tested-by: Marek Szyprowski <m.szyprowski@samsung.com>
---
drivers/gpu/drm/bridge/analogix/analogix_dp_reg.c | 13 +++++--------
1 file changed, 5 insertions(+), 8 deletions(-)
diff --git a/drivers/gpu/drm/bridge/analogix/analogix_dp_reg.c b/drivers/gpu/drm/bridge/analogix/analogix_dp_reg.c
index 4eae206ec31b..58e8a28e99aa 100644
--- a/drivers/gpu/drm/bridge/analogix/analogix_dp_reg.c
+++ b/drivers/gpu/drm/bridge/analogix/analogix_dp_reg.c
@@ -1105,6 +1105,7 @@ ssize_t analogix_dp_transfer(struct analogix_dp_device *dp,
struct drm_dp_aux_msg *msg)
{
u32 reg;
+ u32 status_reg;
u8 *buffer = msg->buffer;
unsigned int i;
int num_transferred = 0;
@@ -1193,16 +1194,12 @@ ssize_t analogix_dp_transfer(struct analogix_dp_device *dp,
/* Clear interrupt source for AUX CH access error */
reg = readl(dp->reg_base + ANALOGIX_DP_INT_STA);
- if (reg & AUX_ERR) {
+ status_reg = readl(dp->reg_base + ANALOGIX_DP_AUX_CH_STA);
+ if ((reg & AUX_ERR) || (status_reg & AUX_STATUS_MASK)) {
writel(AUX_ERR, dp->reg_base + ANALOGIX_DP_INT_STA);
- goto aux_error;
- }
- /* Check AUX CH error access status */
- reg = readl(dp->reg_base + ANALOGIX_DP_AUX_CH_STA);
- if ((reg & AUX_STATUS_MASK)) {
- dev_err(dp->dev, "AUX CH error happened: %d\n\n",
- reg & AUX_STATUS_MASK);
+ dev_warn(dp->dev, "AUX CH error happened: %#x (%d)\n",
+ status_reg & AUX_STATUS_MASK, !!(reg & AUX_ERR));
goto aux_error;
}
--
2.16.1
^ permalink raw reply related
* [PATCH v5 24/36] drm/bridge: analogix_dp: Reorder plat_data->power_off to happen sooner
From: Enric Balletbo i Serra @ 2018-03-09 22:23 UTC (permalink / raw)
To: architt, inki.dae, thierry.reding, hjc, seanpaul, airlied, tfiga,
heiko
Cc: dri-devel, dianders, a.hajda, ykk, kernel, m.szyprowski,
linux-samsung-soc, jy0922.shim, rydberg, krzk, linux-rockchip,
kgene, linux-input, orjan.eide, wxt, jeffy.chen, linux-arm-kernel,
mark.yao, wzz, hl, jingoohan1, sw0312.kim, linux-kernel,
kyungmin.park, Laurent.pinchart, kuankuan.y, hshi,
Kristian H . Kristensen, Enric Balletbo i Serra
In-Reply-To: <20180309222327.18689-1-enric.balletbo@collabora.com>
From: Douglas Anderson <dianders@chromium.org>
The current user of the analogix power_off is "analogix_dp-rockchip".
That driver does this:
- deactivate PSR
- turn off a clock
Both of these things (especially deactive PSR) should be done before
we turn the PHY power off and turn off analog power. Let's move the
callback up.
Note that without this patch (and with
https://patchwork.kernel.org/patch/9553349/ [seanpaul: this patch was
not applied, but it seems like the race can still occur]), I experienced
an error in reboot testing where one thread was at:
rockchip_drm_psr_deactivate
rockchip_dp_powerdown
analogix_dp_bridge_disable
drm_bridge_disable
...and the other thread was at:
analogix_dp_send_psr_spd
analogix_dp_enable_psr
analogix_dp_psr_set
psr_flush_handler
The flush handler thread was finding AUX channel errors and eventually
reported "Failed to apply PSR", where I had a kgdb breakpoint. Presumably
the device would have eventually given up and shut down anyway, but it
seems better to fix the order to be more correct.
Cc: Kristian H. Kristensen <hoegsberg@chromium.org>
Signed-off-by: Douglas Anderson <dianders@chromium.org>
Signed-off-by: Sean Paul <seanpaul@chromium.org>
Signed-off-by: Thierry Escande <thierry.escande@collabora.com>
Reviewed-by: Andrzej Hajda <a.hajda@samsung.com>
Signed-off-by: Enric Balletbo i Serra <enric.balletbo@collabora.com>
Tested-by: Marek Szyprowski <m.szyprowski@samsung.com>
---
drivers/gpu/drm/bridge/analogix/analogix_dp_core.c | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
index 37b16643f14c..eaf93cbd47a8 100644
--- a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
+++ b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
@@ -1337,12 +1337,13 @@ static void analogix_dp_bridge_disable(struct drm_bridge *bridge)
}
disable_irq(dp->irq);
- analogix_dp_set_analog_power_down(dp, POWER_ALL, 1);
- phy_power_off(dp->phy);
if (dp->plat_data->power_off)
dp->plat_data->power_off(dp->plat_data);
+ analogix_dp_set_analog_power_down(dp, POWER_ALL, 1);
+ phy_power_off(dp->phy);
+
clk_disable_unprepare(dp->clock);
pm_runtime_put_sync(dp->dev);
--
2.16.1
^ permalink raw reply related
* [PATCH v5 23/36] drm/bridge: analogix_dp: Move fast link training detect to set_bridge
From: Enric Balletbo i Serra @ 2018-03-09 22:23 UTC (permalink / raw)
To: architt, inki.dae, thierry.reding, hjc, seanpaul, airlied, tfiga,
heiko
Cc: dri-devel, dianders, a.hajda, ykk, kernel, m.szyprowski,
linux-samsung-soc, jy0922.shim, rydberg, krzk, linux-rockchip,
kgene, linux-input, orjan.eide, wxt, jeffy.chen, linux-arm-kernel,
mark.yao, wzz, hl, jingoohan1, sw0312.kim, linux-kernel,
kyungmin.park, Laurent.pinchart, kuankuan.y, hshi,
Enric Balletbo i Serra
In-Reply-To: <20180309222327.18689-1-enric.balletbo@collabora.com>
From: zain wang <wzz@rock-chips.com>
It's too early to detect fast link training, if other step after it
failed, we will set fast_link flag to 1, and retry set_bridge again. In
this case we will power down and power up panel power supply, and we
will do fast link training since we have set fast_link flag to 1. In
fact, we should do full link training now, not the fast link training.
So we should move the fast link detection at the end of set_bridge.
Cc: Tomasz Figa <tfiga@chromium.org>
Signed-off-by: zain wang <wzz@rock-chips.com>
Signed-off-by: Douglas Anderson <dianders@chromium.org>
Signed-off-by: Sean Paul <seanpaul@chromium.org>
Signed-off-by: Thierry Escande <thierry.escande@collabora.com>
Reviewed-by: Andrzej Hajda <a.hajda@samsung.com>
Signed-off-by: Enric Balletbo i Serra <enric.balletbo@collabora.com>
Tested-by: Marek Szyprowski <m.szyprowski@samsung.com>
---
drivers/gpu/drm/bridge/analogix/analogix_dp_core.c | 42 +++++++++++++---------
1 file changed, 26 insertions(+), 16 deletions(-)
diff --git a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
index d76e1652b1fd..37b16643f14c 100644
--- a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
+++ b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
@@ -601,7 +601,7 @@ static int analogix_dp_process_equalizer_training(struct analogix_dp_device *dp)
{
int lane, lane_count, retval;
u32 reg;
- u8 link_align, link_status[2], adjust_request[2], spread;
+ u8 link_align, link_status[2], adjust_request[2];
usleep_range(400, 401);
@@ -645,20 +645,6 @@ static int analogix_dp_process_equalizer_training(struct analogix_dp_device *dp)
dev_dbg(dp->dev, "final lane count = %.2x\n",
dp->link_train.lane_count);
- retval = drm_dp_dpcd_readb(&dp->aux, DP_MAX_DOWNSPREAD,
- &spread);
- if (retval != 1) {
- dev_err(dp->dev, "failed to read downspread %d\n",
- retval);
- dp->fast_train_enable = false;
- } else {
- dp->fast_train_enable =
- (spread & DP_NO_AUX_HANDSHAKE_LINK_TRAINING) ?
- true : false;
- }
- dev_dbg(dp->dev, "fast link training %s\n",
- dp->fast_train_enable ? "supported" : "unsupported");
-
dp->link_train.lt_state = FINISHED;
return 0;
@@ -996,6 +982,22 @@ static irqreturn_t analogix_dp_irq_thread(int irq, void *arg)
return IRQ_HANDLED;
}
+static int analogix_dp_fast_link_train_detection(struct analogix_dp_device *dp)
+{
+ int ret;
+ u8 spread;
+
+ ret = drm_dp_dpcd_readb(&dp->aux, DP_MAX_DOWNSPREAD, &spread);
+ if (ret != 1) {
+ dev_err(dp->dev, "failed to read downspread %d\n", ret);
+ return ret;
+ }
+ dp->fast_train_enable = !!(spread & DP_NO_AUX_HANDSHAKE_LINK_TRAINING);
+ dev_dbg(dp->dev, "fast link training %s\n",
+ dp->fast_train_enable ? "supported" : "unsupported");
+ return 0;
+}
+
static int analogix_dp_commit(struct analogix_dp_device *dp)
{
int ret;
@@ -1038,8 +1040,16 @@ static int analogix_dp_commit(struct analogix_dp_device *dp)
if (ret)
return ret;
- if (dp->psr_enable)
+ if (dp->psr_enable) {
ret = analogix_dp_enable_sink_psr(dp);
+ if (ret)
+ return ret;
+ }
+
+ /* Check whether panel supports fast training */
+ ret = analogix_dp_fast_link_train_detection(dp);
+ if (ret)
+ dp->psr_enable = false;
return ret;
}
--
2.16.1
^ permalink raw reply related
* [PATCH v5 22/36] drm/bridge: analogix_dp: Fix incorrect operations with register ANALOGIX_DP_FUNC_EN_1
From: Enric Balletbo i Serra @ 2018-03-09 22:23 UTC (permalink / raw)
To: architt, inki.dae, thierry.reding, hjc, seanpaul, airlied, tfiga,
heiko
Cc: dri-devel, dianders, a.hajda, ykk, kernel, m.szyprowski,
linux-samsung-soc, jy0922.shim, rydberg, krzk, linux-rockchip,
kgene, linux-input, orjan.eide, wxt, jeffy.chen, linux-arm-kernel,
mark.yao, wzz, hl, jingoohan1, sw0312.kim, linux-kernel,
kyungmin.park, Laurent.pinchart, kuankuan.y, hshi,
Enric Balletbo i Serra
In-Reply-To: <20180309222327.18689-1-enric.balletbo@collabora.com>
From: zain wang <wzz@rock-chips.com>
Register ANALOGIX_DP_FUNC_EN_1(offset 0x18), Rockchip is different to
Exynos:
on Exynos edp phy,
BIT 7 MASTER_VID_FUNC_EN_N
BIT 6 reserved
BIT 5 SLAVE_VID_FUNC_EN_N
on Rockchip edp phy,
BIT 7 reserved
BIT 6 RK_VID_CAP_FUNC_EN_N
BIT 5 RK_VID_FIFO_FUNC_EN_N
So, we should do some private operations to Rockchip.
Cc: Tomasz Figa <tfiga@chromium.org>
Signed-off-by: zain wang <wzz@rock-chips.com>
Signed-off-by: Sean Paul <seanpaul@chromium.org>
Signed-off-by: Thierry Escande <thierry.escande@collabora.com>
Reviewed-by: Andrzej Hajda <a.hajda@samsung.com>
Signed-off-by: Enric Balletbo i Serra <enric.balletbo@collabora.com>
Tested-by: Marek Szyprowski <m.szyprowski@samsung.com>
---
drivers/gpu/drm/bridge/analogix/analogix_dp_reg.c | 19 ++++++++++++++-----
drivers/gpu/drm/bridge/analogix/analogix_dp_reg.h | 2 ++
2 files changed, 16 insertions(+), 5 deletions(-)
diff --git a/drivers/gpu/drm/bridge/analogix/analogix_dp_reg.c b/drivers/gpu/drm/bridge/analogix/analogix_dp_reg.c
index 02ab1aaa9993..4eae206ec31b 100644
--- a/drivers/gpu/drm/bridge/analogix/analogix_dp_reg.c
+++ b/drivers/gpu/drm/bridge/analogix/analogix_dp_reg.c
@@ -126,9 +126,14 @@ void analogix_dp_reset(struct analogix_dp_device *dp)
analogix_dp_stop_video(dp);
analogix_dp_enable_video_mute(dp, 0);
- reg = MASTER_VID_FUNC_EN_N | SLAVE_VID_FUNC_EN_N |
- AUD_FIFO_FUNC_EN_N | AUD_FUNC_EN_N |
- HDCP_FUNC_EN_N | SW_FUNC_EN_N;
+ if (dp->plat_data && is_rockchip(dp->plat_data->dev_type))
+ reg = RK_VID_CAP_FUNC_EN_N | RK_VID_FIFO_FUNC_EN_N |
+ SW_FUNC_EN_N;
+ else
+ reg = MASTER_VID_FUNC_EN_N | SLAVE_VID_FUNC_EN_N |
+ AUD_FIFO_FUNC_EN_N | AUD_FUNC_EN_N |
+ HDCP_FUNC_EN_N | SW_FUNC_EN_N;
+
writel(reg, dp->reg_base + ANALOGIX_DP_FUNC_EN_1);
reg = SSC_FUNC_EN_N | AUX_FUNC_EN_N |
@@ -971,8 +976,12 @@ void analogix_dp_config_video_slave_mode(struct analogix_dp_device *dp)
u32 reg;
reg = readl(dp->reg_base + ANALOGIX_DP_FUNC_EN_1);
- reg &= ~(MASTER_VID_FUNC_EN_N | SLAVE_VID_FUNC_EN_N);
- reg |= MASTER_VID_FUNC_EN_N;
+ if (dp->plat_data && is_rockchip(dp->plat_data->dev_type)) {
+ reg &= ~(RK_VID_CAP_FUNC_EN_N | RK_VID_FIFO_FUNC_EN_N);
+ } else {
+ reg &= ~(MASTER_VID_FUNC_EN_N | SLAVE_VID_FUNC_EN_N);
+ reg |= MASTER_VID_FUNC_EN_N;
+ }
writel(reg, dp->reg_base + ANALOGIX_DP_FUNC_EN_1);
reg = readl(dp->reg_base + ANALOGIX_DP_VIDEO_CTL_10);
diff --git a/drivers/gpu/drm/bridge/analogix/analogix_dp_reg.h b/drivers/gpu/drm/bridge/analogix/analogix_dp_reg.h
index b633a4a5082a..0cf27c731727 100644
--- a/drivers/gpu/drm/bridge/analogix/analogix_dp_reg.h
+++ b/drivers/gpu/drm/bridge/analogix/analogix_dp_reg.h
@@ -127,7 +127,9 @@
/* ANALOGIX_DP_FUNC_EN_1 */
#define MASTER_VID_FUNC_EN_N (0x1 << 7)
+#define RK_VID_CAP_FUNC_EN_N (0x1 << 6)
#define SLAVE_VID_FUNC_EN_N (0x1 << 5)
+#define RK_VID_FIFO_FUNC_EN_N (0x1 << 5)
#define AUD_FIFO_FUNC_EN_N (0x1 << 4)
#define AUD_FUNC_EN_N (0x1 << 3)
#define HDCP_FUNC_EN_N (0x1 << 2)
--
2.16.1
^ permalink raw reply related
* [PATCH v5 21/36] drm/bridge: analogix_dp: Fix timeout of video streamclk config
From: Enric Balletbo i Serra @ 2018-03-09 22:23 UTC (permalink / raw)
To: architt, inki.dae, thierry.reding, hjc, seanpaul, airlied, tfiga,
heiko
Cc: dri-devel, dianders, a.hajda, ykk, kernel, m.szyprowski,
linux-samsung-soc, jy0922.shim, rydberg, krzk, linux-rockchip,
kgene, linux-input, orjan.eide, wxt, jeffy.chen, linux-arm-kernel,
mark.yao, wzz, hl, jingoohan1, sw0312.kim, linux-kernel,
kyungmin.park, Laurent.pinchart, kuankuan.y, hshi,
Enric Balletbo i Serra
In-Reply-To: <20180309222327.18689-1-enric.balletbo@collabora.com>
From: zain wang <wzz@rock-chips.com>
The STRM_VALID bit in register ANALOGIX_DP_SYS_CTL_3 may be unstable,
so we may hit the error log "Timeout of video streamclk ok" since
checked this unstable bit.
In fact, we can go continue and the streamclk is ok if we wait enough time,
it does no effect on display.
Let's change this error to warn.
Cc: Douglas Anderson <dianders@chromium.org>
Signed-off-by: zain wang <wzz@rock-chips.com>
Signed-off-by: Sean Paul <seanpaul@chromium.org>
Signed-off-by: Thierry Escande <thierry.escande@collabora.com>
Reviewed-by: Andrzej Hajda <a.hajda@samsung.com>
Signed-off-by: Enric Balletbo i Serra <enric.balletbo@collabora.com>
Tested-by: Marek Szyprowski <m.szyprowski@samsung.com>
---
drivers/gpu/drm/bridge/analogix/analogix_dp_core.c | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
index 1f1cb624414d..d76e1652b1fd 100644
--- a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
+++ b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
@@ -921,8 +921,9 @@ static int analogix_dp_config_video(struct analogix_dp_device *dp)
done_count = 0;
}
if (timeout_loop > DP_TIMEOUT_LOOP_COUNT) {
- dev_err(dp->dev, "Timeout of video streamclk ok\n");
- return -ETIMEDOUT;
+ dev_warn(dp->dev,
+ "Ignoring timeout of video streamclk ok\n");
+ break;
}
usleep_range(1000, 1001);
--
2.16.1
^ permalink raw reply related
* [PATCH v5 20/36] drm/bridge: analogix_dp: Don't use ANALOGIX_DP_PLL_CTL to control pll
From: Enric Balletbo i Serra @ 2018-03-09 22:23 UTC (permalink / raw)
To: architt, inki.dae, thierry.reding, hjc, seanpaul, airlied, tfiga,
heiko
Cc: dri-devel, dianders, a.hajda, ykk, kernel, m.szyprowski,
linux-samsung-soc, jy0922.shim, rydberg, krzk, linux-rockchip,
kgene, linux-input, orjan.eide, wxt, jeffy.chen, linux-arm-kernel,
mark.yao, wzz, hl, jingoohan1, sw0312.kim, linux-kernel,
kyungmin.park, Laurent.pinchart, kuankuan.y, hshi,
Enric Balletbo i Serra
In-Reply-To: <20180309222327.18689-1-enric.balletbo@collabora.com>
From: zain wang <wzz@rock-chips.com>
There is no register named ANALOGIX_DP_PLL_CTL in Rockchip edp phy reg
list. We should use BIT_4 in ANALOGIX_DP_PD to control the pll power
instead of ANALOGIX_DP_PLL_CTL.
Cc: Douglas Anderson <dianders@chromium.org>
Signed-off-by: zain wang <wzz@rock-chips.com>
Signed-off-by: Sean Paul <seanpaul@chromium.org>
Signed-off-by: Thierry Escande <thierry.escande@collabora.com>
Reviewed-by: Andrzej Hajda <a.hajda@samsung.com>
Signed-off-by: Enric Balletbo i Serra <enric.balletbo@collabora.com>
Tested-by: Marek Szyprowski <m.szyprowski@samsung.com>
---
drivers/gpu/drm/bridge/analogix/analogix_dp_reg.c | 20 ++++++++++++--------
1 file changed, 12 insertions(+), 8 deletions(-)
diff --git a/drivers/gpu/drm/bridge/analogix/analogix_dp_reg.c b/drivers/gpu/drm/bridge/analogix/analogix_dp_reg.c
index 7b7fd227e1f9..02ab1aaa9993 100644
--- a/drivers/gpu/drm/bridge/analogix/analogix_dp_reg.c
+++ b/drivers/gpu/drm/bridge/analogix/analogix_dp_reg.c
@@ -230,16 +230,20 @@ enum pll_status analogix_dp_get_pll_lock_status(struct analogix_dp_device *dp)
void analogix_dp_set_pll_power_down(struct analogix_dp_device *dp, bool enable)
{
u32 reg;
+ u32 mask = DP_PLL_PD;
+ u32 pd_addr = ANALOGIX_DP_PLL_CTL;
- if (enable) {
- reg = readl(dp->reg_base + ANALOGIX_DP_PLL_CTL);
- reg |= DP_PLL_PD;
- writel(reg, dp->reg_base + ANALOGIX_DP_PLL_CTL);
- } else {
- reg = readl(dp->reg_base + ANALOGIX_DP_PLL_CTL);
- reg &= ~DP_PLL_PD;
- writel(reg, dp->reg_base + ANALOGIX_DP_PLL_CTL);
+ if (dp->plat_data && is_rockchip(dp->plat_data->dev_type)) {
+ pd_addr = ANALOGIX_DP_PD;
+ mask = RK_PLL_PD;
}
+
+ reg = readl(dp->reg_base + pd_addr);
+ if (enable)
+ reg |= mask;
+ else
+ reg &= ~mask;
+ writel(reg, dp->reg_base + pd_addr);
}
void analogix_dp_set_analog_power_down(struct analogix_dp_device *dp,
--
2.16.1
^ permalink raw reply related
* [PATCH v5 19/36] drm/rockchip: Restore psr->state when enable/disable psr failed
From: Enric Balletbo i Serra @ 2018-03-09 22:23 UTC (permalink / raw)
To: architt, inki.dae, thierry.reding, hjc, seanpaul, airlied, tfiga,
heiko
Cc: dri-devel, dianders, a.hajda, ykk, kernel, m.szyprowski,
linux-samsung-soc, jy0922.shim, rydberg, krzk, linux-rockchip,
kgene, linux-input, orjan.eide, wxt, jeffy.chen, linux-arm-kernel,
mark.yao, wzz, hl, jingoohan1, sw0312.kim, linux-kernel,
kyungmin.park, Laurent.pinchart, kuankuan.y, hshi,
Enric Balletbo i Serra
In-Reply-To: <20180309222327.18689-1-enric.balletbo@collabora.com>
From: zain wang <wzz@rock-chips.com>
If we failed disable psr, it would hang the display until next psr
cycle coming. So we should restore psr->state when it failed.
Cc: Tomasz Figa <tfiga@chromium.org>
Signed-off-by: zain wang <wzz@rock-chips.com>
Signed-off-by: Douglas Anderson <dianders@chromium.org>
Signed-off-by: Sean Paul <seanpaul@chromium.org>
Signed-off-by: Thierry Escande <thierry.escande@collabora.com>
Signed-off-by: Enric Balletbo i Serra <enric.balletbo@collabora.com>
Tested-by: Marek Szyprowski <m.szyprowski@samsung.com>
---
drivers/gpu/drm/bridge/analogix/analogix_dp_core.c | 4 +++-
drivers/gpu/drm/rockchip/analogix_dp-rockchip.c | 10 +++++-----
drivers/gpu/drm/rockchip/rockchip_drm_psr.c | 20 +++++++++++++-------
drivers/gpu/drm/rockchip/rockchip_drm_psr.h | 2 +-
4 files changed, 22 insertions(+), 14 deletions(-)
diff --git a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
index be6eddd0d0a7..1f1cb624414d 100644
--- a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
+++ b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
@@ -153,8 +153,10 @@ int analogix_dp_disable_psr(struct analogix_dp_device *dp)
psr_vsc.DB1 = 0;
ret = drm_dp_dpcd_writeb(&dp->aux, DP_SET_POWER, DP_SET_POWER_D0);
- if (ret != 1)
+ if (ret != 1) {
dev_err(dp->dev, "Failed to set DP Power0 %d\n", ret);
+ return ret;
+ }
return analogix_dp_send_psr_spd(dp, &psr_vsc, false);
}
diff --git a/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c b/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c
index 3e8bf79bea58..8c884f9ce713 100644
--- a/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c
+++ b/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c
@@ -77,13 +77,13 @@ struct rockchip_dp_device {
struct analogix_dp_plat_data plat_data;
};
-static void analogix_dp_psr_set(struct drm_encoder *encoder, bool enabled)
+static int analogix_dp_psr_set(struct drm_encoder *encoder, bool enabled)
{
struct rockchip_dp_device *dp = to_dp(encoder);
int ret;
if (!analogix_dp_psr_enabled(dp->adp))
- return;
+ return 0;
DRM_DEV_DEBUG(dp->dev, "%s PSR...\n", enabled ? "Entry" : "Exit");
@@ -91,13 +91,13 @@ static void analogix_dp_psr_set(struct drm_encoder *encoder, bool enabled)
PSR_WAIT_LINE_FLAG_TIMEOUT_MS);
if (ret) {
DRM_DEV_ERROR(dp->dev, "line flag interrupt did not arrive\n");
- return;
+ return -ETIMEDOUT;
}
if (enabled)
- analogix_dp_enable_psr(dp->adp);
+ return analogix_dp_enable_psr(dp->adp);
else
- analogix_dp_disable_psr(dp->adp);
+ return analogix_dp_disable_psr(dp->adp);
}
static int rockchip_dp_pre_init(struct rockchip_dp_device *dp)
diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_psr.c b/drivers/gpu/drm/rockchip/rockchip_drm_psr.c
index b339ca943139..9376f4396b6b 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_psr.c
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_psr.c
@@ -36,7 +36,7 @@ struct psr_drv {
struct delayed_work flush_work;
- void (*set)(struct drm_encoder *encoder, bool enable);
+ int (*set)(struct drm_encoder *encoder, bool enable);
};
static struct psr_drv *find_psr_by_crtc(struct drm_crtc *crtc)
@@ -93,19 +93,25 @@ static void psr_set_state_locked(struct psr_drv *psr, enum psr_state state)
return;
}
- psr->state = state;
-
/* Actually commit the state change to hardware */
- switch (psr->state) {
+ switch (state) {
case PSR_ENABLE:
- psr->set(psr->encoder, true);
+ if (psr->set(psr->encoder, true))
+ return;
break;
case PSR_DISABLE:
case PSR_FLUSH:
- psr->set(psr->encoder, false);
+ if (psr->set(psr->encoder, false))
+ return;
break;
+
+ default:
+ pr_err("%s: Unknown state %d\n", __func__, state);
+ return;
}
+
+ psr->state = state;
}
static void psr_set_state(struct psr_drv *psr, enum psr_state state)
@@ -229,7 +235,7 @@ EXPORT_SYMBOL(rockchip_drm_psr_flush_all);
* Zero on success, negative errno on failure.
*/
int rockchip_drm_psr_register(struct drm_encoder *encoder,
- void (*psr_set)(struct drm_encoder *, bool enable))
+ int (*psr_set)(struct drm_encoder *, bool enable))
{
struct rockchip_drm_private *drm_drv = encoder->dev->dev_private;
struct psr_drv *psr;
diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_psr.h b/drivers/gpu/drm/rockchip/rockchip_drm_psr.h
index b1ea0155e57c..06537ee27565 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_psr.h
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_psr.h
@@ -22,7 +22,7 @@ int rockchip_drm_psr_activate(struct drm_encoder *encoder);
int rockchip_drm_psr_deactivate(struct drm_encoder *encoder);
int rockchip_drm_psr_register(struct drm_encoder *encoder,
- void (*psr_set)(struct drm_encoder *, bool enable));
+ int (*psr_set)(struct drm_encoder *, bool enable));
void rockchip_drm_psr_unregister(struct drm_encoder *encoder);
#endif /* __ROCKCHIP_DRM_PSR__ */
--
2.16.1
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox