2024-04-07 23:54:08

by Dmitry Baryshkov

[permalink] [raw]
Subject: [PATCH v5 0/4] drm/panel: add support for LG SW43408 panel

The LG SW43408 panel is used on Google Pixel3 devices. For a long time
we could not submit the driver, as the panel was not coming up from the
reset. The panel seems to be picky about some of the delays during init
and it also uses non-standard payload for MIPI_DSI_COMPRESSION_MODE.

Signed-off-by: Dmitry Baryshkov <[email protected]>
---
Changes in v5:
- Mention 60 Hz in the commit message (Marijn)
- Fix the comment regarding the panel being DSC-only (Marijn)
- Link to v4: https://lore.kernel.org/r/[email protected]

Changes in v4:
- Fix order of mipi_dsi_compression_mode_ext() args (Marijn)
- Expanded kerneldoc coments for this function (Marijn)
- And added arguments validation (Marijn)
- In the panel driver send the COMPRESSION_MODE in LPM mode like it was
done originally
- Expanded the .clock maths to show the reason behind the value (Marijn)
- Moved the mode out of the match data (Marijn)
- Link to v3: https://lore.kernel.org/r/[email protected]

Changes in v3:
- Fixed return type of MIPI DSC functions
- Replaced mipi_dsi_compression_mode_raw() with
mipi_dsi_compression_mode_ext() (Marijn)
- Link to v2: https://lore.kernel.org/r/[email protected]

Changes in v2:
- Removed formatting char from schema (Krzysztof)
- Moved additionalProperties after required (Krzysztof)
- Added example to the schema (Krzysztof)
- Removed obsolete comment in the commit message (Marijn)
- Moved DSC params to the panel struct (Marijn)
- Changed dsc_en to be an array (Marijn)
- Added comment regiarding slice_width and slice_count (Marijn)
- Link to v1: https://lore.kernel.org/r/[email protected]

---
Dmitry Baryshkov (2):
drm/mipi-dsi: use correct return type for the DSC functions
drm/mipi-dsi: add mipi_dsi_compression_mode_ext()

Sumit Semwal (2):
dt-bindings: panel: Add LG SW43408 MIPI-DSI panel
drm: panel: Add LG sw43408 panel driver

.../bindings/display/panel/lg,sw43408.yaml | 62 ++++
MAINTAINERS | 8 +
drivers/gpu/drm/drm_mipi_dsi.c | 45 ++-
drivers/gpu/drm/panel/Kconfig | 11 +
drivers/gpu/drm/panel/Makefile | 1 +
drivers/gpu/drm/panel/panel-lg-sw43408.c | 323 +++++++++++++++++++++
include/drm/drm_mipi_dsi.h | 15 +-
7 files changed, 453 insertions(+), 12 deletions(-)
---
base-commit: a6bd6c9333397f5a0e2667d4d82fef8c970108f2
change-id: 20240330-lg-sw43408-panel-b552f411c53e

Best regards,
--
Dmitry Baryshkov <[email protected]>



2024-04-07 23:54:15

by Dmitry Baryshkov

[permalink] [raw]
Subject: [PATCH v5 1/4] dt-bindings: panel: Add LG SW43408 MIPI-DSI panel

From: Sumit Semwal <[email protected]>

LG SW43408 is 1080x2160, 4-lane MIPI-DSI panel present on Google Pixel 3
phones.

Signed-off-by: Vinod Koul <[email protected]>
Signed-off-by: Sumit Semwal <[email protected]>
[caleb: convert to yaml]
Signed-off-by: Caleb Connolly <[email protected]>
Reviewed-by: Krzysztof Kozlowski <[email protected]>
Signed-off-by: Dmitry Baryshkov <[email protected]>
---
.../bindings/display/panel/lg,sw43408.yaml | 62 ++++++++++++++++++++++
1 file changed, 62 insertions(+)

diff --git a/Documentation/devicetree/bindings/display/panel/lg,sw43408.yaml b/Documentation/devicetree/bindings/display/panel/lg,sw43408.yaml
new file mode 100644
index 000000000000..1e08648f5bc7
--- /dev/null
+++ b/Documentation/devicetree/bindings/display/panel/lg,sw43408.yaml
@@ -0,0 +1,62 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/display/panel/lg,sw43408.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: LG SW43408 1080x2160 DSI panel
+
+maintainers:
+ - Caleb Connolly <[email protected]>
+
+description:
+ This panel is used on the Pixel 3, it is a 60hz OLED panel which
+ required DSC (Display Stream Compression) and has rounded corners.
+
+allOf:
+ - $ref: panel-common.yaml#
+
+properties:
+ compatible:
+ items:
+ - const: lg,sw43408
+
+ reg: true
+ port: true
+ vddi-supply: true
+ vpnl-supply: true
+ reset-gpios: true
+
+required:
+ - compatible
+ - vddi-supply
+ - vpnl-supply
+ - reset-gpios
+
+additionalProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/gpio/gpio.h>
+
+ dsi {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ panel@0 {
+ compatible = "lg,sw43408";
+ reg = <0>;
+
+ vddi-supply = <&vreg_l14a_1p88>;
+ vpnl-supply = <&vreg_l28a_3p0>;
+
+ reset-gpios = <&tlmm 6 GPIO_ACTIVE_LOW>;
+
+ port {
+ endpoint {
+ remote-endpoint = <&mdss_dsi0_out>;
+ };
+ };
+ };
+ };
+...

