devicetree.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v3 0/5] Add new panel driver Samsung S6E88A0-AMS427AP24
@ 2024-10-24  3:18 Jakob Hauser
  2024-10-24  3:18 ` [PATCH v3 1/5] dt-bindings: display: panel: Move flip properties to panel-common Jakob Hauser
                   ` (4 more replies)
  0 siblings, 5 replies; 14+ messages in thread
From: Jakob Hauser @ 2024-10-24  3:18 UTC (permalink / raw)
  To: Neil Armstrong, Jessica Zhang, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley
  Cc: Thierry Reding, Laurent Pinchart, Andrzej Hajda, dri-devel,
	devicetree, linux-kernel, ~postmarketos/upstreaming, Jakob Hauser

The patchset adds a new driver for Samsung AMS427AP24 panel with S6E88A0
controller. Patches are based on current branch drm-misc-next.

Changes in v3:
 - Patch 2: Dropped the second "bindings" in the commit subject.
 - Patch 2: Applied 4 spaces indentation in the example.
 - Patch 3: Made struct s6e88a0_ams427ap24_supplies[] "static".
 - Patch 3: Removed the "panel->prepared" parts from functions
   s6e88a0_ams427ap24_prepare() and s6e88a0_ams427ap24_unprepare().
 - Patch 5: Dissolved function s6e88a0_ams427ap24_parse_dt() and placed
   the parsing in the probe function. Changed the parsing from
   of_property_read_bool() to device_property_read_bool().

v1: https://lore.kernel.org/dri-devel/cover.1728582727.git.jahau@rocketmail.com/T/#t
v2: https://lore.kernel.org/dri-devel/cover.1729630039.git.jahau@rocketmail.com/T/#t

Jakob Hauser (5):
  dt-bindings: display: panel: Move flip properties to panel-common
  dt-bindings: display: panel: Add Samsung S6E88A0-AMS427AP24
  drm/panel: samsung-s6e88a0-ams427ap24: Add initial driver
  drm/panel: samsung-s6e88a0-ams427ap24: Add brightness control
  drm/panel: samsung-s6e88a0-ams427ap24: Add flip option

 .../bindings/display/panel/panel-common.yaml  |   8 +
 .../panel/samsung,s6e88a0-ams427ap24.yaml     |  65 ++
 .../display/panel/samsung,s6e8aa0.yaml        |  10 +-
 drivers/gpu/drm/panel/Kconfig                 |  10 +
 drivers/gpu/drm/panel/Makefile                |   1 +
 .../panel/panel-samsung-s6e88a0-ams427ap24.c  | 754 ++++++++++++++++++
 6 files changed, 840 insertions(+), 8 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/display/panel/samsung,s6e88a0-ams427ap24.yaml
 create mode 100644 drivers/gpu/drm/panel/panel-samsung-s6e88a0-ams427ap24.c

-- 
2.39.5


^ permalink raw reply	[flat|nested] 14+ messages in thread

* [PATCH v3 1/5] dt-bindings: display: panel: Move flip properties to panel-common
  2024-10-24  3:18 [PATCH v3 0/5] Add new panel driver Samsung S6E88A0-AMS427AP24 Jakob Hauser
@ 2024-10-24  3:18 ` Jakob Hauser
  2024-10-25 16:25   ` Linus Walleij
  2024-10-24  3:18 ` [PATCH v3 2/5] dt-bindings: display: panel: Add Samsung S6E88A0-AMS427AP24 Jakob Hauser
                   ` (3 subsequent siblings)
  4 siblings, 1 reply; 14+ messages in thread
From: Jakob Hauser @ 2024-10-24  3:18 UTC (permalink / raw)
  To: Neil Armstrong, Jessica Zhang, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley
  Cc: Thierry Reding, Laurent Pinchart, Andrzej Hajda, dri-devel,
	devicetree, linux-kernel, ~postmarketos/upstreaming, Jakob Hauser,
	Krzysztof Kozlowski

The flip properties were used by "samsung,s6e8aa0.yaml" only so far. By
introducing "samsung,s6e88a0-ams427ap24.yaml" they become more common.

Signed-off-by: Jakob Hauser <jahau@rocketmail.com>
Reviewed-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
---
Patch is based on current branch drm-misc-next.
---
 .../bindings/display/panel/panel-common.yaml           |  8 ++++++++
 .../bindings/display/panel/samsung,s6e8aa0.yaml        | 10 ++--------
 2 files changed, 10 insertions(+), 8 deletions(-)

diff --git a/Documentation/devicetree/bindings/display/panel/panel-common.yaml b/Documentation/devicetree/bindings/display/panel/panel-common.yaml
index 0a57a31f4f3d..087415753d60 100644
--- a/Documentation/devicetree/bindings/display/panel/panel-common.yaml
+++ b/Documentation/devicetree/bindings/display/panel/panel-common.yaml
@@ -51,6 +51,14 @@ properties:
     $ref: /schemas/types.yaml#/definitions/uint32
     enum: [0, 90, 180, 270]
 
+  flip-horizontal:
+    description: boolean to flip image horizontally
+    type: boolean
+
+  flip-vertical:
+    description: boolean to flip image vertically
+    type: boolean
+
   # Display Timings
   panel-timing:
     description:
diff --git a/Documentation/devicetree/bindings/display/panel/samsung,s6e8aa0.yaml b/Documentation/devicetree/bindings/display/panel/samsung,s6e8aa0.yaml
index 4601fa460680..19c8cc83db97 100644
--- a/Documentation/devicetree/bindings/display/panel/samsung,s6e8aa0.yaml
+++ b/Documentation/devicetree/bindings/display/panel/samsung,s6e8aa0.yaml
@@ -21,6 +21,8 @@ properties:
 
   reset-gpios: true
   display-timings: true
+  flip-horizontal: true
+  flip-vertical: true
 
   vdd3-supply:
     description: core voltage supply
@@ -46,14 +48,6 @@ properties:
   panel-height-mm:
     description: physical panel height [mm]
 
-  flip-horizontal:
-    description: boolean to flip image horizontally
-    type: boolean
-
-  flip-vertical:
-    description: boolean to flip image vertically
-    type: boolean
-
 required:
   - compatible
   - reg
-- 
2.39.5


