1 From 0a0084b8621682ad96d001e798aa239b11a3cf00 Mon Sep 17 00:00:00 2001
2 From: Timon Skerutsch <kernel@diodes-delight.com>
3 Date: Mon, 13 Nov 2023 22:53:12 +0100
4 Subject: [PATCH] drm/panel: add panel-dsi
6 Equivalent to panel-dpi for configuring a simple DSI panel with
7 device tree side timings and bus settings.
8 Motiviation is the same as for panel-dpi of wanting to support
9 new simple panels without needing to patch the kernel.
11 Signed-off-by: Timon Skerutsch <kernel@diodes-delight.com>
13 drivers/gpu/drm/panel/panel-simple.c | 123 ++++++++++++++++++++++++++-
14 1 file changed, 122 insertions(+), 1 deletion(-)
16 --- a/drivers/gpu/drm/panel/panel-simple.c
17 +++ b/drivers/gpu/drm/panel/panel-simple.c
19 #include <drm/drm_edid.h>
20 #include <drm/drm_mipi_dsi.h>
21 #include <drm/drm_panel.h>
22 +#include <drm/drm_of.h>
25 * struct panel_desc - Describes a simple panel.
26 @@ -4660,6 +4661,9 @@ static const struct panel_desc_dsi osd10
30 +// for panels using generic panel-dsi binding
31 +static struct panel_desc_dsi panel_dsi;
33 static const struct of_device_id dsi_of_match[] = {
35 .compatible = "auo,b080uan01",
36 @@ -4683,14 +4687,118 @@ static const struct of_device_id dsi_of_
37 .compatible = "osddisplays,osd101t2045-53ts",
38 .data = &osd101t2045_53ts
40 + /* Must be the last entry */
41 + .compatible = "panel-dsi",
47 MODULE_DEVICE_TABLE(of, dsi_of_match);
50 +/* Checks for DSI panel definition in device-tree, analog to panel_dpi */
51 +static int panel_dsi_dt_probe(struct device *dev,
52 + struct panel_desc_dsi *desc_dsi)
54 + struct panel_desc *desc;
55 + struct display_timing *timing;
56 + const struct device_node *np;
57 + const char *dsi_color_format;
58 + const char *dsi_mode_flags;
59 + struct property *prop;
64 + desc = devm_kzalloc(dev, sizeof(*desc), GFP_KERNEL);
68 + timing = devm_kzalloc(dev, sizeof(*timing), GFP_KERNEL);
72 + ret = of_get_display_timing(np, "panel-timing", timing);
74 + dev_err(dev, "%pOF: no panel-timing node found for \"panel-dsi\" binding\n",
79 + desc->timings = timing;
80 + desc->num_timings = 1;
82 + of_property_read_u32(np, "width-mm", &desc->size.width);
83 + of_property_read_u32(np, "height-mm", &desc->size.height);
85 + dsi_lanes = drm_of_get_data_lanes_count_ep(np, 0, 0, 1, 4);
87 + if (dsi_lanes < 0) {
88 + dev_err(dev, "%pOF: no or too many data-lanes defined", np);
92 + desc_dsi->lanes = dsi_lanes;
94 + of_property_read_string(np, "dsi-color-format", &dsi_color_format);
95 + if (!strcmp(dsi_color_format, "RGB888")) {
96 + desc_dsi->format = MIPI_DSI_FMT_RGB888;
98 + } else if (!strcmp(dsi_color_format, "RGB565")) {
99 + desc_dsi->format = MIPI_DSI_FMT_RGB565;
101 + } else if (!strcmp(dsi_color_format, "RGB666")) {
102 + desc_dsi->format = MIPI_DSI_FMT_RGB666;
104 + } else if (!strcmp(dsi_color_format, "RGB666_PACKED")) {
105 + desc_dsi->format = MIPI_DSI_FMT_RGB666_PACKED;
108 + dev_err(dev, "%pOF: no valid dsi-color-format defined", np);
113 + of_property_for_each_string(np, "mode", prop, dsi_mode_flags) {
114 + if (!strcmp(dsi_mode_flags, "MODE_VIDEO"))
115 + desc_dsi->flags |= MIPI_DSI_MODE_VIDEO;
116 + else if (!strcmp(dsi_mode_flags, "MODE_VIDEO_BURST"))
117 + desc_dsi->flags |= MIPI_DSI_MODE_VIDEO_BURST;
118 + else if (!strcmp(dsi_mode_flags, "MODE_VIDEO_SYNC_PULSE"))
119 + desc_dsi->flags |= MIPI_DSI_MODE_VIDEO_SYNC_PULSE;
120 + else if (!strcmp(dsi_mode_flags, "MODE_VIDEO_AUTO_VERT"))
121 + desc_dsi->flags |= MIPI_DSI_MODE_VIDEO_AUTO_VERT;
122 + else if (!strcmp(dsi_mode_flags, "MODE_VIDEO_HSE"))
123 + desc_dsi->flags |= MIPI_DSI_MODE_VIDEO_HSE;
124 + else if (!strcmp(dsi_mode_flags, "MODE_VIDEO_NO_HFP"))
125 + desc_dsi->flags |= MIPI_DSI_MODE_VIDEO_NO_HFP;
126 + else if (!strcmp(dsi_mode_flags, "MODE_VIDEO_NO_HBP"))
127 + desc_dsi->flags |= MIPI_DSI_MODE_VIDEO_NO_HBP;
128 + else if (!strcmp(dsi_mode_flags, "MODE_VIDEO_NO_HSA"))
129 + desc_dsi->flags |= MIPI_DSI_MODE_VIDEO_NO_HSA;
130 + else if (!strcmp(dsi_mode_flags, "MODE_VSYNC_FLUSH"))
131 + desc_dsi->flags |= MIPI_DSI_MODE_VSYNC_FLUSH;
132 + else if (!strcmp(dsi_mode_flags, "MODE_NO_EOT_PACKET"))
133 + desc_dsi->flags |= MIPI_DSI_MODE_NO_EOT_PACKET;
134 + else if (!strcmp(dsi_mode_flags, "CLOCK_NON_CONTINUOUS"))
135 + desc_dsi->flags |= MIPI_DSI_CLOCK_NON_CONTINUOUS;
136 + else if (!strcmp(dsi_mode_flags, "MODE_LPM"))
137 + desc_dsi->flags |= MIPI_DSI_MODE_LPM;
138 + else if (!strcmp(dsi_mode_flags, "HS_PKT_END_ALIGNED"))
139 + desc_dsi->flags |= MIPI_DSI_HS_PKT_END_ALIGNED;
142 + desc->connector_type = DRM_MODE_CONNECTOR_DSI;
143 + desc_dsi->desc = *desc;
148 static int panel_simple_dsi_probe(struct mipi_dsi_device *dsi)
150 const struct panel_desc_dsi *desc;
151 + struct panel_desc_dsi *dt_desc;
152 const struct of_device_id *id;
155 @@ -4698,7 +4806,20 @@ static int panel_simple_dsi_probe(struct
160 + if (id->data == &panel_dsi) {
161 + /* Handle the generic panel-dsi binding */
162 + dt_desc = devm_kzalloc(&dsi->dev, sizeof(*dt_desc), GFP_KERNEL);
166 + err = panel_dsi_dt_probe(&dsi->dev, dt_desc);
175 err = panel_simple_probe(&dsi->dev, &desc->desc);