--
2.39.2


2024-04-07 23:54:28

by Dmitry Baryshkov

[permalink] [raw]
Subject: [PATCH v5 3/4] drm/mipi-dsi: add mipi_dsi_compression_mode_ext()

Add the extended version of mipi_dsi_compression_mode(). It provides
a way to specify the algorithm and PPS selector.

Signed-off-by: Dmitry Baryshkov <[email protected]>
---
drivers/gpu/drm/drm_mipi_dsi.c | 41 ++++++++++++++++++++++++++++++++++-------
include/drm/drm_mipi_dsi.h | 9 +++++++++
2 files changed, 43 insertions(+), 7 deletions(-)

diff --git a/drivers/gpu/drm/drm_mipi_dsi.c b/drivers/gpu/drm/drm_mipi_dsi.c
index 9874ff6d4718..795001bb7ff1 100644
--- a/drivers/gpu/drm/drm_mipi_dsi.c
+++ b/drivers/gpu/drm/drm_mipi_dsi.c
@@ -645,29 +645,56 @@ int mipi_dsi_set_maximum_return_packet_size(struct mipi_dsi_device *dsi,
EXPORT_SYMBOL(mipi_dsi_set_maximum_return_packet_size);

/**
- * mipi_dsi_compression_mode() - enable/disable DSC on the peripheral
+ * mipi_dsi_compression_mode_ext() - enable/disable DSC on the peripheral
* @dsi: DSI peripheral device
* @enable: Whether to enable or disable the DSC
+ * @algo: Selected compression algorithm
+ * @pps_selector: Select PPS from the table of pre-stored or uploaded PPS entries
*
- * Enable or disable Display Stream Compression on the peripheral using the
- * default Picture Parameter Set and VESA DSC 1.1 algorithm.
+ * Enable or disable Display Stream Compression on the peripheral.
*
* Return: 0 on success or a negative error code on failure.
*/
-int mipi_dsi_compression_mode(struct mipi_dsi_device *dsi, bool enable)
+int mipi_dsi_compression_mode_ext(struct mipi_dsi_device *dsi, bool enable,
+ enum mipi_dsi_compression_algo algo,
+ unsigned int pps_selector)
{
- /* Note: Needs updating for non-default PPS or algorithm */
- u8 tx[2] = { enable << 0, 0 };
+ u8 tx[2] = { };
struct mipi_dsi_msg msg = {
.channel = dsi->channel,
.type = MIPI_DSI_COMPRESSION_MODE,
.tx_len = sizeof(tx),
.tx_buf = tx,
};
- int ret = mipi_dsi_device_transfer(dsi, &msg);
+ int ret;
+
+ if (algo > 3 || pps_selector > 3)
+ return -EINVAL;
+
+ tx[0] = (enable << 0) |
+ (algo << 1) |
+ (pps_selector << 4);
+
+ ret = mipi_dsi_device_transfer(dsi, &msg);

return (ret < 0) ? ret : 0;
}
+EXPORT_SYMBOL(mipi_dsi_compression_mode_ext);
+
+/**
+ * mipi_dsi_compression_mode() - enable/disable DSC on the peripheral
+ * @dsi: DSI peripheral device
+ * @enable: Whether to enable or disable the DSC
+ *
+ * Enable or disable Display Stream Compression on the peripheral using the
+ * default Picture Parameter Set and VESA DSC 1.1 algorithm.
+ *
+ * Return: 0 on success or a negative error code on failure.
+ */
+int mipi_dsi_compression_mode(struct mipi_dsi_device *dsi, bool enable)
+{
+ return mipi_dsi_compression_mode_ext(dsi, enable, MIPI_DSI_COMPRESSION_DSC, 0);
+}
EXPORT_SYMBOL(mipi_dsi_compression_mode);

/**
diff --git a/include/drm/drm_mipi_dsi.h b/include/drm/drm_mipi_dsi.h
index 3011d33eccbd..82b1cc434ea3 100644
--- a/include/drm/drm_mipi_dsi.h
+++ b/include/drm/drm_mipi_dsi.h
@@ -226,6 +226,12 @@ static inline int mipi_dsi_pixel_format_to_bpp(enum mipi_dsi_pixel_format fmt)
return -EINVAL;
}

+enum mipi_dsi_compression_algo {
+ MIPI_DSI_COMPRESSION_DSC = 0,
+ MIPI_DSI_COMPRESSION_VENDOR = 3,
+ /* other two values are reserved, DSI 1.3 */
+};
+
struct mipi_dsi_device *
mipi_dsi_device_register_full(struct mipi_dsi_host *host,
const struct mipi_dsi_device_info *info);
@@ -242,6 +248,9 @@ int mipi_dsi_turn_on_peripheral(struct mipi_dsi_device *dsi);
int mipi_dsi_set_maximum_return_packet_size(struct mipi_dsi_device *dsi,
u16 value);
int mipi_dsi_compression_mode(struct mipi_dsi_device *dsi, bool enable);
+int mipi_dsi_compression_mode_ext(struct mipi_dsi_device *dsi, bool enable,
+ enum mipi_dsi_compression_algo algo,
+ unsigned int pps_selector);
int mipi_dsi_picture_parameter_set(struct mipi_dsi_device *dsi,
const struct drm_dsc_picture_parameter_set *pps);