^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH v3 2/5] dt-bindings: display: panel: Add Samsung S6E88A0-AMS427AP24
  2024-10-24  3:18 [PATCH v3 0/5] Add new panel driver Samsung S6E88A0-AMS427AP24 Jakob Hauser
  2024-10-24  3:18 ` [PATCH v3 1/5] dt-bindings: display: panel: Move flip properties to panel-common Jakob Hauser
@ 2024-10-24  3:18 ` Jakob Hauser
  2024-10-25 16:24   ` Linus Walleij
  2024-10-24  3:18 ` [PATCH v3 3/5] drm/panel: samsung-s6e88a0-ams427ap24: Add initial driver Jakob Hauser
                   ` (2 subsequent siblings)
  4 siblings, 1 reply; 14+ messages in thread
From: Jakob Hauser @ 2024-10-24  3:18 UTC (permalink / raw)
  To: Neil Armstrong, Jessica Zhang, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley
  Cc: Thierry Reding, Laurent Pinchart, Andrzej Hajda, dri-devel,
	devicetree, linux-kernel, ~postmarketos/upstreaming, Jakob Hauser,
	Krzysztof Kozlowski

Add bindings for Samsung AMS427AP24 panel with S6E88A0 controller.

Signed-off-by: Jakob Hauser <jahau@rocketmail.com>
Reviewed-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
---
Patch is based on current branch drm-misc-next.

Changes in v3:
 - Dropped the second "bindings" in the commit subject.
 - Applied 4 spaces indentation in the example.
---
 .../panel/samsung,s6e88a0-ams427ap24.yaml     | 65 +++++++++++++++++++
 1 file changed, 65 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/display/panel/samsung,s6e88a0-ams427ap24.yaml

diff --git a/Documentation/devicetree/bindings/display/panel/samsung,s6e88a0-ams427ap24.yaml b/Documentation/devicetree/bindings/display/panel/samsung,s6e88a0-ams427ap24.yaml
new file mode 100644
index 000000000000..db284ba5be20
--- /dev/null
+++ b/Documentation/devicetree/bindings/display/panel/samsung,s6e88a0-ams427ap24.yaml
@@ -0,0 +1,65 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/display/panel/samsung,s6e88a0-ams427ap24.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Samsung AMS427AP24 panel with S6E88A0 controller
+
+maintainers:
+  - Jakob Hauser <jahau@rocketmail.com>
+
+allOf:
+  - $ref: panel-common.yaml#
+
+properties:
+  compatible:
+    const: samsung,s6e88a0-ams427ap24
+
+  reg:
+    maxItems: 1
+
+  port: true
+  reset-gpios: true
+  flip-horizontal: true
+
+  vdd3-supply:
+    description: core voltage supply
+
+  vci-supply:
+    description: voltage supply for analog circuits
+
+required:
+  - compatible
+  - reg
+  - port
+  - reset-gpios
+  - vdd3-supply
+  - vci-supply
+
+additionalProperties: false
+
+examples:
+  - |
+    #include <dt-bindings/gpio/gpio.h>
+
+    dsi {
+        #address-cells = <1>;
+        #size-cells = <0>;
+
+        panel@0 {
+            compatible = "samsung,s6e88a0-ams427ap24";
+            reg = <0>;
+
+            vdd3-supply = <&pm8916_l17>;
+            vci-supply = <&pm8916_l6>;
+            reset-gpios = <&tlmm 25 GPIO_ACTIVE_LOW>;
+            flip-horizontal;
+
+            port {
+                panel_in: endpoint {
+                    remote-endpoint = <&mdss_dsi0_out>;
+                };
+            };
+        };
+    };
-- 
2.39.5


^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH v3 3/5] drm/panel: samsung-s6e88a0-ams427ap24: Add initial driver
  2024-10-24  3:18 [PATCH v3 0/5] Add new panel driver Samsung S6E88A0-AMS427AP24 Jakob Hauser
  2024-10-24  3:18 ` [PATCH v3 1/5] dt-bindings: display: panel: Move flip properties to panel-common Jakob Hauser
  2024-10-24  3:18 ` [PATCH v3 2/5] dt-bindings: display: panel: Add Samsung S6E88A0-AMS427AP24 Jakob Hauser
@ 2024-10-24  3:18 ` Jakob Hauser
  2024-10-25 16:36   ` Linus Walleij
  2024-10-24  3:18 ` [PATCH v3 4/5] drm/panel: samsung-s6e88a0-ams427ap24: Add brightness control Jakob Hauser
  2024-10-24  3:18 ` [PATCH v3 5/5] drm/panel: samsung-s6e88a0-ams427ap24: Add flip option Jakob Hauser
  4 siblings, 1 reply; 14+ messages in thread
From: Jakob Hauser @ 2024-10-24  3:18 UTC (permalink / raw)
  To: Neil Armstrong, Jessica Zhang, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley
  Cc: Thierry Reding, Laurent Pinchart, Andrzej Hajda, dri-devel,
	devicetree, linux-kernel, ~postmarketos/upstreaming, Jakob Hauser

This initial part of the panel driver was mostly generated by the
"linux-mdss-dsi-panel-driver-generator" tool [1], reading downstream
Android kernel file "dsi_panel_S6E88A0_AMS427AP24_qhd_octa_video.dtsi" [2].

On top of the generic output of the tool, there were a couple of changes
applied:
- Added mipi_dsi_dcs_set_display_on() to function s6e88a0_ams427ap24_on(),
  otherwise the display does not show up.
- In functions s6e88a0_ams427ap24_on() and s6e88a0_ams427ap24_off()
  changed DSI commands to multi context and used "accum_err" returns.
- In functions s6e88a0_ams427ap24_on() and s6e88a0_ams427ap24_off() replaced
  msleep() by mipi_dsi_msleep().
- The function s6e88a0_ams427ap24_get_modes() was changed to make use of
  drm_connector_helper_get_modes_fixed(). This also required to include
  drm/drm_probe_helper.h.
- In function s6e88a0_ams427ap24_probe() registring the regulators was changed
  to devm_regulator_bulk_get_const(). This required to change supplies in struct
  s6e88a0_ams427ap24 to a pointer.
- Removed bool "prepared" from struct s6e88a0_ams427ap24 and according parts in
  functions s6e88a0_ams427ap24_prepare() and s6e88a0_ams427ap24_unprepare().

[1] https://github.com/msm8916-mainline/linux-mdss-dsi-panel-driver-generator
[2] https://github.com/msm8916-mainline/linux-downstream/blob/GT-I9195I/drivers/video/msm/mdss/samsung/S6E88A0_AMS427AP24/dsi_panel_S6E88A0_AMS427AP24_qhd_octa_video.dtsi

Signed-off-by: Jakob Hauser <jahau@rocketmail.com>
---
Changes in v3:
 - Made struct s6e88a0_ams427ap24_supplies[] "static".
 - Removed the "panel->prepared" parts from functions
   s6e88a0_ams427ap24_prepare() and s6e88a0_ams427ap24_unprepare().
---
 drivers/gpu/drm/panel/Kconfig                 |   9 +
 drivers/gpu/drm/panel/Makefile                |   1 +
 .../panel/panel-samsung-s6e88a0-ams427ap24.c  | 252 ++++++++++++++++++
 3 files changed, 262 insertions(+)
 create mode 100644 drivers/gpu/drm/panel/panel-samsung-s6e88a0-ams427ap24.c

diff --git a/drivers/gpu/drm/panel/Kconfig b/drivers/gpu/drm/panel/Kconfig
index bce4cb64184a..f8adc38447fb 100644
--- a/drivers/gpu/drm/panel/Kconfig
+++ b/drivers/gpu/drm/panel/Kconfig
@@ -632,6 +632,15 @@ config DRM_PANEL_SAMSUNG_AMS639RQ08
 	  Say Y or M here if you want to enable support for the
 	  Samsung AMS639RQ08 FHD Plus (2340x1080@60Hz) CMD mode panel.
 
+config DRM_PANEL_SAMSUNG_S6E88A0_AMS427AP24
+	tristate "Samsung AMS427AP24 panel with S6E88A0 controller"
+	depends on GPIOLIB && OF && REGULATOR
+	depends on DRM_MIPI_DSI
+	help
+	  Say Y here if you want to enable support for Samsung AMS427AP24 panel
+	  with S6E88A0 controller (found in Samsung Galaxy S4 Mini Value Edition
+	  GT-I9195I). To compile this driver as a module, choose M here.
+
 config DRM_PANEL_SAMSUNG_S6E88A0_AMS452EF01
 	tristate "Samsung AMS452EF01 panel with S6E88A0 DSI video mode controller"
 	depends on OF
diff --git a/drivers/gpu/drm/panel/Makefile b/drivers/gpu/drm/panel/Makefile
index 4db02c2411ae..7dcf72646cac 100644
--- a/drivers/gpu/drm/panel/Makefile
+++ b/drivers/gpu/drm/panel/Makefile
@@ -77,6 +77,7 @@ obj-$(CONFIG_DRM_PANEL_SAMSUNG_S6E63J0X03) += panel-samsung-s6e63j0x03.o
 obj-$(CONFIG_DRM_PANEL_SAMSUNG_S6E63M0) += panel-samsung-s6e63m0.o
 obj-$(CONFIG_DRM_PANEL_SAMSUNG_S6E63M0_SPI) += panel-samsung-s6e63m0-spi.o
 obj-$(CONFIG_DRM_PANEL_SAMSUNG_S6E63M0_DSI) += panel-samsung-s6e63m0-dsi.o
+obj-$(CONFIG_DRM_PANEL_SAMSUNG_S6E88A0_AMS427AP24) += panel-samsung-s6e88a0-ams427ap24.o
 obj-$(CONFIG_DRM_PANEL_SAMSUNG_S6E88A0_AMS452EF01) += panel-samsung-s6e88a0-ams452ef01.o
 obj-$(CONFIG_DRM_PANEL_SAMSUNG_S6E8AA0) += panel-samsung-s6e8aa0.o
 obj-$(CONFIG_DRM_PANEL_SAMSUNG_SOFEF00) += panel-samsung-sofef00.o
diff --git a/drivers/gpu/drm/panel/panel-samsung-s6e88a0-ams427ap24.c b/drivers/gpu/drm/panel/panel-samsung-s6e88a0-ams427ap24.c
new file mode 100644
index 000000000000..7435e0fcb4f5
--- /dev/null
+++ b/drivers/gpu/drm/panel/panel-samsung-s6e88a0-ams427ap24.c
@@ -0,0 +1,252 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Samsung AMS427AP24 panel with S6E88A0 controller
+ * Copyright (c) 2024 Jakob Hauser <jahau@rocketmail.com>
+ */
+
+#include <linux/delay.h>
+#include <linux/gpio/consumer.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/regulator/consumer.h>
+
+#include <video/mipi_display.h>
+
+#include <drm/drm_mipi_dsi.h>
+#include <drm/drm_modes.h>
+#include <drm/drm_panel.h>
+#include <drm/drm_probe_helper.h>
+
+struct s6e88a0_ams427ap24 {
+	struct drm_panel panel;
+	struct mipi_dsi_device *dsi;
+	struct regulator_bulk_data *supplies;
+	struct gpio_desc *reset_gpio;
+};
+
+static const struct regulator_bulk_data s6e88a0_ams427ap24_supplies[] = {
+	{ .supply = "vdd3" },
+	{ .supply = "vci" },
+};
+
+static inline
+struct s6e88a0_ams427ap24 *to_s6e88a0_ams427ap24(struct drm_panel *panel)
+{
+	return container_of(panel, struct s6e88a0_ams427ap24, panel);
+}
+
+static void s6e88a0_ams427ap24_reset(struct s6e88a0_ams427ap24 *ctx)
+{
+	gpiod_set_value_cansleep(ctx->reset_gpio, 0);
+	usleep_range(5000, 6000);
+	gpiod_set_value_cansleep(ctx->reset_gpio, 1);
+	usleep_range(1000, 2000);
+	gpiod_set_value_cansleep(ctx->reset_gpio, 0);
+	usleep_range(18000, 19000);
+}
+
+static int s6e88a0_ams427ap24_on(struct s6e88a0_ams427ap24 *ctx)
+{
+	struct mipi_dsi_device *dsi = ctx->dsi;
+	struct mipi_dsi_multi_context dsi_ctx = { .dsi = dsi };
+
+	dsi->mode_flags |= MIPI_DSI_MODE_LPM;
+
+	mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xf0, 0x5a, 0x5a);
+	mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xfc, 0x5a, 0x5a);
+	mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xb0, 0x11);
+	mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xfd, 0x11);
+	mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xb0, 0x13);
+	mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xfd, 0x18);
+	mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xb0, 0x02);
+	mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xb8, 0x30);
+
+	mipi_dsi_dcs_exit_sleep_mode_multi(&dsi_ctx);
+	mipi_dsi_msleep(&dsi_ctx, 20);
+
+	mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xf1, 0x5a, 0x5a);
+	mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xcc, 0x4c);
+	mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xf2, 0x03, 0x0d);
+	mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xf1, 0xa5, 0xa5);
+	mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xca,
+				     0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x80,
+				     0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+				     0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+				     0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+				     0x80, 0x80, 0x00, 0x00, 0x00);
+	mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xb2,
+				     0x40, 0x08, 0x20, 0x00, 0x08);
+	mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xb6, 0x28, 0x0b);
+	mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xf7, 0x03);
+	mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x55, 0x00);
+	mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xf0, 0xa5, 0xa5);
+	mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xfc, 0xa5, 0xa5);
+
+	mipi_dsi_dcs_set_display_on_multi(&dsi_ctx);
+
+	return dsi_ctx.accum_err;
+}
+
+static int s6e88a0_ams427ap24_off(struct s6e88a0_ams427ap24 *ctx)
+{
+	struct mipi_dsi_device *dsi = ctx->dsi;
+	struct mipi_dsi_multi_context dsi_ctx = { .dsi = dsi };
+
+	dsi->mode_flags &= ~MIPI_DSI_MODE_LPM;
+
+	mipi_dsi_dcs_set_display_off_multi(&dsi_ctx);
+	mipi_dsi_dcs_enter_sleep_mode_multi(&dsi_ctx);
+	mipi_dsi_msleep(&dsi_ctx, 120);
+
+	return dsi_ctx.accum_err;
+}
+
+static int s6e88a0_ams427ap24_prepare(struct drm_panel *panel)
+{
+	struct s6e88a0_ams427ap24 *ctx = to_s6e88a0_ams427ap24(panel);
+	struct device *dev = &ctx->dsi->dev;
+	int ret;
+
+	ret = regulator_bulk_enable(ARRAY_SIZE(s6e88a0_ams427ap24_supplies),
+				    ctx->supplies);
+	if (ret < 0) {
+		dev_err(dev, "Failed to enable regulators: %d\n", ret);
+		return ret;
+	}
+
+	s6e88a0_ams427ap24_reset(ctx);
+
+	ret = s6e88a0_ams427ap24_on(ctx);
+	if (ret < 0) {
+		dev_err(dev, "Failed to initialize panel: %d\n", ret);
+		gpiod_set_value_cansleep(ctx->reset_gpio, 1);
+		regulator_bulk_disable(ARRAY_SIZE(s6e88a0_ams427ap24_supplies),
+				       ctx->supplies);
+		return ret;
+	}
+
+	return 0;
+}
+
+static int s6e88a0_ams427ap24_unprepare(struct drm_panel *panel)
+{
+	struct s6e88a0_ams427ap24 *ctx = to_s6e88a0_ams427ap24(panel);
+	struct device *dev = &ctx->dsi->dev;
+	int ret;
+
+	ret = s6e88a0_ams427ap24_off(ctx);
+	if (ret < 0)
+		dev_err(dev, "Failed to un-initialize panel: %d\n", ret);
+
+	gpiod_set_value_cansleep(ctx->reset_gpio, 1);
+	regulator_bulk_disable(ARRAY_SIZE(s6e88a0_ams427ap24_supplies),
+			       ctx->supplies);
+
+	return 0;
+}
+
+static const struct drm_display_mode s6e88a0_ams427ap24_mode = {
+	.clock = (540 + 94 + 4 + 18) * (960 + 12 + 1 + 3) * 60 / 1000,
+	.hdisplay = 540,
+	.hsync_start = 540 + 94,
+	.hsync_end = 540 + 94 + 4,
+	.htotal = 540 + 94 + 4 + 18,
+	.vdisplay = 960,
+	.vsync_start = 960 + 12,
+	.vsync_end = 960 + 12 + 1,
+	.vtotal = 960 + 12 + 1 + 3,
+	.width_mm = 55,
+	.height_mm = 95,
+	.type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED,
+};
+
+static int s6e88a0_ams427ap24_get_modes(struct drm_panel *panel,
+					struct drm_connector *connector)
+{
+	return drm_connector_helper_get_modes_fixed(connector,
+						    &s6e88a0_ams427ap24_mode);
+}
+
+static const struct drm_panel_funcs s6e88a0_ams427ap24_panel_funcs = {
+	.prepare = s6e88a0_ams427ap24_prepare,
+	.unprepare = s6e88a0_ams427ap24_unprepare,
+	.get_modes = s6e88a0_ams427ap24_get_modes,
+};
+
+static int s6e88a0_ams427ap24_probe(struct mipi_dsi_device *dsi)
+{
+	struct device *dev = &dsi->dev;
+	struct s6e88a0_ams427ap24 *ctx;
+	int ret;
+
+	ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL);
+	if (!ctx)
+		return -ENOMEM;
+
+	ret = devm_regulator_bulk_get_const(dev,
+				      ARRAY_SIZE(s6e88a0_ams427ap24_supplies),
+				      s6e88a0_ams427ap24_supplies,
+				      &ctx->supplies);
+	if (ret < 0)
+		return ret;
+
+	ctx->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_HIGH);
+	if (IS_ERR(ctx->reset_gpio))
+		return dev_err_probe(dev, PTR_ERR(ctx->reset_gpio),
+				     "Failed to get reset-gpios\n");
+
+	ctx->dsi = dsi;
+	mipi_dsi_set_drvdata(dsi, ctx);
+
+	dsi->lanes = 2;
+	dsi->format = MIPI_DSI_FMT_RGB888;
+	dsi->mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_BURST |
+			  MIPI_DSI_MODE_NO_EOT_PACKET;
+
+	drm_panel_init(&ctx->panel, dev, &s6e88a0_ams427ap24_panel_funcs,
+		       DRM_MODE_CONNECTOR_DSI);
+	ctx->panel.prepare_prev_first = true;
+
+	drm_panel_add(&ctx->panel);
+
+	ret = mipi_dsi_attach(dsi);
+	if (ret < 0) {
+		dev_err(dev, "Failed to attach to DSI host: %d\n", ret);
+		drm_panel_remove(&ctx->panel);
+		return ret;
+	}
+
+	return 0;
+}
+
+static void s6e88a0_ams427ap24_remove(struct mipi_dsi_device *dsi)
+{
+	struct s6e88a0_ams427ap24 *ctx = mipi_dsi_get_drvdata(dsi);
+	int ret;
+
+	ret = mipi_dsi_detach(dsi);
+	if (ret < 0)
+		dev_err(&dsi->dev, "Failed to detach from DSI host: %d\n", ret);
+
+	drm_panel_remove(&ctx->panel);
+}
+
+static const struct of_device_id s6e88a0_ams427ap24_of_match[] = {
+	{ .compatible = "samsung,s6e88a0-ams427ap24" },
+	{ /* sentinel */ },
+};
+MODULE_DEVICE_TABLE(of, s6e88a0_ams427ap24_of_match);
+
+static struct mipi_dsi_driver s6e88a0_ams427ap24_driver = {
+	.probe = s6e88a0_ams427ap24_probe,
+	.remove = s6e88a0_ams427ap24_remove,
+	.driver = {
+		.name = "panel-s6e88a0-ams427ap24",
+		.of_match_table = s6e88a0_ams427ap24_of_match,
+	},
+};
+module_mipi_dsi_driver(s6e88a0_ams427ap24_driver);
+
+MODULE_AUTHOR("Jakob Hauser <jahau@rocketmail.com>");
+MODULE_DESCRIPTION("Samsung AMS427AP24 panel with S6E88A0 controller");
+MODULE_LICENSE("GPL v2");
-- 
2.39.5


^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH v3 4/5] drm/panel: samsung-s6e88a0-ams427ap24: Add brightness control
  2024-10-24  3:18 [PATCH v3 0/5] Add new panel driver Samsung S6E88A0-AMS427AP24 Jakob Hauser
                   ` (2 preceding siblings ...)
  2024-10-24  3:18 ` [PATCH v3 3/5] drm/panel: samsung-s6e88a0-ams427ap24: Add initial driver Jakob Hauser
@ 2024-10-24  3:18 ` Jakob Hauser
  2024-10-25 19:27   ` Linus Walleij
  2024-10-24  3:18 ` [PATCH v3 5/5] drm/panel: samsung-s6e88a0-ams427ap24: Add flip option Jakob Hauser
  4 siblings, 1 reply; 14+ messages in thread
From: Jakob Hauser @ 2024-10-24  3:18 UTC (permalink / raw)
  To: Neil Armstrong, Jessica Zhang, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley
  Cc: Thierry Reding, Laurent Pinchart, Andrzej Hajda, dri-devel,
	devicetree, linux-kernel, ~postmarketos/upstreaming, Jakob Hauser

The tables for brightness to candela, aid and elvss were taken from downstream
kernel file "dsi_panel_S6E88A0_AMS427AP24_qhd_octa_video.dtsi" [1][2][3].

The gamma table gets generated in "ss_dsi_smart_dimming_S6E88A0_AMS427AP24.c" [4]
with hard-coded starting values. The function smart_dimming_init() [5] goes
through the v{*}_adjustments, generate_gray_scale and gamma_init procedure.
Instead of calculating it manually, it's easier to compile a custom downstream
kernel with SMART_DIMMING_DEBUG enabled and read out dmesg early at boot.

