summaryrefslogtreecommitdiffstats
path: root/target/linux/bcm27xx/patches-6.1/950-1182-drm-panel-add-panel-dsi.patch
diff options
context:
space:
mode:
Diffstat (limited to 'target/linux/bcm27xx/patches-6.1/950-1182-drm-panel-add-panel-dsi.patch')
-rw-r--r--target/linux/bcm27xx/patches-6.1/950-1182-drm-panel-add-panel-dsi.patch176
1 files changed, 176 insertions, 0 deletions
diff --git a/target/linux/bcm27xx/patches-6.1/950-1182-drm-panel-add-panel-dsi.patch b/target/linux/bcm27xx/patches-6.1/950-1182-drm-panel-add-panel-dsi.patch
new file mode 100644
index 0000000000..d914ab6d04
--- /dev/null
+++ b/target/linux/bcm27xx/patches-6.1/950-1182-drm-panel-add-panel-dsi.patch
@@ -0,0 +1,176 @@
+From 0a0084b8621682ad96d001e798aa239b11a3cf00 Mon Sep 17 00:00:00 2001
+From: Timon Skerutsch <kernel@diodes-delight.com>
+Date: Mon, 13 Nov 2023 22:53:12 +0100
+Subject: [PATCH] drm/panel: add panel-dsi
+
+Equivalent to panel-dpi for configuring a simple DSI panel with
+device tree side timings and bus settings.
+Motiviation is the same as for panel-dpi of wanting to support
+new simple panels without needing to patch the kernel.
+
+Signed-off-by: Timon Skerutsch <kernel@diodes-delight.com>
+---
+ drivers/gpu/drm/panel/panel-simple.c | 123 ++++++++++++++++++++++++++-
+ 1 file changed, 122 insertions(+), 1 deletion(-)
+
+--- a/drivers/gpu/drm/panel/panel-simple.c
++++ b/drivers/gpu/drm/panel/panel-simple.c
+@@ -40,6 +40,7 @@
+ #include <drm/drm_edid.h>
+ #include <drm/drm_mipi_dsi.h>
+ #include <drm/drm_panel.h>
++#include <drm/drm_of.h>
+
+ /**
+ * struct panel_desc - Describes a simple panel.
+@@ -4660,6 +4661,9 @@ static const struct panel_desc_dsi osd10
+ .lanes = 4,
+ };
+
++// for panels using generic panel-dsi binding
++static struct panel_desc_dsi panel_dsi;
++
+ static const struct of_device_id dsi_of_match[] = {
+ {
+ .compatible = "auo,b080uan01",
+@@ -4683,14 +4687,118 @@ static const struct of_device_id dsi_of_
+ .compatible = "osddisplays,osd101t2045-53ts",
+ .data = &osd101t2045_53ts
+ }, {
++ /* Must be the last entry */
++ .compatible = "panel-dsi",
++ .data = &panel_dsi,
++ }, {
+ /* sentinel */
+ }
+ };
+ MODULE_DEVICE_TABLE(of, dsi_of_match);
+
++
++/* Checks for DSI panel definition in device-tree, analog to panel_dpi */
++static int panel_dsi_dt_probe(struct device *dev,
++ struct panel_desc_dsi *desc_dsi)
++{
++ struct panel_desc *desc;
++ struct display_timing *timing;
++ const struct device_node *np;
++ const char *dsi_color_format;
++ const char *dsi_mode_flags;
++ struct property *prop;
++ int dsi_lanes, ret;
++
++ np = dev->of_node;
++
++ desc = devm_kzalloc(dev, sizeof(*desc), GFP_KERNEL);
++ if (!desc)
++ return -ENOMEM;
++
++ timing = devm_kzalloc(dev, sizeof(*timing), GFP_KERNEL);
++ if (!timing)
++ return -ENOMEM;
++
++ ret = of_get_display_timing(np, "panel-timing", timing);
++ if (ret < 0) {
++ dev_err(dev, "%pOF: no panel-timing node found for \"panel-dsi\" binding\n",
++ np);
++ return ret;
++ }
++
++ desc->timings = timing;
++ desc->num_timings = 1;
++
++ of_property_read_u32(np, "width-mm", &desc->size.width);
++ of_property_read_u32(np, "height-mm", &desc->size.height);
++
++ dsi_lanes = drm_of_get_data_lanes_count_ep(np, 0, 0, 1, 4);
++
++ if (dsi_lanes < 0) {
++ dev_err(dev, "%pOF: no or too many data-lanes defined", np);
++ return dsi_lanes;
++ }
++
++ desc_dsi->lanes = dsi_lanes;
++
++ of_property_read_string(np, "dsi-color-format", &dsi_color_format);
++ if (!strcmp(dsi_color_format, "RGB888")) {
++ desc_dsi->format = MIPI_DSI_FMT_RGB888;
++ desc->bpc = 8;
++ } else if (!strcmp(dsi_color_format, "RGB565")) {
++ desc_dsi->format = MIPI_DSI_FMT_RGB565;
++ desc->bpc = 6;
++ } else if (!strcmp(dsi_color_format, "RGB666")) {
++ desc_dsi->format = MIPI_DSI_FMT_RGB666;
++ desc->bpc = 6;
++ } else if (!strcmp(dsi_color_format, "RGB666_PACKED")) {
++ desc_dsi->format = MIPI_DSI_FMT_RGB666_PACKED;
++ desc->bpc = 6;
++ } else {
++ dev_err(dev, "%pOF: no valid dsi-color-format defined", np);
++ return -EINVAL;
++ }
++
++
++ of_property_for_each_string(np, "mode", prop, dsi_mode_flags) {
++ if (!strcmp(dsi_mode_flags, "MODE_VIDEO"))
++ desc_dsi->flags |= MIPI_DSI_MODE_VIDEO;
++ else if (!strcmp(dsi_mode_flags, "MODE_VIDEO_BURST"))
++ desc_dsi->flags |= MIPI_DSI_MODE_VIDEO_BURST;
++ else if (!strcmp(dsi_mode_flags, "MODE_VIDEO_SYNC_PULSE"))
++ desc_dsi->flags |= MIPI_DSI_MODE_VIDEO_SYNC_PULSE;
++ else if (!strcmp(dsi_mode_flags, "MODE_VIDEO_AUTO_VERT"))
++ desc_dsi->flags |= MIPI_DSI_MODE_VIDEO_AUTO_VERT;
++ else if (!strcmp(dsi_mode_flags, "MODE_VIDEO_HSE"))
++ desc_dsi->flags |= MIPI_DSI_MODE_VIDEO_HSE;
++ else if (!strcmp(dsi_mode_flags, "MODE_VIDEO_NO_HFP"))
++ desc_dsi->flags |= MIPI_DSI_MODE_VIDEO_NO_HFP;
++ else if (!strcmp(dsi_mode_flags, "MODE_VIDEO_NO_HBP"))
++ desc_dsi->flags |= MIPI_DSI_MODE_VIDEO_NO_HBP;
++ else if (!strcmp(dsi_mode_flags, "MODE_VIDEO_NO_HSA"))
++ desc_dsi->flags |= MIPI_DSI_MODE_VIDEO_NO_HSA;
++ else if (!strcmp(dsi_mode_flags, "MODE_VSYNC_FLUSH"))
++ desc_dsi->flags |= MIPI_DSI_MODE_VSYNC_FLUSH;
++ else if (!strcmp(dsi_mode_flags, "MODE_NO_EOT_PACKET"))
++ desc_dsi->flags |= MIPI_DSI_MODE_NO_EOT_PACKET;
++ else if (!strcmp(dsi_mode_flags, "CLOCK_NON_CONTINUOUS"))
++ desc_dsi->flags |= MIPI_DSI_CLOCK_NON_CONTINUOUS;
++ else if (!strcmp(dsi_mode_flags, "MODE_LPM"))
++ desc_dsi->flags |= MIPI_DSI_MODE_LPM;
++ else if (!strcmp(dsi_mode_flags, "HS_PKT_END_ALIGNED"))
++ desc_dsi->flags |= MIPI_DSI_HS_PKT_END_ALIGNED;
++ }
++
++ desc->connector_type = DRM_MODE_CONNECTOR_DSI;
++ desc_dsi->desc = *desc;
++
++ return 0;
++}
++
+ static int panel_simple_dsi_probe(struct mipi_dsi_device *dsi)
+ {
+ const struct panel_desc_dsi *desc;
++ struct panel_desc_dsi *dt_desc;
+ const struct of_device_id *id;
+ int err;
+
+@@ -4698,7 +4806,20 @@ static int panel_simple_dsi_probe(struct
+ if (!id)
+ return -ENODEV;
+
+- desc = id->data;
++ if (id->data == &panel_dsi) {
++ /* Handle the generic panel-dsi binding */
++ dt_desc = devm_kzalloc(&dsi->dev, sizeof(*dt_desc), GFP_KERNEL);
++ if (!dt_desc)
++ return -ENOMEM;
++
++ err = panel_dsi_dt_probe(&dsi->dev, dt_desc);
++ if (err < 0)
++ return err;
++
++ desc = dt_desc;
++ } else {
++ desc = id->data;
++ }
+
+ err = panel_simple_probe(&dsi->dev, &desc->desc);
+ if (err < 0)