--
2.39.2


2024-04-07 23:54:57

by Dmitry Baryshkov

[permalink] [raw]
Subject: [PATCH v5 2/4] drm/mipi-dsi: use correct return type for the DSC functions

The functions mipi_dsi_compression_mode() and
mipi_dsi_picture_parameter_set() return 0-or-error rather than a buffer
size. Follow example of other similar MIPI DSI functions and use int
return type instead of size_t.

Fixes: f4dea1aaa9a1 ("drm/dsi: add helpers for DSI compression mode and PPS packets")
Reviewed-by: Marijn Suijten <[email protected]>
Signed-off-by: Dmitry Baryshkov <[email protected]>
---
drivers/gpu/drm/drm_mipi_dsi.c | 6 +++---
include/drm/drm_mipi_dsi.h | 6 +++---
2 files changed, 6 insertions(+), 6 deletions(-)

diff --git a/drivers/gpu/drm/drm_mipi_dsi.c b/drivers/gpu/drm/drm_mipi_dsi.c
index ef6e416522f8..9874ff6d4718 100644
--- a/drivers/gpu/drm/drm_mipi_dsi.c
+++ b/drivers/gpu/drm/drm_mipi_dsi.c
@@ -654,7 +654,7 @@ EXPORT_SYMBOL(mipi_dsi_set_maximum_return_packet_size);
*
* Return: 0 on success or a negative error code on failure.
*/
-ssize_t mipi_dsi_compression_mode(struct mipi_dsi_device *dsi, bool enable)
+int mipi_dsi_compression_mode(struct mipi_dsi_device *dsi, bool enable)
{
/* Note: Needs updating for non-default PPS or algorithm */
u8 tx[2] = { enable << 0, 0 };
@@ -679,8 +679,8 @@ EXPORT_SYMBOL(mipi_dsi_compression_mode);
*
* Return: 0 on success or a negative error code on failure.
*/
-ssize_t mipi_dsi_picture_parameter_set(struct mipi_dsi_device *dsi,
- const struct drm_dsc_picture_parameter_set *pps)
+int mipi_dsi_picture_parameter_set(struct mipi_dsi_device *dsi,
+ const struct drm_dsc_picture_parameter_set *pps)
{
struct mipi_dsi_msg msg = {
.channel = dsi->channel,
diff --git a/include/drm/drm_mipi_dsi.h b/include/drm/drm_mipi_dsi.h
index c0aec0d4d664..3011d33eccbd 100644
--- a/include/drm/drm_mipi_dsi.h
+++ b/include/drm/drm_mipi_dsi.h
@@ -241,9 +241,9 @@ int mipi_dsi_shutdown_peripheral(struct mipi_dsi_device *dsi);
int mipi_dsi_turn_on_peripheral(struct mipi_dsi_device *dsi);
int mipi_dsi_set_maximum_return_packet_size(struct mipi_dsi_device *dsi,
u16 value);
-ssize_t mipi_dsi_compression_mode(struct mipi_dsi_device *dsi, bool enable);
-ssize_t mipi_dsi_picture_parameter_set(struct mipi_dsi_device *dsi,
- const struct drm_dsc_picture_parameter_set *pps);
+int mipi_dsi_compression_mode(struct mipi_dsi_device *dsi, bool enable);
+int mipi_dsi_picture_parameter_set(struct mipi_dsi_device *dsi,
+ const struct drm_dsc_picture_parameter_set *pps);

ssize_t mipi_dsi_generic_write(struct mipi_dsi_device *dsi, const void *payload,
size_t size);

--
2.39.2


2024-04-07 23:55:29

by Dmitry Baryshkov

[permalink] [raw]
Subject: [PATCH v5 4/4] drm: panel: Add LG sw43408 panel driver

From: Sumit Semwal <[email protected]>

LG SW43408 is 1080x2160@60Hz, 4-lane MIPI-DSI panel, used in some
Google Pixel-3 phones.

Signed-off-by: Sumit Semwal <[email protected]>
[vinod: Add DSC support]
Signed-off-by: Vinod Koul <[email protected]>
[caleb: cleanup and support turning off the panel]
Signed-off-by: Caleb Connolly <[email protected]>
[DB: partially rewrote the driver and fixed DSC programming]
Reviewed-by: Marijn Suijten <[email protected]>
Signed-off-by: Dmitry Baryshkov <[email protected]>
---
MAINTAINERS | 8 +
drivers/gpu/drm/panel/Kconfig | 11 ++
drivers/gpu/drm/panel/Makefile | 1 +
drivers/gpu/drm/panel/panel-lg-sw43408.c | 323 +++++++++++++++++++++++++++++++
4 files changed, 343 insertions(+)

diff --git a/MAINTAINERS b/MAINTAINERS
index d36c19c1bf81..4cc43c16e07e 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -6789,6 +6789,14 @@ S: Maintained
F: Documentation/devicetree/bindings/display/panel/jadard,jd9365da-h3.yaml
F: drivers/gpu/drm/panel/panel-jadard-jd9365da-h3.c

+DRM DRIVER FOR LG SW43408 PANELS
+M: Sumit Semwal <[email protected]>
+M: Caleb Connolly <[email protected]>
+S: Maintained
+T: git git://anongit.freedesktop.org/drm/drm-misc
+F: Documentation/devicetree/bindings/display/panel/lg,sw43408.yaml
+F: drivers/gpu/drm/panel/panel-lg-sw43408.c
+
DRM DRIVER FOR LOGICVC DISPLAY CONTROLLER
M: Paul Kocialkowski <[email protected]>
S: Supported
diff --git a/drivers/gpu/drm/panel/Kconfig b/drivers/gpu/drm/panel/Kconfig
index 6dc451f58a3e..4dc435fd9a44 100644
--- a/drivers/gpu/drm/panel/Kconfig
+++ b/drivers/gpu/drm/panel/Kconfig
@@ -335,6 +335,17 @@ config DRM_PANEL_LG_LG4573
Say Y here if you want to enable support for LG4573 RGB panel.
To compile this driver as a module, choose M here.

+config DRM_PANEL_LG_SW43408
+ tristate "LG SW43408 panel"
+ depends on OF
+ depends on DRM_MIPI_DSI
+ depends on BACKLIGHT_CLASS_DEVICE
+ help
+ Say Y here if you want to enable support for LG sw43408 panel.
+ The panel has a 1080x2160@60Hz resolution and uses 24 bit RGB per
+ pixel. It provides a MIPI DSI interface to the host and has a
+ built-in LED backlight.
+
config DRM_PANEL_MAGNACHIP_D53E6EA8966
tristate "Magnachip D53E6EA8966 DSI panel"
depends on OF && SPI
diff --git a/drivers/gpu/drm/panel/Makefile b/drivers/gpu/drm/panel/Makefile
index 24a02655d726..0b40b010e8e7 100644
--- a/drivers/gpu/drm/panel/Makefile
+++ b/drivers/gpu/drm/panel/Makefile
@@ -34,6 +34,7 @@ obj-$(CONFIG_DRM_PANEL_LEADTEK_LTK050H3146W) += panel-leadtek-ltk050h3146w.o
obj-$(CONFIG_DRM_PANEL_LEADTEK_LTK500HD1829) += panel-leadtek-ltk500hd1829.o
obj-$(CONFIG_DRM_PANEL_LG_LB035Q02) += panel-lg-lb035q02.o
obj-$(CONFIG_DRM_PANEL_LG_LG4573) += panel-lg-lg4573.o
+obj-$(CONFIG_DRM_PANEL_LG_SW43408) += panel-lg-sw43408.o
obj-$(CONFIG_DRM_PANEL_MAGNACHIP_D53E6EA8966) += panel-magnachip-d53e6ea8966.o
obj-$(CONFIG_DRM_PANEL_NEC_NL8048HL11) += panel-nec-nl8048hl11.o
obj-$(CONFIG_DRM_PANEL_NEWVISION_NV3051D) += panel-newvision-nv3051d.o
diff --git a/drivers/gpu/drm/panel/panel-lg-sw43408.c b/drivers/gpu/drm/panel/panel-lg-sw43408.c
new file mode 100644
index 000000000000..bd9706ae7615
--- /dev/null
+++ b/drivers/gpu/drm/panel/panel-lg-sw43408.c
@@ -0,0 +1,323 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2019-2024 Linaro Ltd
+ * Author: Sumit Semwal <[email protected]>
+ * Dmitry Baryshkov <[email protected]>
+ */
+
+#include <linux/backlight.h>
+#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_panel.h>
+#include <drm/drm_probe_helper.h>
+#include <drm/display/drm_dsc.h>
+#include <drm/display/drm_dsc_helper.h>
+
+#define NUM_SUPPLIES 2
+
+struct sw43408_panel {
+ struct drm_panel base;
+ struct mipi_dsi_device *link;
+
+ struct regulator_bulk_data supplies[NUM_SUPPLIES];
+
+ struct gpio_desc *reset_gpio;
+
+ struct drm_dsc_config dsc;
+};
+
+static inline struct sw43408_panel *to_panel_info(struct drm_panel *panel)
+{
+ return container_of(panel, struct sw43408_panel, base);
+}
+
+static int sw43408_unprepare(struct drm_panel *panel)
+{
+ struct sw43408_panel *ctx = to_panel_info(panel);
+ int ret;
+
+ ret = mipi_dsi_dcs_set_display_off(ctx->link);
+ if (ret < 0)
+ dev_err(panel->dev, "set_display_off cmd failed ret = %d\n", ret);
+
+ ret = mipi_dsi_dcs_enter_sleep_mode(ctx->link);
+ if (ret < 0)
+ dev_err(panel->dev, "enter_sleep cmd failed ret = %d\n", ret);
+
+ msleep(100);
+
+ gpiod_set_value(ctx->reset_gpio, 1);
+
+ return regulator_bulk_disable(ARRAY_SIZE(ctx->supplies), ctx->supplies);
+}
+
+static int sw43408_program(struct drm_panel *panel)
+{
+ struct sw43408_panel *ctx = to_panel_info(panel);
+ struct drm_dsc_picture_parameter_set pps;
+
+ mipi_dsi_dcs_write_seq(ctx->link, MIPI_DCS_SET_GAMMA_CURVE, 0x02);
+
+ mipi_dsi_dcs_set_tear_on(ctx->link, MIPI_DSI_DCS_TEAR_MODE_VBLANK);
+
+ mipi_dsi_dcs_write_seq(ctx->link, 0x53, 0x0c, 0x30);
+ mipi_dsi_dcs_write_seq(ctx->link, 0x55, 0x00, 0x70, 0xdf, 0x00, 0x70, 0xdf);
+ mipi_dsi_dcs_write_seq(ctx->link, 0xf7, 0x01, 0x49, 0x0c);
+
+ mipi_dsi_dcs_exit_sleep_mode(ctx->link);
+
+ msleep(135);
+
+ /* COMPRESSION_MODE moved after setting the PPS */
+
+ mipi_dsi_dcs_write_seq(ctx->link, 0xb0, 0xac);
+ mipi_dsi_dcs_write_seq(ctx->link, 0xe5,
+ 0x00, 0x3a, 0x00, 0x3a, 0x00, 0x0e, 0x10);
+ mipi_dsi_dcs_write_seq(ctx->link, 0xb5,
+ 0x75, 0x60, 0x2d, 0x5d, 0x80, 0x00, 0x0a, 0x0b,
+ 0x00, 0x05, 0x0b, 0x00, 0x80, 0x0d, 0x0e, 0x40,
+ 0x00, 0x0c, 0x00, 0x16, 0x00, 0xb8, 0x00, 0x80,
+ 0x0d, 0x0e, 0x40, 0x00, 0x0c, 0x00, 0x16, 0x00,
+ 0xb8, 0x00, 0x81, 0x00, 0x03, 0x03, 0x03, 0x01,
+ 0x01);
+ msleep(85);
+ mipi_dsi_dcs_write_seq(ctx->link, 0xcd,
+ 0x00, 0x00, 0x00, 0x19, 0x19, 0x19, 0x19, 0x19,
+ 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19,
+ 0x16, 0x16);
+ mipi_dsi_dcs_write_seq(ctx->link, 0xcb, 0x80, 0x5c, 0x07, 0x03, 0x28);
+ mipi_dsi_dcs_write_seq(ctx->link, 0xc0, 0x02, 0x02, 0x0f);
+ mipi_dsi_dcs_write_seq(ctx->link, 0x55, 0x04, 0x61, 0xdb, 0x04, 0x70, 0xdb);
+ mipi_dsi_dcs_write_seq(ctx->link, 0xb0, 0xca);
+
+ mipi_dsi_dcs_set_display_on(ctx->link);
+
+ msleep(50);
+
+ ctx->link->mode_flags &= ~MIPI_DSI_MODE_LPM;
+
+ drm_dsc_pps_payload_pack(&pps, ctx->link->dsc);
+ mipi_dsi_picture_parameter_set(ctx->link, &pps);
+
+ ctx->link->mode_flags |= MIPI_DSI_MODE_LPM;
+
+ /*
+ * This panel uses PPS selectors with offset:
+ * PPS 1 if pps_identifier is 0
+ * PPS 2 if pps_identifier is 1
+ */
+ mipi_dsi_compression_mode_ext(ctx->link, true,
+ MIPI_DSI_COMPRESSION_DSC, 1);
+
+
+ return 0;
+}
+
+static int sw43408_prepare(struct drm_panel *panel)
+{
+ struct sw43408_panel *ctx = to_panel_info(panel);
+ int ret;
+
+ ret = regulator_bulk_enable(ARRAY_SIZE(ctx->supplies), ctx->supplies);
+ if (ret < 0)
+ return ret;
+
+ usleep_range(5000, 6000);
+
+ gpiod_set_value(ctx->reset_gpio, 0);
+ usleep_range(9000, 10000);
+ gpiod_set_value(ctx->reset_gpio, 1);
+ usleep_range(1000, 2000);
+ gpiod_set_value(ctx->reset_gpio, 0);
+ usleep_range(9000, 10000);
+
+ ret = sw43408_program(panel);
+ if (ret)
+ goto poweroff;
+
+ return 0;
+
+poweroff:
+ gpiod_set_value(ctx->reset_gpio, 1);
+ regulator_bulk_disable(ARRAY_SIZE(ctx->supplies), ctx->supplies);
+ return ret;
+}
+
+static const struct drm_display_mode sw43408_mode = {
+ .clock = (1080 + 20 + 32 + 20) * (2160 + 20 + 4 + 20) * 60 / 1000,
+
+ .hdisplay = 1080,
+ .hsync_start = 1080 + 20,
+ .hsync_end = 1080 + 20 + 32,
+ .htotal = 1080 + 20 + 32 + 20,
+
+ .vdisplay = 2160,
+ .vsync_start = 2160 + 20,
+ .vsync_end = 2160 + 20 + 4,
+ .vtotal = 2160 + 20 + 4 + 20,
+
+ .width_mm = 62,
+ .height_mm = 124,
+
+ .type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED,
+};
+
+static int sw43408_get_modes(struct drm_panel *panel,
+ struct drm_connector *connector)
+{
+ return drm_connector_helper_get_modes_fixed(connector, &sw43408_mode);
+}
+
+static int sw43408_backlight_update_status(struct backlight_device *bl)
+{
+ struct mipi_dsi_device *dsi = bl_get_data(bl);
+ uint16_t brightness = backlight_get_brightness(bl);
+
+ return mipi_dsi_dcs_set_display_brightness_large(dsi, brightness);
+}
+
+const struct backlight_ops sw43408_backlight_ops = {
+ .update_status = sw43408_backlight_update_status,
+};
+
+static int sw43408_backlight_init(struct sw43408_panel *ctx)
+{
+ struct device *dev = &ctx->link->dev;
+ const struct backlight_properties props = {
+ .type = BACKLIGHT_PLATFORM,
+ .brightness = 255,
+ .max_brightness = 255,
+ };
+
+ ctx->base.backlight = devm_backlight_device_register(dev, dev_name(dev), dev,
+ ctx->link,
+ &sw43408_backlight_ops,
+ &props);
+
+ if (IS_ERR(ctx->base.backlight))
+ return dev_err_probe(dev, PTR_ERR(ctx->base.backlight),
+ "Failed to create backlight\n");
+
+ return 0;
+}
+
+static const struct drm_panel_funcs sw43408_funcs = {
+ .unprepare = sw43408_unprepare,
+ .prepare = sw43408_prepare,
+ .get_modes = sw43408_get_modes,
+};
+
+static const struct of_device_id sw43408_of_match[] = {
+ { .compatible = "lg,sw43408", },
+ { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, sw43408_of_match);
+
+static int sw43408_add(struct sw43408_panel *ctx)
+{
+ struct device *dev = &ctx->link->dev;
+ int ret;
+
+ ctx->supplies[0].supply = "vddi"; /* 1.88 V */
+ ctx->supplies[0].init_load_uA = 62000;
+ ctx->supplies[1].supply = "vpnl"; /* 3.0 V */
+ ctx->supplies[1].init_load_uA = 857000;
+
+ ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(ctx->supplies),
+ ctx->supplies);
+ if (ret < 0)
+ return ret;
+
+ ctx->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_LOW);
+ if (IS_ERR(ctx->reset_gpio)) {
+ dev_err(dev, "cannot get reset gpio %ld\n",
+ PTR_ERR(ctx->reset_gpio));
+ return PTR_ERR(ctx->reset_gpio);
+ }
+
+ ret = sw43408_backlight_init(ctx);
+ if (ret < 0)
+ return ret;
+
+ ctx->base.prepare_prev_first = true;
+
+ drm_panel_init(&ctx->base, dev, &sw43408_funcs, DRM_MODE_CONNECTOR_DSI);
+
+ drm_panel_add(&ctx->base);
+ return ret;
+}
+
+static int sw43408_probe(struct mipi_dsi_device *dsi)
+{
+ struct sw43408_panel *ctx;
+ int ret;
+
+ ctx = devm_kzalloc(&dsi->dev, sizeof(*ctx), GFP_KERNEL);
+ if (!ctx)
+ return -ENOMEM;
+
+ dsi->mode_flags = MIPI_DSI_MODE_LPM;
+ dsi->format = MIPI_DSI_FMT_RGB888;
+ dsi->lanes = 4;
+
+ ctx->link = dsi;
+ mipi_dsi_set_drvdata(dsi, ctx);
+
+ ret = sw43408_add(ctx);
+ if (ret < 0)
+ return ret;
+
+ /* The panel works only in the DSC mode. Set DSC params. */
+ ctx->dsc.dsc_version_major = 0x1;
+ ctx->dsc.dsc_version_minor = 0x1;
+
+ /* slice_count * slice_width == width */
+ ctx->dsc.slice_height = 16;
+ ctx->dsc.slice_width = 540;
+ ctx->dsc.slice_count = 2;
+ ctx->dsc.bits_per_component = 8;
+ ctx->dsc.bits_per_pixel = 8 << 4;
+ ctx->dsc.block_pred_enable = true;
+
+ dsi->dsc = &ctx->dsc;
+
+ return mipi_dsi_attach(dsi);
+}
+
+static void sw43408_remove(struct mipi_dsi_device *dsi)
+{
+ struct sw43408_panel *ctx = mipi_dsi_get_drvdata(dsi);
+ int ret;
+
+ ret = sw43408_unprepare(&ctx->base);
+ if (ret < 0)
+ dev_err(&dsi->dev, "failed to unprepare panel: %d\n",
+ 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->base);
+}
+
+static struct mipi_dsi_driver sw43408_driver = {
+ .driver = {
+ .name = "panel-lg-sw43408",
+ .of_match_table = sw43408_of_match,
+ },
+ .probe = sw43408_probe,
+ .remove = sw43408_remove,
+};
+module_mipi_dsi_driver(sw43408_driver);
+
+MODULE_AUTHOR("Sumit Semwal <[email protected]>");
+MODULE_DESCRIPTION("LG SW436408 MIPI-DSI LED panel");
+MODULE_LICENSE("GPL");

--
2.39.2


2024-04-09 17:47:13

by Jessica Zhang

[permalink] [raw]
Subject: Re: [PATCH v5 2/4] drm/mipi-dsi: use correct return type for the DSC functions



On 4/7/2024 4:53 PM, Dmitry Baryshkov wrote:
> The functions mipi_dsi_compression_mode() and
> mipi_dsi_picture_parameter_set() return 0-or-error rather than a buffer
> size. Follow example of other similar MIPI DSI functions and use int
> return type instead of size_t.

Hi Dmitry,

Reviewed-by: Jessica Zhang <[email protected]>

Thanks,

Jessica Zhang

>
> Fixes: f4dea1aaa9a1 ("drm/dsi: add helpers for DSI compression mode and PPS packets")
> Reviewed-by: Marijn Suijten <[email protected]>
> Signed-off-by: Dmitry Baryshkov <[email protected]>
> ---
> drivers/gpu/drm/drm_mipi_dsi.c | 6 +++---
> include/drm/drm_mipi_dsi.h | 6 +++---
> 2 files changed, 6 insertions(+), 6 deletions(-)
>
> diff --git a/drivers/gpu/drm/drm_mipi_dsi.c b/drivers/gpu/drm/drm_mipi_dsi.c
> index ef6e416522f8..9874ff6d4718 100644
> --- a/drivers/gpu/drm/drm_mipi_dsi.c
> +++ b/drivers/gpu/drm/drm_mipi_dsi.c
> @@ -654,7 +654,7 @@ EXPORT_SYMBOL(mipi_dsi_set_maximum_return_packet_size);
> *
> * Return: 0 on success or a negative error code on failure.
> */
> -ssize_t mipi_dsi_compression_mode(struct mipi_dsi_device *dsi, bool enable)
> +int mipi_dsi_compression_mode(struct mipi_dsi_device *dsi, bool enable)
> {
> /* Note: Needs updating for non-default PPS or algorithm */
> u8 tx[2] = { enable << 0, 0 };
> @@ -679,8 +679,8 @@ EXPORT_SYMBOL(mipi_dsi_compression_mode);
> *
> * Return: 0 on success or a negative error code on failure.
> */
> -ssize_t mipi_dsi_picture_parameter_set(struct mipi_dsi_device *dsi,
> - const struct drm_dsc_picture_parameter_set *pps)
> +int mipi_dsi_picture_parameter_set(struct mipi_dsi_device *dsi,
> + const struct drm_dsc_picture_parameter_set *pps)
> {
> struct mipi_dsi_msg msg = {
> .channel = dsi->channel,
> diff --git a/include/drm/drm_mipi_dsi.h b/include/drm/drm_mipi_dsi.h
> index c0aec0d4d664..3011d33eccbd 100644
> --- a/include/drm/drm_mipi_dsi.h
> +++ b/include/drm/drm_mipi_dsi.h
> @@ -241,9 +241,9 @@ int mipi_dsi_shutdown_peripheral(struct mipi_dsi_device *dsi);
> int mipi_dsi_turn_on_peripheral(struct mipi_dsi_device *dsi);
> int mipi_dsi_set_maximum_return_packet_size(struct mipi_dsi_device *dsi,
> u16 value);
> -ssize_t mipi_dsi_compression_mode(struct mipi_dsi_device *dsi, bool enable);
> -ssize_t mipi_dsi_picture_parameter_set(struct mipi_dsi_device *dsi,
> - const struct drm_dsc_picture_parameter_set *pps);
> +int mipi_dsi_compression_mode(struct mipi_dsi_device *dsi, bool enable);
> +int mipi_dsi_picture_parameter_set(struct mipi_dsi_device *dsi,
> + const struct drm_dsc_picture_parameter_set *pps);
>
> ssize_t mipi_dsi_generic_write(struct mipi_dsi_device *dsi, const void *payload,
> size_t size);
>
> --
> 2.39.2
>

2024-04-13 21:30:25

by Marijn Suijten

[permalink] [raw]
Subject: Re: [PATCH v5 3/4] drm/mipi-dsi: add mipi_dsi_compression_mode_ext()

On 2024-04-08 02:53:52, Dmitry Baryshkov wrote:
> Add the extended version of mipi_dsi_compression_mode(). It provides
> a way to specify the algorithm and PPS selector.
>
> Signed-off-by: Dmitry Baryshkov <[email protected]>

Reviewed-by: Marijn Suijten <[email protected]>

Something doesn't stick with me on the _ext() naming, but I don't have something
better to propose.

- Marijn

> ---
> drivers/gpu/drm/drm_mipi_dsi.c | 41 ++++++++++++++++++++++++++++++++++-------
> include/drm/drm_mipi_dsi.h | 9 +++++++++
> 2 files changed, 43 insertions(+), 7 deletions(-)
>
> diff --git a/drivers/gpu/drm/drm_mipi_dsi.c b/drivers/gpu/drm/drm_mipi_dsi.c
> index 9874ff6d4718..795001bb7ff1 100644
> --- a/drivers/gpu/drm/drm_mipi_dsi.c
> +++ b/drivers/gpu/drm/drm_mipi_dsi.c
> @@ -645,29 +645,56 @@ int mipi_dsi_set_maximum_return_packet_size(struct mipi_dsi_device *dsi,
> EXPORT_SYMBOL(mipi_dsi_set_maximum_return_packet_size);
>
> /**
> - * mipi_dsi_compression_mode() - enable/disable DSC on the peripheral
> + * mipi_dsi_compression_mode_ext() - enable/disable DSC on the peripheral
> * @dsi: DSI peripheral device
> * @enable: Whether to enable or disable the DSC
> + * @algo: Selected compression algorithm
> + * @pps_selector: Select PPS from the table of pre-stored or uploaded PPS entries
> *
> - * Enable or disable Display Stream Compression on the peripheral using the
> - * default Picture Parameter Set and VESA DSC 1.1 algorithm.
> + * Enable or disable Display Stream Compression on the peripheral.
> *
> * Return: 0 on success or a negative error code on failure.
> */
> -int mipi_dsi_compression_mode(struct mipi_dsi_device *dsi, bool enable)
> +int mipi_dsi_compression_mode_ext(struct mipi_dsi_device *dsi, bool enable,
> + enum mipi_dsi_compression_algo algo,
> + unsigned int pps_selector)
> {
> - /* Note: Needs updating for non-default PPS or algorithm */
> - u8 tx[2] = { enable << 0, 0 };
> + u8 tx[2] = { };
> struct mipi_dsi_msg msg = {
> .channel = dsi->channel,
> .type = MIPI_DSI_COMPRESSION_MODE,
> .tx_len = sizeof(tx),
> .tx_buf = tx,
> };
> - int ret = mipi_dsi_device_transfer(dsi, &msg);
> + int ret;
> +
> + if (algo > 3 || pps_selector > 3)
> + return -EINVAL;
> +
> + tx[0] = (enable << 0) |
> + (algo << 1) |
> + (pps_selector << 4);
> +
> + ret = mipi_dsi_device_transfer(dsi, &msg);
>
> return (ret < 0) ? ret : 0;
> }
> +EXPORT_SYMBOL(mipi_dsi_compression_mode_ext);
> +
> +/**
> + * mipi_dsi_compression_mode() - enable/disable DSC on the peripheral
> + * @dsi: DSI peripheral device
> + * @enable: Whether to enable or disable the DSC
> + *
> + * Enable or disable Display Stream Compression on the peripheral using the
> + * default Picture Parameter Set and VESA DSC 1.1 algorithm.
> + *
> + * Return: 0 on success or a negative error code on failure.
> + */
> +int mipi_dsi_compression_mode(struct mipi_dsi_device *dsi, bool enable)
> +{
> + return mipi_dsi_compression_mode_ext(dsi, enable, MIPI_DSI_COMPRESSION_DSC, 0);
> +}
> EXPORT_SYMBOL(mipi_dsi_compression_mode);
>
> /**
> diff --git a/include/drm/drm_mipi_dsi.h b/include/drm/drm_mipi_dsi.h
> index 3011d33eccbd..82b1cc434ea3 100644
> --- a/include/drm/drm_mipi_dsi.h
> +++ b/include/drm/drm_mipi_dsi.h
> @@ -226,6 +226,12 @@ static inline int mipi_dsi_pixel_format_to_bpp(enum mipi_dsi_pixel_format fmt)
> return -EINVAL;
> }
>
> +enum mipi_dsi_compression_algo {
> + MIPI_DSI_COMPRESSION_DSC = 0,
> + MIPI_DSI_COMPRESSION_VENDOR = 3,
> + /* other two values are reserved, DSI 1.3 */
> +};
> +
> struct mipi_dsi_device *
> mipi_dsi_device_register_full(struct mipi_dsi_host *host,
> const struct mipi_dsi_device_info *info);
> @@ -242,6 +248,9 @@ int mipi_dsi_turn_on_peripheral(struct mipi_dsi_device *dsi);
> int mipi_dsi_set_maximum_return_packet_size(struct mipi_dsi_device *dsi,
> u16 value);
> int mipi_dsi_compression_mode(struct mipi_dsi_device *dsi, bool enable);
> +int mipi_dsi_compression_mode_ext(struct mipi_dsi_device *dsi, bool enable,
> + enum mipi_dsi_compression_algo algo,
> + unsigned int pps_selector);
> int mipi_dsi_picture_parameter_set(struct mipi_dsi_device *dsi,
> const struct drm_dsc_picture_parameter_set *pps);
>
>
> --
> 2.39.2
>