Selection of the values for aid and elvss are again according to downstream
file "dsi_panel_S6E88A0_AMS427AP24_qhd_octa_video.dtsi" [6][7].

The set of write commands is guided by downstream file "ss_dsi_panel_common.c" [8]
followed by "ss_dsi_panel_S6E88A0_AMS427AP24.c" [9].

The dsi mode flag MIPI_DSI_MODE_VIDEO_NO_HFP prevents screen flickering while
changing the brightness.

[1] https://github.com/msm8916-mainline/linux-downstream/blob/GT-I9195I/drivers/video/msm/mdss/samsung/S6E88A0_AMS427AP24/dsi_panel_S6E88A0_AMS427AP24_qhd_octa_video.dtsi#L341-L397
[2] https://github.com/msm8916-mainline/linux-downstream/blob/GT-I9195I/drivers/video/msm/mdss/samsung/S6E88A0_AMS427AP24/dsi_panel_S6E88A0_AMS427AP24_qhd_octa_video.dtsi#L214-L254
[3] https://github.com/msm8916-mainline/linux-downstream/blob/GT-I9195I/drivers/video/msm/mdss/samsung/S6E88A0_AMS427AP24/dsi_panel_S6E88A0_AMS427AP24_qhd_octa_video.dtsi#L301-L320
[4] https://github.com/msm8916-mainline/linux-downstream/blob/GT-I9195I/drivers/video/msm/mdss/samsung/S6E88A0_AMS427AP24/ss_dsi_smart_dimming_S6E88A0_AMS427AP24.c
[5] https://github.com/msm8916-mainline/linux-downstream/blob/GT-I9195I/drivers/video/msm/mdss/samsung/S6E88A0_AMS427AP24/ss_dsi_smart_dimming_S6E88A0_AMS427AP24.c#L1816-L1900
[6] https://github.com/msm8916-mainline/linux-downstream/blob/GT-I9195I/drivers/video/msm/mdss/samsung/S6E88A0_AMS427AP24/dsi_panel_S6E88A0_AMS427AP24_qhd_octa_video.dtsi#L256-L268
[7] https://github.com/msm8916-mainline/linux-downstream/blob/GT-I9195I/drivers/video/msm/mdss/samsung/S6E88A0_AMS427AP24/dsi_panel_S6E88A0_AMS427AP24_qhd_octa_video.dtsi#L322-L334
[8] https://github.com/msm8916-mainline/linux-downstream/blob/GT-I9195I/drivers/video/msm/mdss/samsung/ss_dsi_panel_common.c#L1389-L1517
[9] https://github.com/msm8916-mainline/linux-downstream/blob/GT-I9195I/drivers/video/msm/mdss/samsung/S6E88A0_AMS427AP24/ss_dsi_panel_S6E88A0_AMS427AP24.c#L666-L678

Signed-off-by: Jakob Hauser <jahau@rocketmail.com>
Reviewed-by: Neil Armstrong <neil.armstrong@linaro.org>
---
 drivers/gpu/drm/panel/Kconfig                 |   1 +
 .../panel/panel-samsung-s6e88a0-ams427ap24.c  | 519 +++++++++++++++++-
 2 files changed, 508 insertions(+), 12 deletions(-)

diff --git a/drivers/gpu/drm/panel/Kconfig b/drivers/gpu/drm/panel/Kconfig
index f8adc38447fb..d7469c565d1d 100644
--- a/drivers/gpu/drm/panel/Kconfig
+++ b/drivers/gpu/drm/panel/Kconfig
@@ -636,6 +636,7 @@ config DRM_PANEL_SAMSUNG_S6E88A0_AMS427AP24
 	tristate "Samsung AMS427AP24 panel with S6E88A0 controller"
 	depends on GPIOLIB && OF && REGULATOR
 	depends on DRM_MIPI_DSI
+	depends on BACKLIGHT_CLASS_DEVICE
 	help
 	  Say Y here if you want to enable support for Samsung AMS427AP24 panel
 	  with S6E88A0 controller (found in Samsung Galaxy S4 Mini Value Edition
diff --git a/drivers/gpu/drm/panel/panel-samsung-s6e88a0-ams427ap24.c b/drivers/gpu/drm/panel/panel-samsung-s6e88a0-ams427ap24.c
index 7435e0fcb4f5..9e211be432d7 100644
--- a/drivers/gpu/drm/panel/panel-samsung-s6e88a0-ams427ap24.c
+++ b/drivers/gpu/drm/panel/panel-samsung-s6e88a0-ams427ap24.c
@@ -4,6 +4,7 @@
  * Copyright (c) 2024 Jakob Hauser <jahau@rocketmail.com>
  */
 
+#include <linux/backlight.h>
 #include <linux/delay.h>
 #include <linux/gpio/consumer.h>
 #include <linux/module.h>
@@ -17,8 +18,17 @@
 #include <drm/drm_panel.h>
 #include <drm/drm_probe_helper.h>
 
+#define NUM_STEPS_CANDELA	54
+#define NUM_STEPS_AID		39
+#define NUM_STEPS_ELVSS		17
+
+#define SEQ_LENGTH_AID		5
+#define SEQ_LENGTH_ELVSS	2
+#define SEQ_LENGTH_GAMMA	33
+
 struct s6e88a0_ams427ap24 {
 	struct drm_panel panel;
+	struct backlight_device *bl_dev;
 	struct mipi_dsi_device *dsi;
 	struct regulator_bulk_data *supplies;
 	struct gpio_desc *reset_gpio;
@@ -35,6 +45,464 @@ struct s6e88a0_ams427ap24 *to_s6e88a0_ams427ap24(struct drm_panel *panel)
 	return container_of(panel, struct s6e88a0_ams427ap24, panel);
 }
 
+enum candela {
+	CANDELA_10CD, /* 0 */
+	CANDELA_11CD,
+	CANDELA_12CD,
+	CANDELA_13CD,
+	CANDELA_14CD,
+	CANDELA_15CD,
+	CANDELA_16CD,
+	CANDELA_17CD,
+	CANDELA_19CD,
+	CANDELA_20CD,
+	CANDELA_21CD,
+	CANDELA_22CD,
+	CANDELA_24CD,
+	CANDELA_25CD,
+	CANDELA_27CD,
+	CANDELA_29CD,
+	CANDELA_30CD,
+	CANDELA_32CD,
+	CANDELA_34CD,
+	CANDELA_37CD,
+	CANDELA_39CD,
+	CANDELA_41CD,
+	CANDELA_44CD,
+	CANDELA_47CD,
+	CANDELA_50CD,
+	CANDELA_53CD,
+	CANDELA_56CD,
+	CANDELA_60CD,
+	CANDELA_64CD,
+	CANDELA_68CD,
+	CANDELA_72CD,
+	CANDELA_77CD,
+	CANDELA_82CD,
+	CANDELA_87CD,
+	CANDELA_93CD,
+	CANDELA_98CD,
+	CANDELA_105CD,
+	CANDELA_111CD,
+	CANDELA_119CD,
+	CANDELA_126CD,
+	CANDELA_134CD,
+	CANDELA_143CD,
+	CANDELA_152CD,
+	CANDELA_162CD,
+	CANDELA_172CD,
+	CANDELA_183CD,
+	CANDELA_195CD,
+	CANDELA_207CD,
+	CANDELA_220CD,
+	CANDELA_234CD,
+	CANDELA_249CD,
+	CANDELA_265CD,
+	CANDELA_282CD,
+	CANDELA_300CD, /* 53 */
+};
+
+static const int s6e88a0_ams427ap24_br_to_cd[NUM_STEPS_CANDELA] = {
+	/* brightness till, candela */
+	10, /* 10CD */
+	11, /* 11CD */
+	12, /* 12CD */
+	13, /* 13CD */
+	14, /* 14CD */
+	15, /* 15CD */
+	16, /* 16CD */
+	17, /* 17CD */
+	18, /* 19CD */
+	19, /* 20CD */
+	20, /* 21CD */
+	21, /* 22CD */
+	22, /* 24CD */
+	23, /* 25CD */
+	24, /* 27CD */
+	25, /* 29CD */
+	26, /* 30CD */
+	27, /* 32CD */
+	28, /* 34CD */
+	29, /* 37CD */
+	30, /* 39CD */
+	32, /* 41CD */
+	34, /* 44CD */
+	36, /* 47CD */
+	38, /* 50CD */
+	40, /* 53CD */
+	43, /* 56CD */
+	46, /* 60CD */
+	49, /* 64CD */
+	52, /* 68CD */
+	56, /* 72CD */
+	59, /* 77CD */
+	63, /* 82CD */
+	67, /* 87CD */
+	71, /* 93CD */
+	76, /* 98CD */
+	80, /* 105CD */
+	86, /* 111CD */
+	91, /* 119CD */
+	97, /* 126CD */
+	104, /* 134CD */
+	110, /* 143CD */
+	118, /* 152CD */
+	125, /* 162CD */
+	133, /* 172CD */
+	142, /* 183CD */
+	150, /* 195CD */
+	160, /* 207CD */
+	170, /* 220CD */
+	181, /* 234CD */
+	205, /* 249CD */
+	234, /* 265CD */
+	254, /* 282CD */
+	255, /* 300CD */
+};
+
+static const u8 s6e88a0_ams427ap24_aid[NUM_STEPS_AID][SEQ_LENGTH_AID] = {
+	{ 0x40, 0x08, 0x20, 0x03, 0x77 }, /* AOR 90.9%, 10CD */
+	{ 0x40, 0x08, 0x20, 0x03, 0x73 }, /* AOR 90.5%, 11CD */
+	{ 0x40, 0x08, 0x20, 0x03, 0x69 }, /* AOR 89.4%, 12CD */
+	{ 0x40, 0x08, 0x20, 0x03, 0x65 }, /* AOR 89.0%, 13CD */
+	{ 0x40, 0x08, 0x20, 0x03, 0x61 }, /* AOR 88.6%, 14CD */
+	{ 0x40, 0x08, 0x20, 0x03, 0x55 }, /* AOR 87.4%, 15CD */
+	{ 0x40, 0x08, 0x20, 0x03, 0x50 }, /* AOR 86.9%, 16CD */
+	{ 0x40, 0x08, 0x20, 0x03, 0x45 }, /* AOR 85.8%, 17CD */
+	{ 0x40, 0x08, 0x20, 0x03, 0x35 }, /* AOR 84.1%, 19CD */
+	{ 0x40, 0x08, 0x20, 0x03, 0x27 }, /* AOR 82.7%, 20CD */
+	{ 0x40, 0x08, 0x20, 0x03, 0x23 }, /* AOR 82.3%, 21CD */
+	{ 0x40, 0x08, 0x20, 0x03, 0x17 }, /* AOR 81.0%, 22CD */
+	{ 0x40, 0x08, 0x20, 0x03, 0x11 }, /* AOR 80.4%, 24CD */
+	{ 0x40, 0x08, 0x20, 0x03, 0x04 }, /* AOR 79.1%, 25CD */
+	{ 0x40, 0x08, 0x20, 0x02, 0xf4 }, /* AOR 77.5%, 27CD */
+	{ 0x40, 0x08, 0x20, 0x02, 0xe3 }, /* AOR 75.7%, 29CD */
+	{ 0x40, 0x08, 0x20, 0x02, 0xd7 }, /* AOR 74.5%, 30CD */
+	{ 0x40, 0x08, 0x20, 0x02, 0xc6 }, /* AOR 72.7%, 32CD */
+	{ 0x40, 0x08, 0x20, 0x02, 0xb7 }, /* AOR 71.2%, 34CD */
+	{ 0x40, 0x08, 0x20, 0x02, 0xa1 }, /* AOR 69.0%, 37CD */
+	{ 0x40, 0x08, 0x20, 0x02, 0x91 }, /* AOR 67.3%, 39CD */
+	{ 0x40, 0x08, 0x20, 0x02, 0x78 }, /* AOR 64.8%, 41CD */
+	{ 0x40, 0x08, 0x20, 0x02, 0x62 }, /* AOR 62.5%, 44CD */
+	{ 0x40, 0x08, 0x20, 0x02, 0x45 }, /* AOR 59.5%, 47CD */
+	{ 0x40, 0x08, 0x20, 0x02, 0x30 }, /* AOR 57.4%, 50CD */
+	{ 0x40, 0x08, 0x20, 0x02, 0x13 }, /* AOR 54.4%, 53CD */
+	{ 0x40, 0x08, 0x20, 0x01, 0xf5 }, /* AOR 51.3%, 56CD */
+	{ 0x40, 0x08, 0x20, 0x01, 0xd3 }, /* AOR 47.8%, 60CD */
+	{ 0x40, 0x08, 0x20, 0x01, 0xb1 }, /* AOR 44.4%, 64CD */
+	{ 0x40, 0x08, 0x20, 0x01, 0x87 }, /* AOR 40.1%, 68CD */
+	{ 0x40, 0x08, 0x20, 0x01, 0x63 }, /* AOR 36.6%, 72CD */
+	{ 0x40, 0x08, 0x20, 0x01, 0x35 }, /* AOR 31.7%, 77CD */
+	{ 0x40, 0x08, 0x20, 0x01, 0x05 }, /* AOR 26.9%, 82CD */
+	{ 0x40, 0x08, 0x20, 0x00, 0xd5 }, /* AOR 21.8%, 87CD */
+	{ 0x40, 0x08, 0x20, 0x00, 0xa1 }, /* AOR 16.5%, 93CD */
+	{ 0x40, 0x08, 0x20, 0x00, 0x6f }, /* AOR 11.4%, 98CD */
+	{ 0x40, 0x08, 0x20, 0x00, 0x31 }, /* AOR 5.0%, 105CD */
+	{ 0x40, 0x08, 0x20, 0x01, 0x86 }, /* AOR 40.0%, 111CD ~ 172CD */
+	{ 0x40, 0x08, 0x20, 0x00, 0x08 }, /* AOR 0.6%, 183CD ~ 300CD */
+};
+
+static const u8 s6e88a0_ams427ap24_elvss[NUM_STEPS_ELVSS][SEQ_LENGTH_ELVSS] = {
+	{ 0x28, 0x14 }, /* 10CD ~ 111CD */
+	{ 0x28, 0x13 }, /* 119CD */
+	{ 0x28, 0x12 }, /* 126CD */
+	{ 0x28, 0x12 }, /* 134CD */
+	{ 0x28, 0x11 }, /* 143CD */
+	{ 0x28, 0x10 }, /* 152CD */
+	{ 0x28, 0x0f }, /* 162CD */
+	{ 0x28, 0x0e }, /* 172CD */
+	{ 0x28, 0x11 }, /* 183CD */
+	{ 0x28, 0x11 }, /* 195CD */
+	{ 0x28, 0x10 }, /* 207CD */
+	{ 0x28, 0x0f }, /* 220CD */
+	{ 0x28, 0x0f }, /* 234CD */
+	{ 0x28, 0x0e }, /* 249CD */
+	{ 0x28, 0x0d }, /* 265CD */
+	{ 0x28, 0x0c }, /* 282CD */
+	{ 0x28, 0x0b }, /* 300CD */
+};
+
+static const u8 s6e88a0_ams427ap24_gamma[NUM_STEPS_CANDELA][SEQ_LENGTH_GAMMA] = {
+	/* 10CD */
+	{ 0x00, 0xc8, 0x00, 0xc4, 0x00, 0xc5, 0x8c, 0x8a, 0x8a, 0x8c, 0x8b,
+	  0x8c, 0x87, 0x89, 0x89, 0x88, 0x87, 0x8c, 0x80, 0x82, 0x88, 0x7b,
+	  0x72, 0x8c, 0x60, 0x68, 0x8c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+	/* 11CD */
+	{ 0x00, 0xc8, 0x00, 0xc4, 0x00, 0xc5, 0x8c, 0x8a, 0x8a, 0x8c, 0x8b,
+	  0x8c, 0x87, 0x89, 0x89, 0x88, 0x87, 0x8c, 0x80, 0x82, 0x88, 0x7b,
+	  0x72, 0x8c, 0x60, 0x68, 0x8c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+	/* 12CD */
+	{ 0x00, 0xc8, 0x00, 0xc4, 0x00, 0xc5, 0x8c, 0x8a, 0x8a, 0x8b, 0x8b,
+	  0x8c, 0x88, 0x89, 0x8a, 0x88, 0x87, 0x8c, 0x81, 0x82, 0x87, 0x7a,
+	  0x72, 0x8b, 0x60, 0x68, 0x8c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+	/* 13CD */
+	{ 0x00, 0xc8, 0x00, 0xc4, 0x00, 0xc5, 0x8c, 0x8a, 0x8a, 0x8b, 0x8b,
+	  0x8c, 0x88, 0x89, 0x8a, 0x88, 0x87, 0x8c, 0x81, 0x82, 0x87, 0x7a,
+	  0x72, 0x8b, 0x61, 0x69, 0x8c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+	/* 14CD */
+	{ 0x00, 0xc8, 0x00, 0xc4, 0x00, 0xc5, 0x8c, 0x8a, 0x89, 0x8c, 0x8b,
+	  0x8c, 0x88, 0x89, 0x8a, 0x87, 0x86, 0x8a, 0x82, 0x82, 0x87, 0x79,
+	  0x71, 0x89, 0x63, 0x6c, 0x8e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+	/* 15CD */
+	{ 0x00, 0xc8, 0x00, 0xc4, 0x00, 0xc5, 0x8c, 0x8a, 0x8a, 0x8c, 0x8c,
+	  0x8c, 0x86, 0x87, 0x88, 0x85, 0x85, 0x8a, 0x83, 0x83, 0x88, 0x78,
+	  0x72, 0x89, 0x64, 0x6c, 0x8e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+	/* 16CD */
+	{ 0x00, 0xc8, 0x00, 0xc4, 0x00, 0xc5, 0x8c, 0x8a, 0x89, 0x8c, 0x8b,
+	  0x8c, 0x86, 0x88, 0x88, 0x86, 0x86, 0x8a, 0x84, 0x84, 0x88, 0x78,
+	  0x72, 0x89, 0x5d, 0x67, 0x8b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+	/* 17CD */
+	{ 0x00, 0xc8, 0x00, 0xc4, 0x00, 0xc5, 0x8c, 0x8a, 0x89, 0x8b, 0x8b,
+	  0x8b, 0x87, 0x89, 0x89, 0x86, 0x86, 0x8a, 0x84, 0x83, 0x87, 0x78,
+	  0x73, 0x89, 0x64, 0x6e, 0x8e, 0x38, 0x32, 0x24, 0x00, 0x00, 0x00 },
+	/* 19CD */
+	{ 0x00, 0xc8, 0x00, 0xc4, 0x00, 0xc5, 0x8c, 0x8a, 0x89, 0x8b, 0x8b,
+	  0x8b, 0x87, 0x89, 0x89, 0x86, 0x86, 0x89, 0x84, 0x84, 0x87, 0x77,
+	  0x72, 0x88, 0x65, 0x6f, 0x8e, 0x38, 0x32, 0x24, 0x00, 0x00, 0x00 },
+	/* 20CD */
+	{ 0x00, 0xc8, 0x00, 0xc4, 0x00, 0xc5, 0x8c, 0x8a, 0x89, 0x8b, 0x8b,
+	  0x8b, 0x88, 0x89, 0x89, 0x85, 0x85, 0x88, 0x82, 0x83, 0x85, 0x79,
+	  0x73, 0x88, 0x65, 0x6f, 0x8e, 0x38, 0x32, 0x24, 0x00, 0x00, 0x00 },
+	/* 21CD */
+	{ 0x00, 0xc8, 0x00, 0xc4, 0x00, 0xc5, 0x8c, 0x8a, 0x89, 0x8b, 0x8b,
+	  0x8b, 0x88, 0x89, 0x89, 0x85, 0x85, 0x88, 0x82, 0x83, 0x85, 0x79,
+	  0x74, 0x88, 0x65, 0x6f, 0x8e, 0x38, 0x32, 0x24, 0x00, 0x00, 0x00 },
+	/* 22CD */
+	{ 0x00, 0xc8, 0x00, 0xc4, 0x00, 0xc5, 0x8c, 0x8a, 0x89, 0x8c, 0x8b,
+	  0x8c, 0x86, 0x88, 0x87, 0x86, 0x86, 0x89, 0x82, 0x83, 0x85, 0x7c,
+	  0x75, 0x87, 0x65, 0x6f, 0x8e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+	/* 24CD */
+	{ 0x00, 0xc8, 0x00, 0xc4, 0x00, 0xc5, 0x8c, 0x8a, 0x89, 0x8c, 0x8b,
+	  0x8c, 0x86, 0x88, 0x87, 0x86, 0x86, 0x89, 0x82, 0x83, 0x85, 0x7c,
+	  0x76, 0x86, 0x66, 0x6f, 0x8e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+	/* 25CD */
+	{ 0x00, 0xc8, 0x00, 0xc4, 0x00, 0xc5, 0x8c, 0x8a, 0x89, 0x8b, 0x8b,
+	  0x8b, 0x86, 0x89, 0x88, 0x87, 0x87, 0x89, 0x82, 0x82, 0x84, 0x7f,
+	  0x7a, 0x89, 0x6b, 0x73, 0x8f, 0x33, 0x2f, 0x22, 0x00, 0x00, 0x00 },
+	/* 27CD */
+	{ 0x00, 0xc8, 0x00, 0xc4, 0x00, 0xc5, 0x8c, 0x8a, 0x89, 0x8b, 0x8b,
+	  0x8b, 0x86, 0x89, 0x88, 0x87, 0x87, 0x89, 0x82, 0x82, 0x84, 0x7f,
+	  0x7a, 0x89, 0x6b, 0x73, 0x8f, 0x33, 0x2f, 0x22, 0x00, 0x00, 0x00 },
+	/* 29CD */
+	{ 0x00, 0xc8, 0x00, 0xc4, 0x00, 0xc5, 0x8c, 0x8a, 0x89, 0x8b, 0x8b,
+	  0x8b, 0x86, 0x89, 0x88, 0x85, 0x84, 0x87, 0x84, 0x85, 0x86, 0x80,
+	  0x7b, 0x88, 0x6a, 0x73, 0x8f, 0x33, 0x2f, 0x22, 0x00, 0x00, 0x00 },
+	/* 30CD */
+	{ 0x00, 0xc8, 0x00, 0xc4, 0x00, 0xc5, 0x8c, 0x8a, 0x89, 0x8b, 0x8b,
+	  0x8b, 0x86, 0x89, 0x88, 0x85, 0x84, 0x87, 0x84, 0x85, 0x86, 0x80,
+	  0x7b, 0x88, 0x6a, 0x73, 0x8f, 0x33, 0x2f, 0x22, 0x00, 0x00, 0x00 },
+	/* 32CD */
+	{ 0x00, 0xc8, 0x00, 0xc4, 0x00, 0xc5, 0x8c, 0x8a, 0x89, 0x8b, 0x8b,
+	  0x8b, 0x86, 0x89, 0x88, 0x85, 0x84, 0x87, 0x84, 0x85, 0x86, 0x80,
+	  0x7b, 0x88, 0x6a, 0x73, 0x8f, 0x33, 0x2f, 0x22, 0x00, 0x00, 0x00 },
+	/* 34CD */
+	{ 0x00, 0xc8, 0x00, 0xc4, 0x00, 0xc5, 0x8c, 0x8a, 0x89, 0x8b, 0x8b,
+	  0x8b, 0x86, 0x89, 0x88, 0x85, 0x84, 0x87, 0x83, 0x84, 0x84, 0x7f,
+	  0x79, 0x86, 0x6c, 0x76, 0x91, 0x33, 0x2f, 0x22, 0x00, 0x00, 0x00 },
+	/* 37CD */
+	{ 0x00, 0xc8, 0x00, 0xc4, 0x00, 0xc5, 0x8b, 0x89, 0x89, 0x8b, 0x8b,
+	  0x8b, 0x86, 0x88, 0x88, 0x87, 0x86, 0x87, 0x83, 0x84, 0x84, 0x7f,
+	  0x79, 0x86, 0x6c, 0x76, 0x90, 0x33, 0x2f, 0x22, 0x00, 0x00, 0x00 },
+	/* 39CD */
+	{ 0x00, 0xc8, 0x00, 0xc4, 0x00, 0xc5, 0x8b, 0x89, 0x89, 0x8b, 0x8b,
+	  0x8b, 0x86, 0x88, 0x87, 0x84, 0x84, 0x86, 0x83, 0x85, 0x85, 0x80,
+	  0x79, 0x85, 0x6c, 0x76, 0x90, 0x33, 0x2f, 0x22, 0x00, 0x00, 0x00 },
+	/* 41CD */
+	{ 0x00, 0xc8, 0x00, 0xc4, 0x00, 0xc5, 0x8b, 0x89, 0x89, 0x8b, 0x8b,
+	  0x8b, 0x86, 0x88, 0x87, 0x84, 0x84, 0x86, 0x81, 0x84, 0x83, 0x7f,
+	  0x79, 0x84, 0x6e, 0x79, 0x93, 0x33, 0x2f, 0x22, 0x00, 0x00, 0x00 },
+	/* 44CD */
+	{ 0x00, 0xc8, 0x00, 0xc4, 0x00, 0xc5, 0x8b, 0x89, 0x89, 0x8b, 0x8b,
+	  0x8b, 0x86, 0x88, 0x87, 0x84, 0x84, 0x86, 0x81, 0x84, 0x83, 0x7f,
+	  0x79, 0x84, 0x6e, 0x79, 0x92, 0x33, 0x2f, 0x22, 0x00, 0x00, 0x00 },
+	/* 47CD */
+	{ 0x00, 0xc8, 0x00, 0xc4, 0x00, 0xc5, 0x8b, 0x89, 0x89, 0x8b, 0x8b,
+	  0x8b, 0x86, 0x88, 0x87, 0x84, 0x85, 0x86, 0x81, 0x84, 0x83, 0x7f,
+	  0x79, 0x83, 0x6f, 0x79, 0x91, 0x33, 0x2f, 0x22, 0x00, 0x00, 0x00 },
+	/* 50CD */
+	{ 0x00, 0xc8, 0x00, 0xc4, 0x00, 0xc5, 0x8b, 0x89, 0x89, 0x8b, 0x8b,
+	  0x8b, 0x86, 0x88, 0x87, 0x84, 0x85, 0x86, 0x82, 0x84, 0x83, 0x7f,
+	  0x79, 0x83, 0x6f, 0x79, 0x90, 0x33, 0x2f, 0x22, 0x00, 0x00, 0x00 },
+	/* 53CD */
+	{ 0x00, 0xc8, 0x00, 0xc4, 0x00, 0xc5, 0x8b, 0x89, 0x89, 0x8b, 0x8b,
+	  0x8b, 0x86, 0x88, 0x87, 0x83, 0x83, 0x85, 0x84, 0x85, 0x85, 0x7f,
+	  0x79, 0x83, 0x70, 0x79, 0x8f, 0x33, 0x2f, 0x22, 0x00, 0x00, 0x00 },
+	/* 56CD */
+	{ 0x00, 0xc8, 0x00, 0xc4, 0x00, 0xc5, 0x8b, 0x89, 0x89, 0x8b, 0x8a,
+	  0x8a, 0x87, 0x89, 0x87, 0x83, 0x83, 0x85, 0x84, 0x85, 0x84, 0x7f,
+	  0x79, 0x82, 0x70, 0x7a, 0x8e, 0x33, 0x2f, 0x22, 0x00, 0x00, 0x00 },
+	/* 60CD */
+	{ 0x00, 0xc8, 0x00, 0xc4, 0x00, 0xc5, 0x8b, 0x89, 0x89, 0x8b, 0x8a,
+	  0x8a, 0x87, 0x89, 0x87, 0x83, 0x83, 0x85, 0x84, 0x85, 0x84, 0x7e,
+	  0x79, 0x82, 0x71, 0x7a, 0x8d, 0x33, 0x2f, 0x22, 0x00, 0x00, 0x00 },
+	/* 64CD */
+	{ 0x00, 0xc8, 0x00, 0xc4, 0x00, 0xc5, 0x8b, 0x89, 0x89, 0x8b, 0x8a,
+	  0x8a, 0x86, 0x88, 0x86, 0x84, 0x84, 0x86, 0x82, 0x83, 0x82, 0x80,
+	  0x7a, 0x84, 0x71, 0x7a, 0x8c, 0x33, 0x2f, 0x22, 0x00, 0x00, 0x00 },
+	/* 68CD */
+	{ 0x00, 0xc8, 0x00, 0xc4, 0x00, 0xc5, 0x8a, 0x89, 0x89, 0x8c, 0x8a,
+	  0x8a, 0x86, 0x88, 0x86, 0x84, 0x84, 0x86, 0x82, 0x84, 0x82, 0x81,
+	  0x7b, 0x83, 0x72, 0x7b, 0x8b, 0x33, 0x2f, 0x22, 0x00, 0x00, 0x00 },
+	/* 72CD */
+	{ 0x00, 0xc8, 0x00, 0xc4, 0x00, 0xc5, 0x8a, 0x89, 0x89, 0x8c, 0x8a,
+	  0x8a, 0x86, 0x88, 0x86, 0x85, 0x85, 0x86, 0x82, 0x84, 0x82, 0x81,
+	  0x7b, 0x83, 0x72, 0x7c, 0x8a, 0x33, 0x2f, 0x22, 0x00, 0x00, 0x00 },
+	/* 77CD */
+	{ 0x00, 0xc8, 0x00, 0xc4, 0x00, 0xc5, 0x8a, 0x89, 0x89, 0x8c, 0x8a,
+	  0x8a, 0x85, 0x87, 0x85, 0x85, 0x87, 0x87, 0x82, 0x84, 0x82, 0x81,
+	  0x7c, 0x82, 0x72, 0x7c, 0x89, 0x33, 0x2f, 0x22, 0x00, 0x00, 0x00 },
+	/* 82CD */
+	{ 0x00, 0xc8, 0x00, 0xc4, 0x00, 0xc5, 0x8a, 0x89, 0x89, 0x8c, 0x8a,
+	  0x8a, 0x85, 0x87, 0x85, 0x85, 0x87, 0x87, 0x82, 0x84, 0x82, 0x81,
+	  0x7c, 0x82, 0x73, 0x7c, 0x88, 0x33, 0x2f, 0x22, 0x00, 0x00, 0x00 },
+	/* 87CD */
+	{ 0x00, 0xc8, 0x00, 0xc4, 0x00, 0xc5, 0x8a, 0x89, 0x89, 0x8c, 0x8a,
+	  0x8a, 0x85, 0x87, 0x85, 0x84, 0x84, 0x86, 0x80, 0x84, 0x81, 0x80,
+	  0x7a, 0x82, 0x76, 0x7f, 0x89, 0x33, 0x2f, 0x22, 0x00, 0x00, 0x00 },
+	/* 93CD */
+	{ 0x00, 0xc8, 0x00, 0xc4, 0x00, 0xc5, 0x8a, 0x89, 0x89, 0x8b, 0x8a,
+	  0x8a, 0x86, 0x87, 0x85, 0x84, 0x85, 0x86, 0x80, 0x84, 0x80, 0x80,
+	  0x7a, 0x82, 0x76, 0x80, 0x88, 0x33, 0x2f, 0x22, 0x00, 0x00, 0x00 },
+	/* 98CD */
+	{ 0x00, 0xc8, 0x00, 0xc4, 0x00, 0xc5, 0x8a, 0x89, 0x89, 0x8b, 0x8a,
+	  0x8a, 0x86, 0x87, 0x85, 0x85, 0x85, 0x86, 0x80, 0x84, 0x80, 0x80,
+	  0x7a, 0x82, 0x76, 0x80, 0x88, 0x33, 0x2f, 0x22, 0x00, 0x00, 0x00 },
+	/* 105CD */
+	{ 0x00, 0xc8, 0x00, 0xc4, 0x00, 0xc5, 0x89, 0x88, 0x88, 0x8b, 0x8a,
+	  0x8a, 0x84, 0x87, 0x85, 0x85, 0x85, 0x85, 0x80, 0x84, 0x80, 0x7f,
+	  0x79, 0x81, 0x71, 0x7d, 0x87, 0x38, 0x32, 0x24, 0x00, 0x00, 0x00 },
+	/* 111CD */
+	{ 0x00, 0xdf, 0x00, 0xde, 0x00, 0xde, 0x85, 0x85, 0x84, 0x87, 0x86,
+	  0x87, 0x85, 0x86, 0x85, 0x83, 0x83, 0x83, 0x81, 0x82, 0x82, 0x80,
+	  0x7d, 0x82, 0x75, 0x7f, 0x86, 0x85, 0x85, 0x82, 0x00, 0x00, 0x00 },
+	/* 119CD */
+	{ 0x00, 0xe3, 0x00, 0xe1, 0x00, 0xe2, 0x85, 0x85, 0x84, 0x86, 0x85,
+	  0x85, 0x84, 0x85, 0x84, 0x83, 0x83, 0x83, 0x82, 0x82, 0x82, 0x7e,
+	  0x7b, 0x81, 0x75, 0x7f, 0x86, 0x85, 0x85, 0x82, 0x00, 0x00, 0x00 },
+	/* 126CD */
+	{ 0x00, 0xe6, 0x00, 0xe5, 0x00, 0xe5, 0x85, 0x84, 0x84, 0x85, 0x85,
+	  0x85, 0x84, 0x84, 0x84, 0x82, 0x83, 0x83, 0x80, 0x81, 0x81, 0x80,
+	  0x7f, 0x83, 0x73, 0x7c, 0x84, 0x85, 0x85, 0x82, 0x00, 0x00, 0x00 },
+	/* 134CD */
+	{ 0x00, 0xe9, 0x00, 0xe8, 0x00, 0xe8, 0x84, 0x84, 0x83, 0x85, 0x85,
+	  0x85, 0x84, 0x84, 0x83, 0x81, 0x82, 0x82, 0x81, 0x81, 0x81, 0x7f,
+	  0x7d, 0x81, 0x73, 0x7c, 0x83, 0x85, 0x85, 0x82, 0x00, 0x00, 0x00 },
+	/* 143CD */
+	{ 0x00, 0xed, 0x00, 0xec, 0x00, 0xec, 0x84, 0x83, 0x83, 0x84, 0x84,
+	  0x84, 0x84, 0x84, 0x83, 0x82, 0x83, 0x83, 0x81, 0x80, 0x81, 0x7f,
+	  0x7e, 0x81, 0x70, 0x79, 0x81, 0x85, 0x85, 0x82, 0x00, 0x00, 0x00 },
+	/* 152CD */
+	{ 0x00, 0xf0, 0x00, 0xf0, 0x00, 0xf0, 0x83, 0x83, 0x83, 0x83, 0x83,
+	  0x83, 0x84, 0x84, 0x83, 0x81, 0x81, 0x81, 0x80, 0x80, 0x81, 0x80,
+	  0x80, 0x82, 0x6f, 0x78, 0x7f, 0x85, 0x85, 0x82, 0x00, 0x00, 0x00 },
+	/* 162CD */
+	{ 0x00, 0xf4, 0x00, 0xf3, 0x00, 0xf4, 0x83, 0x83, 0x83, 0x83, 0x83,
+	  0x83, 0x82, 0x81, 0x81, 0x81, 0x81, 0x81, 0x80, 0x80, 0x81, 0x80,
+	  0x7f, 0x82, 0x6f, 0x78, 0x7f, 0x85, 0x85, 0x82, 0x00, 0x00, 0x00 },
+	/* 172CD */
+	{ 0x00, 0xf8, 0x00, 0xf8, 0x00, 0xf8, 0x82, 0x82, 0x82, 0x82, 0x82,
+	  0x82, 0x82, 0x81, 0x81, 0x80, 0x81, 0x80, 0x80, 0x80, 0x81, 0x81,
+	  0x80, 0x83, 0x6d, 0x76, 0x7d, 0x85, 0x85, 0x82, 0x00, 0x00, 0x00 },
+	/* 183CD */
+	{ 0x00, 0xe0, 0x00, 0xdf, 0x00, 0xdf, 0x84, 0x84, 0x83, 0x86, 0x86,
+	  0x86, 0x83, 0x84, 0x83, 0x82, 0x82, 0x82, 0x81, 0x83, 0x81, 0x81,
+	  0x7e, 0x81, 0x80, 0x82, 0x84, 0x85, 0x85, 0x82, 0x00, 0x00, 0x00 },
+	/* 195CD */
+	{ 0x00, 0xe4, 0x00, 0xe3, 0x00, 0xe3, 0x84, 0x83, 0x83, 0x85, 0x85,
+	  0x85, 0x83, 0x84, 0x83, 0x81, 0x82, 0x82, 0x82, 0x83, 0x81, 0x81,
+	  0x80, 0x82, 0x7d, 0x7f, 0x81, 0x85, 0x85, 0x82, 0x00, 0x00, 0x00 },
+	/* 207CD */
+	{ 0x00, 0xe7, 0x00, 0xe6, 0x00, 0xe6, 0x83, 0x82, 0x82, 0x85, 0x85,
+	  0x85, 0x82, 0x83, 0x83, 0x82, 0x82, 0x82, 0x80, 0x81, 0x80, 0x81,
+	  0x80, 0x82, 0x7d, 0x7f, 0x81, 0x85, 0x85, 0x82, 0x00, 0x00, 0x00 },
+	/* 220CD */
+	{ 0x00, 0xeb, 0x00, 0xea, 0x00, 0xea, 0x83, 0x83, 0x82, 0x84, 0x84,
+	  0x84, 0x82, 0x83, 0x82, 0x81, 0x81, 0x82, 0x81, 0x82, 0x81, 0x80,
+	  0x7e, 0x80, 0x7d, 0x7f, 0x81, 0x85, 0x85, 0x82, 0x00, 0x00, 0x00 },
+	/* 234CD */
+	{ 0x00, 0xef, 0x00, 0xee, 0x00, 0xee, 0x83, 0x82, 0x82, 0x83, 0x83,
+	  0x83, 0x82, 0x82, 0x82, 0x81, 0x81, 0x81, 0x80, 0x80, 0x80, 0x80,
+	  0x80, 0x81, 0x7b, 0x7c, 0x7f, 0x85, 0x85, 0x82, 0x00, 0x00, 0x00 },
+	/* 249CD */
+	{ 0x00, 0xf3, 0x00, 0xf2, 0x00, 0xf2, 0x82, 0x81, 0x81, 0x83, 0x83,
+	  0x83, 0x82, 0x82, 0x82, 0x81, 0x81, 0x81, 0x80, 0x81, 0x80, 0x7f,
+	  0x7e, 0x7f, 0x7b, 0x7c, 0x7f, 0x85, 0x85, 0x82, 0x00, 0x00, 0x00 },
+	/* 265CD */
+	{ 0x00, 0xf7, 0x00, 0xf7, 0x00, 0xf7, 0x81, 0x81, 0x80, 0x82, 0x82,
+	  0x82, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x81, 0x80, 0x7f,
+	  0x7e, 0x7f, 0x7b, 0x7c, 0x7f, 0x85, 0x85, 0x82, 0x00, 0x00, 0x00 },
+	/* 282CD */
+	{ 0x00, 0xfb, 0x00, 0xfb, 0x00, 0xfb, 0x80, 0x80, 0x80, 0x81, 0x81,
+	  0x81, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x7f, 0x7f, 0x7f, 0x7f,
+	  0x7f, 0x7f, 0x78, 0x79, 0x7d, 0x85, 0x85, 0x82, 0x00, 0x00, 0x00 },
+	/* 300CD */
+	{ 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x80, 0x80, 0x80, 0x80, 0x80,
+	  0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+	  0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00 },
+};
+
+static int s6e88a0_ams427ap24_set_brightness(struct backlight_device *bd)
+{
+	struct s6e88a0_ams427ap24 *ctx = bl_get_data(bd);
+	struct mipi_dsi_device *dsi = ctx->dsi;
+	struct mipi_dsi_multi_context dsi_ctx = { .dsi = dsi };
+	struct device *dev = &dsi->dev;
+	int brightness = bd->props.brightness;
+	int candela_enum;
+	u8 b2[SEQ_LENGTH_AID + 1];
+	u8 b6[SEQ_LENGTH_ELVSS + 1];
+	u8 ca[SEQ_LENGTH_GAMMA + 1];
+
+	/* get candela enum from brightness */
+	for (candela_enum = 0; candela_enum < NUM_STEPS_CANDELA; candela_enum++)
+		if (brightness <= s6e88a0_ams427ap24_br_to_cd[candela_enum])
+			break;
+
+	/* get aid */
+	b2[0] = 0xb2;
+	switch (candela_enum) {
+	case CANDELA_10CD ... CANDELA_105CD:
+		memcpy(&b2[1], s6e88a0_ams427ap24_aid[candela_enum],
+		       SEQ_LENGTH_AID);
+		break;
+	case CANDELA_111CD ... CANDELA_172CD:
+		memcpy(&b2[1], s6e88a0_ams427ap24_aid[CANDELA_111CD],
+		       SEQ_LENGTH_AID);
+		break;
+	case CANDELA_183CD ... CANDELA_300CD:
+		memcpy(&b2[1], s6e88a0_ams427ap24_aid[CANDELA_111CD + 1],
+		       SEQ_LENGTH_AID);
+		break;
+	default:
+		dev_err(dev, "Failed to get aid data\n");
+		return -EINVAL;
+	}
+
+	/* get elvss */
+	b6[0] = 0xb6;
+	if (candela_enum <= CANDELA_111CD) {
+		memcpy(&b6[1], s6e88a0_ams427ap24_elvss[0], SEQ_LENGTH_ELVSS);
+	} else {
+		memcpy(&b6[1], s6e88a0_ams427ap24_elvss[candela_enum - CANDELA_111CD],
+		       SEQ_LENGTH_ELVSS);
+	}
+
+	/* get gamma */
+	ca[0] = 0xca;
+	memcpy(&ca[1], s6e88a0_ams427ap24_gamma[candela_enum], SEQ_LENGTH_GAMMA);
+
+	/* write: key on, aid, acl off, elvss, gamma, gamma update, key off */
+	mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xf0, 0x5a, 0x5a);
+	mipi_dsi_dcs_write_buffer_multi(&dsi_ctx, b2, ARRAY_SIZE(b2));
+	mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x55, 0x00);
+	mipi_dsi_dcs_write_buffer_multi(&dsi_ctx, b6, ARRAY_SIZE(b6));
+	mipi_dsi_dcs_write_buffer_multi(&dsi_ctx, ca, ARRAY_SIZE(ca));
+	mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xf7, 0x03);
+	mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xf0, 0xa5, 0xa5);
+
+	return dsi_ctx.accum_err;
+}
+
 static void s6e88a0_ams427ap24_reset(struct s6e88a0_ams427ap24 *ctx)
 {
 	gpiod_set_value_cansleep(ctx->reset_gpio, 0);
@@ -49,6 +517,8 @@ static int s6e88a0_ams427ap24_on(struct s6e88a0_ams427ap24 *ctx)
 {
 	struct mipi_dsi_device *dsi = ctx->dsi;
 	struct mipi_dsi_multi_context dsi_ctx = { .dsi = dsi };
+	struct device *dev = &dsi->dev;
+	int ret;
 
 	dsi->mode_flags |= MIPI_DSI_MODE_LPM;
 
@@ -68,20 +538,15 @@ static int s6e88a0_ams427ap24_on(struct s6e88a0_ams427ap24 *ctx)
 	mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xcc, 0x4c);
 	mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xf2, 0x03, 0x0d);
 	mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xf1, 0xa5, 0xa5);
-	mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xca,
-				     0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x80,
-				     0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
-				     0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
-				     0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
-				     0x80, 0x80, 0x00, 0x00, 0x00);
-	mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xb2,
-				     0x40, 0x08, 0x20, 0x00, 0x08);
-	mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xb6, 0x28, 0x0b);
-	mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xf7, 0x03);
-	mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x55, 0x00);
 	mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xf0, 0xa5, 0xa5);
 	mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xfc, 0xa5, 0xa5);
 
+	ret = s6e88a0_ams427ap24_set_brightness(ctx->bl_dev);
+	if (ret < 0) {
+		dev_err(dev, "Failed to set brightness: %d\n", ret);
+		return ret;
+	}
+
 	mipi_dsi_dcs_set_display_on_multi(&dsi_ctx);
 
 	return dsi_ctx.accum_err;
@@ -173,6 +638,32 @@ static const struct drm_panel_funcs s6e88a0_ams427ap24_panel_funcs = {
 	.get_modes = s6e88a0_ams427ap24_get_modes,
 };
 
+static const struct backlight_ops s6e88a0_ams427ap24_bl_ops = {
+	.update_status	= s6e88a0_ams427ap24_set_brightness,
+};
+
+static int s6e88a0_ams427ap24_register_backlight(struct s6e88a0_ams427ap24 *ctx)
+{
+	struct backlight_properties props = {
+		.type		= BACKLIGHT_RAW,
+		.brightness	= 180,
+		.max_brightness = 255,
+	};
+	struct mipi_dsi_device *dsi = ctx->dsi;
+	struct device *dev = &dsi->dev;
+	int ret = 0;
+
+	ctx->bl_dev = devm_backlight_device_register(dev, dev_name(dev), dev, ctx,
+						     &s6e88a0_ams427ap24_bl_ops,
+						     &props);
+	if (IS_ERR(ctx->bl_dev)) {
+		ret = PTR_ERR(ctx->bl_dev);
+		dev_err(dev, "error registering backlight device (%d)\n", ret);
+	}
+
+	return ret;
+}
+
 static int s6e88a0_ams427ap24_probe(struct mipi_dsi_device *dsi)
 {
 	struct device *dev = &dsi->dev;
@@ -201,12 +692,16 @@ static int s6e88a0_ams427ap24_probe(struct mipi_dsi_device *dsi)
 	dsi->lanes = 2;
 	dsi->format = MIPI_DSI_FMT_RGB888;
 	dsi->mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_BURST |
-			  MIPI_DSI_MODE_NO_EOT_PACKET;
+			  MIPI_DSI_MODE_NO_EOT_PACKET | MIPI_DSI_MODE_VIDEO_NO_HFP;
 
 	drm_panel_init(&ctx->panel, dev, &s6e88a0_ams427ap24_panel_funcs,
 		       DRM_MODE_CONNECTOR_DSI);
 	ctx->panel.prepare_prev_first = true;
 
+	ret = s6e88a0_ams427ap24_register_backlight(ctx);
+	if (ret < 0)
+		return ret;
+
 	drm_panel_add(&ctx->panel);
 
 	ret = mipi_dsi_attach(dsi);
-- 
2.39.5


^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH v3 5/5] drm/panel: samsung-s6e88a0-ams427ap24: Add flip option
  2024-10-24  3:18 [PATCH v3 0/5] Add new panel driver Samsung S6E88A0-AMS427AP24 Jakob Hauser
                   ` (3 preceding siblings ...)
  2024-10-24  3:18 ` [PATCH v3 4/5] drm/panel: samsung-s6e88a0-ams427ap24: Add brightness control Jakob Hauser
@ 2024-10-24  3:18 ` Jakob Hauser
  2024-10-25 19:32   ` Linus Walleij
  4 siblings, 1 reply; 14+ messages in thread
From: Jakob Hauser @ 2024-10-24  3:18 UTC (permalink / raw)
  To: Neil Armstrong, Jessica Zhang, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley
  Cc: Thierry Reding, Laurent Pinchart, Andrzej Hajda, dri-devel,
	devicetree, linux-kernel, ~postmarketos/upstreaming, Jakob Hauser

The way of implementing a flip option follows the existing
panel-samsung-s6e8aa0.c [1][2][3].

The value to flip the screen is taken from a downstream kernel file of
a similar but older panel [4]. The mipi clock [5] for the new panel
samsung-s6e88a0-ams427ap24 matches 461 MHz and a hardware read-out of the
0xcb values corresponds to revision R01 of that older panel [6]. Although
for samsung-s6e88a0-ams427ap24 that's in non-flipped state while in this
older driver it seems to be the other way around. Further up there is a
hint [7] basically saying for revision R01 to change the first word of the
0xcb command from 0x06 to 0x0e, which is actually setting BIT(3) of that
word. This causes a horizontal flip.

[1] https://github.com/torvalds/linux/blob/v6.11/drivers/gpu/drm/panel/panel-samsung-s6e8aa0.c#L103
[2] https://github.com/torvalds/linux/blob/v6.11/drivers/gpu/drm/panel/panel-samsung-s6e8aa0.c#L207-L211
[3] https://github.com/torvalds/linux/blob/v6.11/drivers/gpu/drm/panel/panel-samsung-s6e8aa0.c#L954-L974
[4] https://github.com/LineageOS/android_kernel_samsung_msm8930-common/blob/lineage-15.1/drivers/video/msm/mipi_samsung_oled_video_qhd_pt-8930.c
[5] https://github.com/LineageOS/android_kernel_samsung_msm8930-common/blob/lineage-15.1/drivers/video/msm/mipi_samsung_oled_video_qhd_pt-8930.c#L2027-L2028
[6] https://github.com/LineageOS/android_kernel_samsung_msm8930-common/blob/lineage-15.1/drivers/video/msm/mipi_samsung_oled_video_qhd_pt-8930.c#L137-L151
[7] https://github.com/LineageOS/android_kernel_samsung_msm8930-common/blob/lineage-15.1/drivers/video/msm/mipi_samsung_oled_video_qhd_pt-8930.c#L66-L74

Signed-off-by: Jakob Hauser <jahau@rocketmail.com>
Reviewed-by: Neil Armstrong <neil.armstrong@linaro.org>
---
Changes in v3:
 - Dissolved function s6e88a0_ams427ap24_parse_dt() and placed
   the parsing in the probe function. Changed the parsing from
   of_property_read_bool() to device_property_read_bool().
---
 drivers/gpu/drm/panel/panel-samsung-s6e88a0-ams427ap24.c | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/drivers/gpu/drm/panel/panel-samsung-s6e88a0-ams427ap24.c b/drivers/gpu/drm/panel/panel-samsung-s6e88a0-ams427ap24.c
index 9e211be432d7..cbd51351a325 100644
--- a/drivers/gpu/drm/panel/panel-samsung-s6e88a0-ams427ap24.c
+++ b/drivers/gpu/drm/panel/panel-samsung-s6e88a0-ams427ap24.c
@@ -32,6 +32,7 @@ struct s6e88a0_ams427ap24 {
 	struct mipi_dsi_device *dsi;
 	struct regulator_bulk_data *supplies;
 	struct gpio_desc *reset_gpio;
+	bool flip_horizontal;
 };
 
 static const struct regulator_bulk_data s6e88a0_ams427ap24_supplies[] = {
@@ -538,6 +539,10 @@ static int s6e88a0_ams427ap24_on(struct s6e88a0_ams427ap24 *ctx)
 	mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xcc, 0x4c);
 	mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xf2, 0x03, 0x0d);
 	mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xf1, 0xa5, 0xa5);
+
+	if (ctx->flip_horizontal)
+		mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xcb, 0x0e);
+
 	mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xf0, 0xa5, 0xa5);
 	mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xfc, 0xa5, 0xa5);
 
@@ -698,6 +703,8 @@ static int s6e88a0_ams427ap24_probe(struct mipi_dsi_device *dsi)
 		       DRM_MODE_CONNECTOR_DSI);
 	ctx->panel.prepare_prev_first = true;
 
+	ctx->flip_horizontal = device_property_read_bool(dev, "flip-horizontal");
+
 	ret = s6e88a0_ams427ap24_register_backlight(ctx);
 	if (ret < 0)
 		return ret;
-- 
2.39.5


^ permalink raw reply related	[flat|nested] 14+ messages in thread

* Re: [PATCH v3 2/5] dt-bindings: display: panel: Add Samsung S6E88A0-AMS427AP24
  2024-10-24  3:18 ` [PATCH v3 2/5] dt-bindings: display: panel: Add Samsung S6E88A0-AMS427AP24 Jakob Hauser
@ 2024-10-25 16:24   ` Linus Walleij
  0 siblings, 0 replies; 14+ messages in thread
From: Linus Walleij @ 2024-10-25 16:24 UTC (permalink / raw)
  To: Jakob Hauser
  Cc: Neil Armstrong, Jessica Zhang, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Thierry Reding, Laurent Pinchart, Andrzej Hajda,
	dri-devel, devicetree, linux-kernel, ~postmarketos/upstreaming,
	Krzysztof Kozlowski

On Thu, Oct 24, 2024 at 5:18 AM Jakob Hauser <jahau@rocketmail.com> wrote:

> Add bindings for Samsung AMS427AP24 panel with S6E88A0 controller.
>
> Signed-off-by: Jakob Hauser <jahau@rocketmail.com>
> Reviewed-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>

Reviewed-by: Linus Walleij <linus.walleij@linaro.org>

Yours,
Linus Walleij

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH v3 1/5] dt-bindings: display: panel: Move flip properties to panel-common
  2024-10-24  3:18 ` [PATCH v3 1/5] dt-bindings: display: panel: Move flip properties to panel-common Jakob Hauser
@ 2024-10-25 16:25   ` Linus Walleij
  0 siblings, 0 replies; 14+ messages in thread
From: Linus Walleij @ 2024-10-25 16:25 UTC (permalink / raw)
  To: Jakob Hauser
  Cc: Neil Armstrong, Jessica Zhang, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Thierry Reding, Laurent Pinchart, Andrzej Hajda,
	dri-devel, devicetree, linux-kernel, ~postmarketos/upstreaming,
	Krzysztof Kozlowski

On Thu, Oct 24, 2024 at 5:18 AM Jakob Hauser <jahau@rocketmail.com> wrote:

> The flip properties were used by "samsung,s6e8aa0.yaml" only so far. By
> introducing "samsung,s6e88a0-ams427ap24.yaml" they become more common.
>
> Signed-off-by: Jakob Hauser <jahau@rocketmail.com>
> Reviewed-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>

I think I even have a legacy panel that needs this, good!
Reviewed-by: Linus Walleij <linus.walleij@linaro.org>

Yours,
Linus Walleij

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH v3 3/5] drm/panel: samsung-s6e88a0-ams427ap24: Add initial driver
  2024-10-24  3:18 ` [PATCH v3 3/5] drm/panel: samsung-s6e88a0-ams427ap24: Add initial driver Jakob Hauser
@ 2024-10-25 16:36   ` Linus Walleij
  2024-10-26  8:51     ` Jakob Hauser
  0 siblings, 1 reply; 14+ messages in thread
From: Linus Walleij @ 2024-10-25 16:36 UTC (permalink / raw)
  To: Jakob Hauser
  Cc: Neil Armstrong, Jessica Zhang, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Thierry Reding, Laurent Pinchart, Andrzej Hajda,
	dri-devel, devicetree, linux-kernel, ~postmarketos/upstreaming

Hi Jakob,

thanks for your patch!

On Thu, Oct 24, 2024 at 5:18 AM Jakob Hauser <jahau@rocketmail.com> wrote:

> This initial part of the panel driver was mostly generated by the
> "linux-mdss-dsi-panel-driver-generator" tool [1], reading downstream
> Android kernel file "dsi_panel_S6E88A0_AMS427AP24_qhd_octa_video.dtsi" [2].
>
> On top of the generic output of the tool, there were a couple of changes
> applied:
> - Added mipi_dsi_dcs_set_display_on() to function s6e88a0_ams427ap24_on(),
>   otherwise the display does not show up.
> - In functions s6e88a0_ams427ap24_on() and s6e88a0_ams427ap24_off()
>   changed DSI commands to multi context and used "accum_err" returns.
> - In functions s6e88a0_ams427ap24_on() and s6e88a0_ams427ap24_off() replaced
>   msleep() by mipi_dsi_msleep().
> - The function s6e88a0_ams427ap24_get_modes() was changed to make use of
>   drm_connector_helper_get_modes_fixed(). This also required to include
>   drm/drm_probe_helper.h.
> - In function s6e88a0_ams427ap24_probe() registring the regulators was changed
>   to devm_regulator_bulk_get_const(). This required to change supplies in struct
>   s6e88a0_ams427ap24 to a pointer.
> - Removed bool "prepared" from struct s6e88a0_ams427ap24 and according parts in
>   functions s6e88a0_ams427ap24_prepare() and s6e88a0_ams427ap24_unprepare().
>
> [1] https://github.com/msm8916-mainline/linux-mdss-dsi-panel-driver-generator
> [2] https://github.com/msm8916-mainline/linux-downstream/blob/GT-I9195I/drivers/video/msm/mdss/samsung/S6E88A0_AMS427AP24/dsi_panel_S6E88A0_AMS427AP24_qhd_octa_video.dtsi
>
> Signed-off-by: Jakob Hauser <jahau@rocketmail.com>

Nice job on this driver so far!

> +#include <linux/delay.h>
> +#include <linux/gpio/consumer.h>
> +#include <linux/module.h>
> +#include <linux/of.h>

Why do you need this include? .of_match_table is part of
<linux/driver.h>

> +static int s6e88a0_ams427ap24_on(struct s6e88a0_ams427ap24 *ctx)
> +{
> +       struct mipi_dsi_device *dsi = ctx->dsi;
> +       struct mipi_dsi_multi_context dsi_ctx = { .dsi = dsi };
> +
> +       dsi->mode_flags |= MIPI_DSI_MODE_LPM;
> +
> +       mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xf0, 0x5a, 0x5a);

Can we provide #defines for at least some of this magic?
See other drivers for a very good idea of what some of them mean.
panel-samsung-s6d27a1.c:#define S6D27A1_PASSWD_L2       0xF0    /*
Password Command for Level 2 Control */
panel-samsung-s6d7aa0.c:#define MCS_PASSWD1             0xf0

> +       mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xfc, 0x5a, 0x5a);

panel-samsung-s6d7aa0.c:#define MCS_PASSWD3             0xfc

> +       mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xb0, 0x11);
> +       mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xfd, 0x11);
> +       mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xb0, 0x13);
> +       mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xfd, 0x18);
> +       mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xb0, 0x02);
> +       mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xb8, 0x30);
(...)
> +       mipi_dsi_dcs_exit_sleep_mode_multi(&dsi_ctx);
> +       mipi_dsi_msleep(&dsi_ctx, 20);
> +
> +       mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xf1, 0x5a, 0x5a);

panel-samsung-s6d7aa0.c:#define MCS_PASSWD2             0xf1

> +       mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xcc, 0x4c);
> +       mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xf2, 0x03, 0x0d);
> +       mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xf1, 0xa5, 0xa5);

panel-samsung-s6d7aa0.c:#define MCS_PASSWD2             0xf1
Send in the reverse password: disable access.

> +       mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xca,
> +                                    0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x80,
> +                                    0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
> +                                    0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
> +                                    0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
> +                                    0x80, 0x80, 0x00, 0x00, 0x00);
> +       mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xb2,
> +                                    0x40, 0x08, 0x20, 0x00, 0x08);
> +       mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xb6, 0x28, 0x0b);
> +       mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xf7, 0x03);
> +       mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x55, 0x00);
> +       mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xf0, 0xa5, 0xa5);
> +       mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xfc, 0xa5, 0xa5);

Send in the reverse password: disable access.

A bit of #defines and comments would make it much more clear what
is going on.

Yours,
Linus Walleij

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH v3 4/5] drm/panel: samsung-s6e88a0-ams427ap24: Add brightness control
  2024-10-24  3:18 ` [PATCH v3 4/5] drm/panel: samsung-s6e88a0-ams427ap24: Add brightness control Jakob Hauser
@ 2024-10-25 19:27   ` Linus Walleij
  2024-10-26 10:47     ` Jakob Hauser
  0 siblings, 1 reply; 14+ messages in thread
From: Linus Walleij @ 2024-10-25 19:27 UTC (permalink / raw)
  To: Jakob Hauser
  Cc: Neil Armstrong, Jessica Zhang, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Thierry Reding, Laurent Pinchart, Andrzej Hajda,
	dri-devel, devicetree, linux-kernel, ~postmarketos/upstreaming

Hi Jakob,

thanks for your patch!

On Thu, Oct 24, 2024 at 5:18 AM Jakob Hauser <jahau@rocketmail.com> wrote:
> +static const int s6e88a0_ams427ap24_br_to_cd[NUM_STEPS_CANDELA] = {

(...)
> +       /* brightness till, candela */

Brightness to candela conversion table? Edit comment?

> +static const u8 s6e88a0_ams427ap24_aid[NUM_STEPS_AID][SEQ_LENGTH_AID] = {

If you know that the sequence 0xb2, 0x40, 0x08, 0x20 means "set AID"
(or is it AOR??) you can #define

#define S6E88A0_SET_AID 0xb2

Then make a small buffer:

u8 set_aid[5] = { S6E88A0_SET_AID, 0x40, 0x08, 0x20, 0x00, 0x00 };

then you can strip the first three bytes from the entire table,
just copy in the two relevant bytes into set_aor[]
and send that.

> +static const u8 s6e88a0_ams427ap24_elvss[NUM_STEPS_ELVSS][SEQ_LENGTH_ELVSS] = {
> +       { 0x28, 0x14 }, /* 10CD ~ 111CD */
> +       { 0x28, 0x13 }, /* 119CD */

Command 0xb6 is
#define S6E88A0_SET_LVSS 0xb6

Same comment: just define
u8 set_lvss[2] = {S6E88A0_SET_LVSS, 0x28, 0x00};
copy the second byte into the command, this becomes
an array of single bytes.

> +static const u8 s6e88a0_ams427ap24_gamma[NUM_STEPS_CANDELA][SEQ_LENGTH_GAMMA] = {
> +       /* 10CD */
> +       { 0x00, 0xc8, 0x00, 0xc4, 0x00, 0xc5, 0x8c, 0x8a, 0x8a, 0x8c, 0x8b,
> +         0x8c, 0x87, 0x89, 0x89, 0x88, 0x87, 0x8c, 0x80, 0x82, 0x88, 0x7b,
> +         0x72, 0x8c, 0x60, 0x68, 0x8c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },

This array looks fine though, it seems to be all unique gamma calibration.

> +static int s6e88a0_ams427ap24_set_brightness(struct backlight_device *bd)
> +{
> +       struct s6e88a0_ams427ap24 *ctx = bl_get_data(bd);
> +       struct mipi_dsi_device *dsi = ctx->dsi;
> +       struct mipi_dsi_multi_context dsi_ctx = { .dsi = dsi };
> +       struct device *dev = &dsi->dev;
> +       int brightness = bd->props.brightness;
> +       int candela_enum;
> +       u8 b2[SEQ_LENGTH_AID + 1];
> +       u8 b6[SEQ_LENGTH_ELVSS + 1];
> +       u8 ca[SEQ_LENGTH_GAMMA + 1];

Rename them to something like my suggestions so we understand what it is
all about. It seems the infrastructure for what I suggested is mostly already
there.

See comment above how to modify arrays to contain stuff that is always
the same.

> +       /* get aid */
> +       b2[0] = 0xb2;

Use a define per above.

> +       switch (candela_enum) {
> +       case CANDELA_10CD ... CANDELA_105CD:
> +               memcpy(&b2[1], s6e88a0_ams427ap24_aid[candela_enum],
> +                      SEQ_LENGTH_AID);
> +               break;
> +       case CANDELA_111CD ... CANDELA_172CD:
> +               memcpy(&b2[1], s6e88a0_ams427ap24_aid[CANDELA_111CD],
> +                      SEQ_LENGTH_AID);
> +               break;
> +       case CANDELA_183CD ... CANDELA_300CD:
> +               memcpy(&b2[1], s6e88a0_ams427ap24_aid[CANDELA_111CD + 1],
> +                      SEQ_LENGTH_AID);
> +               break;
> +       default:
> +               dev_err(dev, "Failed to get aid data\n");
> +               return -EINVAL;
> +       }
> +
> +       /* get elvss */
> +       b6[0] = 0xb6;

Use a define per above.

> +       if (candela_enum <= CANDELA_111CD) {
> +               memcpy(&b6[1], s6e88a0_ams427ap24_elvss[0], SEQ_LENGTH_ELVSS);
> +       } else {
> +               memcpy(&b6[1], s6e88a0_ams427ap24_elvss[candela_enum - CANDELA_111CD],
> +                      SEQ_LENGTH_ELVSS);
> +       }
> +
> +       /* get gamma */
> +       ca[0] = 0xca;

#define S6E88A0_SET_GAMMA 0xca

> +       memcpy(&ca[1], s6e88a0_ams427ap24_gamma[candela_enum], SEQ_LENGTH_GAMMA);
> +
> +       /* write: key on, aid, acl off, elvss, gamma, gamma update, key off */
> +       mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xf0, 0x5a, 0x5a);

0xf0 is clearly an unlocking key as per comment in the previous patch.

> +       mipi_dsi_dcs_write_buffer_multi(&dsi_ctx, b2, ARRAY_SIZE(b2));
> +       mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x55, 0x00);

0x55 is MIPI_DCS_WRITE_POWER_SAVE in <video/mipi_display.h>

> +       mipi_dsi_dcs_write_buffer_multi(&dsi_ctx, b6, ARRAY_SIZE(b6));
> +       mipi_dsi_dcs_write_buffer_multi(&dsi_ctx, ca, ARRAY_SIZE(ca));

> +       mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xf7, 0x03);
> +       mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xf0, 0xa5, 0xa5);

Clearly this locks the L2 access again.

Yours,
Linus Walleij

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH v3 5/5] drm/panel: samsung-s6e88a0-ams427ap24: Add flip option
  2024-10-24  3:18 ` [PATCH v3 5/5] drm/panel: samsung-s6e88a0-ams427ap24: Add flip option Jakob Hauser
@ 2024-10-25 19:32   ` Linus Walleij
  2024-10-26 11:13     ` Jakob Hauser
  0 siblings, 1 reply; 14+ messages in thread
From: Linus Walleij @ 2024-10-25 19:32 UTC (permalink / raw)
  To: Jakob Hauser
  Cc: Neil Armstrong, Jessica Zhang, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Thierry Reding, Laurent Pinchart, Andrzej Hajda,
	dri-devel, devicetree, linux-kernel, ~postmarketos/upstreaming

Hi Jakob,

thanks for your patch!

On Thu, Oct 24, 2024 at 5:18 AM Jakob Hauser <jahau@rocketmail.com> wrote:

> The way of implementing a flip option follows the existing
> panel-samsung-s6e8aa0.c [1][2][3].

That driver is notoriously hard to read because it uses so much
magic numbers so please don't copy that aspect of the driver.

(...)

> +       if (ctx->flip_horizontal)
> +               mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xcb, 0x0e);

#define S6E88A0_SET_FLIP 0xcb
or something like this.

Other than that it looks good!

Yours,
Linus Walleij

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH v3 3/5] drm/panel: samsung-s6e88a0-ams427ap24: Add initial driver
  2024-10-25 16:36   ` Linus Walleij
@ 2024-10-26  8:51     ` Jakob Hauser
  0 siblings, 0 replies; 14+ messages in thread
From: Jakob Hauser @ 2024-10-26  8:51 UTC (permalink / raw)
  To: Linus Walleij
  Cc: Neil Armstrong, Jessica Zhang, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Thierry Reding, Laurent Pinchart, Andrzej Hajda,
	dri-devel, devicetree, linux-kernel, ~postmarketos/upstreaming

Hi Linus,

On 25.10.24 18:36, Linus Walleij wrote:
...
> On Thu, Oct 24, 2024 at 5:18 AM Jakob Hauser <jahau@rocketmail.com> wrote:
...
> 
>> +#include <linux/delay.h>
>> +#include <linux/gpio/consumer.h>
>> +#include <linux/module.h>
>> +#include <linux/of.h>
> 
> Why do you need this include? .of_match_table is part of
> <linux/driver.h>

You're right, I'll remove it.

>> +static int s6e88a0_ams427ap24_on(struct s6e88a0_ams427ap24 *ctx)
>> +{
>> +       struct mipi_dsi_device *dsi = ctx->dsi;
>> +       struct mipi_dsi_multi_context dsi_ctx = { .dsi = dsi };
>> +
>> +       dsi->mode_flags |= MIPI_DSI_MODE_LPM;
>> +
>> +       mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xf0, 0x5a, 0x5a);
> 
> Can we provide #defines for at least some of this magic?
> See other drivers for a very good idea of what some of them mean.
> panel-samsung-s6d27a1.c:#define S6D27A1_PASSWD_L2       0xF0    /*
> Password Command for Level 2 Control */
> panel-samsung-s6d7aa0.c:#define MCS_PASSWD1             0xf0
> 
>> +       mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xfc, 0x5a, 0x5a);
> 
> panel-samsung-s6d7aa0.c:#define MCS_PASSWD3             0xfc
> 
>> +       mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xb0, 0x11);
>> +       mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xfd, 0x11);
>> +       mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xb0, 0x13);
>> +       mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xfd, 0x18);
>> +       mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xb0, 0x02);
>> +       mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xb8, 0x30);
> (...)
>> +       mipi_dsi_dcs_exit_sleep_mode_multi(&dsi_ctx);
>> +       mipi_dsi_msleep(&dsi_ctx, 20);
>> +
>> +       mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xf1, 0x5a, 0x5a);
> 
> panel-samsung-s6d7aa0.c:#define MCS_PASSWD2             0xf1
> 
>> +       mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xcc, 0x4c);
>> +       mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xf2, 0x03, 0x0d);
>> +       mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xf1, 0xa5, 0xa5);
> 
> panel-samsung-s6d7aa0.c:#define MCS_PASSWD2             0xf1
> Send in the reverse password: disable access.
> 
>> +       mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xca,
>> +                                    0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x80,
>> +                                    0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
>> +                                    0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
>> +                                    0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
>> +                                    0x80, 0x80, 0x00, 0x00, 0x00);
>> +       mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xb2,
>> +                                    0x40, 0x08, 0x20, 0x00, 0x08);
>> +       mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xb6, 0x28, 0x0b);
>> +       mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xf7, 0x03);
>> +       mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x55, 0x00);
>> +       mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xf0, 0xa5, 0xa5);
>> +       mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xfc, 0xa5, 0xa5);
> 
> Send in the reverse password: disable access.
> 
> A bit of #defines and comments would make it much more clear what
> is going on.

The difficulty I'm in is that I don't have a datasheet.

 From the Android kernel downstream driver data ams427ap24 [1], from the similar 
but older panel ams427ap01 downstream driver [2] and the similar panel 
ams452ef01 upstream driver [3] I can guess what the commands do... except I 
couldn't find out what "0xf2, 0x03, 0x0d" does and for "0xf1, 0x5a, 0x5a" I was 
guessing level 3 key on because level 1 and 2 was already there.

[1] 
https://github.com/msm8916-mainline/linux-downstream/blob/GT-I9195I/drivers/video/msm/mdss/samsung/S6E88A0_AMS427AP24/dsi_panel_S6E88A0_AMS427AP24_qhd_octa_video.dtsi
[2] 
https://github.com/LineageOS/android_kernel_samsung_msm8930-common/blob/lineage-15.1/drivers/video/msm/mipi_samsung_oled_video_qhd_pt-8930.c
[3] 
https://github.com/torvalds/linux/blob/v6.11/drivers/gpu/drm/panel/panel-samsung-s6e88a0-ams452ef01.c

That said, I can offer to comment the single command lines like this:

mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xf0, 0x5a, 0x5a); // level 1 key on
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xfc, 0x5a, 0x5a); // level 2 key on
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xb0, 0x11); // src latch set global 1
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xfd, 0x11); // src latch set 1
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xb0, 0x13); // src latch set global 2
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xfd, 0x18); // src latch set 2
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xb0, 0x02); // avdd set 1
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xb8, 0x30); // avdd set 2

mipi_dsi_dcs_exit_sleep_mode_multi(&dsi_ctx);
mipi_dsi_msleep(&dsi_ctx, 20);

mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xf1, 0x5a, 0x5a); // level 3 key on
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xcc, 0x4c); // pixel clock divider pol.
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xf2, 0x03, 0x0d); // unknown
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xf1, 0xa5, 0xa5); // level 3 key off
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xca,
                              0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x80,
                              0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
                              0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
                              0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
                              0x80, 0x80, 0x00, 0x00, 0x00); // set gamma
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xb2,
                              0x40, 0x08, 0x20, 0x00, 0x08); // set aid
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xb6, 0x28, 0x0b); // set elvss
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xf7, 0x03); // gamma update
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x55, 0x00); // acl off
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xf0, 0xa5, 0xa5); // level 1 key off
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xfc, 0xa5, 0xa5); // level 2 key off

Some of those lines exceed the 80 characters limit. I would still prefer not to 
break those lines to keep readability.

Now commenting the single command lines is one thing. But giving names to the 
command registers is something different. E.g. in 0xb0 there is "src latch set 
global" but also one of the "avdd". I wouldn't know what name that command 
register should have. For 0xcc and 0xf2 in the downstream ams427ap24 they're 
both in a block labelled "PCD" and in upstream ams452ef01 the 0xcc line is 
commented as "set Pixel Clock Divider polarity" but the 0xf2 register seems to 
be more general because in downstream ams427ap24 it also shows up in a block 
called "AVC" and in downstream ams427ap01 in a command labelled "vporch". 
Guessing names for the command registers will become too arbitrary.

Additionally, I actually would like to avoid the #defines for the command 
registers because this will definitively break the 80 character lines limits 
strong enough, splintering the above command blocks into quite some mess.

Kind regards,
Jakob

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH v3 4/5] drm/panel: samsung-s6e88a0-ams427ap24: Add brightness control
  2024-10-25 19:27   ` Linus Walleij
@ 2024-10-26 10:47     ` Jakob Hauser
  0 siblings, 0 replies; 14+ messages in thread
From: Jakob Hauser @ 2024-10-26 10:47 UTC (permalink / raw)
  To: Linus Walleij
  Cc: Neil Armstrong, Jessica Zhang, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Thierry Reding, Laurent Pinchart, Andrzej Hajda,
	dri-devel, devicetree, linux-kernel, ~postmarketos/upstreaming

Hi Linus,

On 25.10.24 21:27, Linus Walleij wrote:
...
> On Thu, Oct 24, 2024 at 5:18 AM Jakob Hauser <jahau@rocketmail.com> wrote:
>> +static const int s6e88a0_ams427ap24_br_to_cd[NUM_STEPS_CANDELA] = {
> 
> (...)
>> +       /* brightness till, candela */
> 
> Brightness to candela conversion table? Edit comment?

In the downstream driver there is a table with four columns:
<idx> <from> <till> <candella>.

https://github.com/msm8916-mainline/linux-downstream/blob/GT-I9195I/drivers/video/msm/mdss/samsung/S6E88A0_AMS427AP24/dsi_panel_S6E88A0_AMS427AP24_qhd_octa_video.dtsi#L341-L397

The first column is a counter, the second and third is the 
from-till-range of brightness steps that correspond to the forth column 
of candela identifier.

In the patch here I only adopted the third and forth column, because the 
others were not necessary. The comment "brightness till, candela" was 
intended to label those two columns.

To make it more clear, I could add the keyword "columns" and the column 
"brightness from".

         /* columns: brightness from, brightness till, candela */
         /* 0 */    10,  /* 10CD */
         /* 11 */   11,  /* 11CD */
         /* 12 */   12,  /* 12CD */
         /* 13 */   13,  /* 13CD */
         /* 14 */   14,  /* 14CD */

         ...

         /* 30 */   30,  /* 39CD */
         /* 31 */   32,  /* 41CD */
         /* 33 */   34,  /* 44CD */
         /* 35 */   36,  /* 47CD */

         ...

         /* 92 */   97,  /* 126CD */
         /* 98 */   104, /* 134CD */
         /* 105 */  110, /* 143CD */
         /* 111 */  118, /* 152CD */

         ...

         /* 182 */  205, /* 249CD */
         /* 206 */  234, /* 265CD */
         /* 235 */  254, /* 282CD */
         /* 255 */  255, /* 300CD */

>> +static const u8 s6e88a0_ams427ap24_aid[NUM_STEPS_AID][SEQ_LENGTH_AID] = {
> 
> If you know that the sequence 0xb2, 0x40, 0x08, 0x20 means "set AID"
> (or is it AOR??) you can #define
> 
> #define S6E88A0_SET_AID 0xb2

Thanks to Alexey Min, who looked this up, I can say:

"The PWM mechanism used on Samsung displays is called AOR (AMOLED off 
ratio), the related function on the kernel driver is called AID (AMOLED 
impulsive driving)."

source: xdaforums

The downstream driver of ams427ap24 uses the "aid" labeling, therefore I 
stick to that. (Interestingly the older downstream driver ams427ap01 
uses the "aor" labeling.)

> Then make a small buffer:
> 
> u8 set_aid[5] = { S6E88A0_SET_AID, 0x40, 0x08, 0x20, 0x00, 0x00 };
> 
> then you can strip the first three bytes from the entire table,
> just copy in the two relevant bytes into set_aor[]
> and send that.

Ok, I'll try to implement that. The size of the second array dimension 
of that table will then become [SEQ_LENGTH_AID - 3].

...

>> +static int s6e88a0_ams427ap24_set_brightness(struct backlight_device *bd)
>> +{
>> +       struct s6e88a0_ams427ap24 *ctx = bl_get_data(bd);
>> +       struct mipi_dsi_device *dsi = ctx->dsi;
>> +       struct mipi_dsi_multi_context dsi_ctx = { .dsi = dsi };
>> +       struct device *dev = &dsi->dev;
>> +       int brightness = bd->props.brightness;
>> +       int candela_enum;
>> +       u8 b2[SEQ_LENGTH_AID + 1];
>> +       u8 b6[SEQ_LENGTH_ELVSS + 1];
>> +       u8 ca[SEQ_LENGTH_GAMMA + 1];
> 
> Rename them to something like my suggestions so we understand what it is
> all about. It seems the infrastructure for what I suggested is mostly already
> there.

These defines are intended to be the sequence length of the payload for 
commands aid, elvss and gamma. The naming makes sense to me.

The "+ 1" became necessary because when changing the DCS commands to 
multi type I ran into the issue that there is one for 
"mipi_dsi_dcs_write_seq" and one for "mipi_dsi_dcs_write_buffer"... but 
none for "mipi_dsi_dcs_write" :( So I had to convert those into 
"mipi_dsi_dcs_write_buffer"+multi, thus including the command register 
value into the payload string.

...

>> +       if (candela_enum <= CANDELA_111CD) {
>> +               memcpy(&b6[1], s6e88a0_ams427ap24_elvss[0], SEQ_LENGTH_ELVSS);
>> +       } else {
>> +               memcpy(&b6[1], s6e88a0_ams427ap24_elvss[candela_enum - CANDELA_111CD],
>> +                      SEQ_LENGTH_ELVSS);
>> +       }
>> +
>> +       /* get gamma */
>> +       ca[0] = 0xca;
> 
> #define S6E88A0_SET_GAMMA 0xca

As stated in my reply on patch 3, I would like to avoid those defines 
because firstly the naming becomes arbitrary and secondly it spoils the 
readability of the larger DCS command blocks due to necessary line breaks.

In this specific case here a define would make sense. But I can hardly 
implement it here without doing it elsewhere. Therefore I would like to 
keep that as it is.

...

>> +       mipi_dsi_dcs_write_buffer_multi(&dsi_ctx, b2, ARRAY_SIZE(b2));
>> +       mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x55, 0x00);
> 
> 0x55 is MIPI_DCS_WRITE_POWER_SAVE in <video/mipi_display.h>

It's the only one that could be used from <video/mipi_display.h>.

Though "MIPI_DCS_WRITE_POWER_SAVE, 0x00" doesn't say much. In the 
downstream driver there are four levels of ACL:
         0x55, 0x00 -> ACL off
         0x55, 0x01 -> default ACL 15 %
         0x55, 0x02 -> ACL 30 %, also corresponds to the "ACL on" command
         0x55, 0x03 -> doesn't seem to be used

https://github.com/msm8916-mainline/linux-downstream/blob/GT-I9195I/drivers/video/msm/mdss/samsung/S6E88A0_AMS427AP24/dsi_panel_S6E88A0_AMS427AP24_qhd_octa_video.dtsi#L275-L281

I would prefer to stay at 0x55 and add comment "acl off". Embedded in a 
block of other DCS commands with plain command register values and 
single line comments appended, as proposed in my reply on patch 3, it 
looks more readable and descriptive in the context of the other commands.

Kind regards,
Jakob

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH v3 5/5] drm/panel: samsung-s6e88a0-ams427ap24: Add flip option
  2024-10-25 19:32   ` Linus Walleij
@ 2024-10-26 11:13     ` Jakob Hauser
  0 siblings, 0 replies; 14+ messages in thread
From: Jakob Hauser @ 2024-10-26 11:13 UTC (permalink / raw)
  To: Linus Walleij
  Cc: Neil Armstrong, Jessica Zhang, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Thierry Reding, Laurent Pinchart, Andrzej Hajda,
	dri-devel, devicetree, linux-kernel, ~postmarketos/upstreaming

Hi Linus,

On 25.10.24 21:32, Linus Walleij wrote:
...
> On Thu, Oct 24, 2024 at 5:18 AM Jakob Hauser <jahau@rocketmail.com> wrote:
> 
>> The way of implementing a flip option follows the existing
>> panel-samsung-s6e8aa0.c [1][2][3].
> 
> That driver is notoriously hard to read because it uses so much
> magic numbers so please don't copy that aspect of the driver.

Actually I used that same approach for the flip option. The 
implementation of flip looked very well to me. I wanted to state it as 
source in the commit message. I don't feel comfortable without declaring it.

> (...)
> 
>> +       if (ctx->flip_horizontal)
>> +               mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xcb, 0x0e);
> 
> #define S6E88A0_SET_FLIP 0xcb
> or something like this.

The 0xcb command register might be more a general panel control, not 
only serving panel flip. But I can't say for sure. Translating single 
commands to command register names becomes too arbitrary.

...

Kind regards,
Jakob

^ permalink raw reply	[flat|nested] 14+ messages in thread

end of thread, other threads:[~2024-10-26 11:43 UTC | newest]

Thread overview: 14+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2024-10-24  3:18 [PATCH v3 0/5] Add new panel driver Samsung S6E88A0-AMS427AP24 Jakob Hauser
2024-10-24  3:18 ` [PATCH v3 1/5] dt-bindings: display: panel: Move flip properties to panel-common Jakob Hauser
2024-10-25 16:25   ` Linus Walleij
2024-10-24  3:18 ` [PATCH v3 2/5] dt-bindings: display: panel: Add Samsung S6E88A0-AMS427AP24 Jakob Hauser
2024-10-25 16:24   ` Linus Walleij
2024-10-24  3:18 ` [PATCH v3 3/5] drm/panel: samsung-s6e88a0-ams427ap24: Add initial driver Jakob Hauser
2024-10-25 16:36   ` Linus Walleij
2024-10-26  8:51     ` Jakob Hauser
2024-10-24  3:18 ` [PATCH v3 4/5] drm/panel: samsung-s6e88a0-ams427ap24: Add brightness control Jakob Hauser
2024-10-25 19:27   ` Linus Walleij
2024-10-26 10:47     ` Jakob Hauser
2024-10-24  3:18 ` [PATCH v3 5/5] drm/panel: samsung-s6e88a0-ams427ap24: Add flip option Jakob Hauser
2024-10-25 19:32   ` Linus Walleij
2024-10-26 11:13     ` Jakob Hauser

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).