]> Git Repo - J-linux.git/blob - drivers/gpu/drm/tiny/panel-mipi-dbi.c
Merge tag 'vfs-6.13-rc7.fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/vfs/vfs
[J-linux.git] / drivers / gpu / drm / tiny / panel-mipi-dbi.c
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * DRM driver for MIPI DBI compatible display panels
4  *
5  * Copyright 2022 Noralf Trønnes
6  */
7
8 #include <linux/backlight.h>
9 #include <linux/delay.h>
10 #include <linux/firmware.h>
11 #include <linux/gpio/consumer.h>
12 #include <linux/module.h>
13 #include <linux/property.h>
14 #include <linux/regulator/consumer.h>
15 #include <linux/spi/spi.h>
16
17 #include <drm/drm_atomic_helper.h>
18 #include <drm/drm_client_setup.h>
19 #include <drm/drm_drv.h>
20 #include <drm/drm_fbdev_dma.h>
21 #include <drm/drm_gem_atomic_helper.h>
22 #include <drm/drm_gem_dma_helper.h>
23 #include <drm/drm_managed.h>
24 #include <drm/drm_mipi_dbi.h>
25 #include <drm/drm_modes.h>
26 #include <drm/drm_modeset_helper.h>
27
28 #include <video/mipi_display.h>
29
30 struct panel_mipi_dbi_format {
31         const char *name;
32         u32 fourcc;
33         unsigned int bpp;
34 };
35
36 static const struct panel_mipi_dbi_format panel_mipi_dbi_formats[] = {
37         { "r5g6b5", DRM_FORMAT_RGB565, 16 },
38         { "b6x2g6x2r6x2", DRM_FORMAT_RGB888, 24 },
39 };
40
41 static int panel_mipi_dbi_get_format(struct device *dev, u32 *formats, unsigned int *bpp)
42 {
43         const char *format_name;
44         unsigned int i;
45         int ret;
46
47         formats[1] = DRM_FORMAT_XRGB8888;
48
49         ret = device_property_read_string(dev, "format", &format_name);
50         if (ret) {
51                 /* Old Device Trees don't have this property */
52                 formats[0] = DRM_FORMAT_RGB565;
53                 *bpp = 16;
54                 return 0;
55         }
56
57         for (i = 0; i < ARRAY_SIZE(panel_mipi_dbi_formats); i++) {
58                 const struct panel_mipi_dbi_format *format = &panel_mipi_dbi_formats[i];
59
60                 if (strcmp(format_name, format->name))
61                         continue;
62
63                 formats[0] = format->fourcc;
64                 *bpp = format->bpp;
65                 return 0;
66         }
67
68         dev_err(dev, "Pixel format is not supported: '%s'\n", format_name);
69
70         return -EINVAL;
71 }
72
73 static const u8 panel_mipi_dbi_magic[15] = { 'M', 'I', 'P', 'I', ' ', 'D', 'B', 'I',
74                                              0, 0, 0, 0, 0, 0, 0 };
75
76 /*
77  * The display controller configuration is stored in a firmware file.
78  * The Device Tree 'compatible' property value with a '.bin' suffix is passed
79  * to request_firmware() to fetch this file.
80  */
81 struct panel_mipi_dbi_config {
82         /* Magic string: panel_mipi_dbi_magic */
83         u8 magic[15];
84
85         /* Config file format version */
86         u8 file_format_version;
87
88         /*
89          * MIPI commands to execute when the display pipeline is enabled.
90          * This is used to configure the display controller.
91          *
92          * The commands are stored in a byte array with the format:
93          *     command, num_parameters, [ parameter, ...], command, ...
94          *
95          * Some commands require a pause before the next command can be received.
96          * Inserting a delay in the command sequence is done by using the NOP command with one
97          * parameter: delay in miliseconds (the No Operation command is part of the MIPI Display
98          * Command Set where it has no parameters).
99          *
100          * Example:
101          *     command 0x11
102          *     sleep 120ms
103          *     command 0xb1 parameters 0x01, 0x2c, 0x2d
104          *     command 0x29
105          *
106          * Byte sequence:
107          *     0x11 0x00
108          *     0x00 0x01 0x78
109          *     0xb1 0x03 0x01 0x2c 0x2d
110          *     0x29 0x00
111          */
112         u8 commands[];
113 };
114
115 struct panel_mipi_dbi_commands {
116         const u8 *buf;
117         size_t len;
118 };
119
120 static struct panel_mipi_dbi_commands *
121 panel_mipi_dbi_check_commands(struct device *dev, const struct firmware *fw)
122 {
123         const struct panel_mipi_dbi_config *config = (struct panel_mipi_dbi_config *)fw->data;
124         struct panel_mipi_dbi_commands *commands;
125         size_t size = fw->size, commands_len;
126         unsigned int i = 0;
127
128         if (size < sizeof(*config) + 2) { /* At least 1 command */
129                 dev_err(dev, "config: file size=%zu is too small\n", size);
130                 return ERR_PTR(-EINVAL);
131         }
132
133         if (memcmp(config->magic, panel_mipi_dbi_magic, sizeof(config->magic))) {
134                 dev_err(dev, "config: Bad magic: %15ph\n", config->magic);
135                 return ERR_PTR(-EINVAL);
136         }
137
138         if (config->file_format_version != 1) {
139                 dev_err(dev, "config: version=%u is not supported\n", config->file_format_version);
140                 return ERR_PTR(-EINVAL);
141         }
142
143         drm_dev_dbg(dev, DRM_UT_DRIVER, "size=%zu version=%u\n", size, config->file_format_version);
144
145         commands_len = size - sizeof(*config);
146
147         while ((i + 1) < commands_len) {
148                 u8 command = config->commands[i++];
149                 u8 num_parameters = config->commands[i++];
150                 const u8 *parameters = &config->commands[i];
151
152                 i += num_parameters;
153                 if (i > commands_len) {
154                         dev_err(dev, "config: command=0x%02x num_parameters=%u overflows\n",
155                                 command, num_parameters);
156                         return ERR_PTR(-EINVAL);
157                 }
158
159                 if (command == 0x00 && num_parameters == 1)
160                         drm_dev_dbg(dev, DRM_UT_DRIVER, "sleep %ums\n", parameters[0]);
161                 else
162                         drm_dev_dbg(dev, DRM_UT_DRIVER, "command %02x %*ph\n",
163                                     command, num_parameters, parameters);
164         }
165
166         if (i != commands_len) {
167                 dev_err(dev, "config: malformed command array\n");
168                 return ERR_PTR(-EINVAL);
169         }
170
171         commands = devm_kzalloc(dev, sizeof(*commands), GFP_KERNEL);
172         if (!commands)
173                 return ERR_PTR(-ENOMEM);
174
175         commands->len = commands_len;
176         commands->buf = devm_kmemdup(dev, config->commands, commands->len, GFP_KERNEL);
177         if (!commands->buf)
178                 return ERR_PTR(-ENOMEM);
179
180         return commands;
181 }
182
183 static struct panel_mipi_dbi_commands *panel_mipi_dbi_commands_from_fw(struct device *dev)
184 {
185         struct panel_mipi_dbi_commands *commands;
186         const struct firmware *fw;
187         const char *compatible;
188         char fw_name[40];
189         int ret;
190
191         ret = of_property_read_string_index(dev->of_node, "compatible", 0, &compatible);
192         if (ret)
193                 return ERR_PTR(ret);
194
195         snprintf(fw_name, sizeof(fw_name), "%s.bin", compatible);
196         ret = request_firmware(&fw, fw_name, dev);
197         if (ret) {
198                 dev_err(dev, "No config file found for compatible '%s' (error=%d)\n",
199                         compatible, ret);
200
201                 return ERR_PTR(ret);
202         }
203
204         commands = panel_mipi_dbi_check_commands(dev, fw);
205         release_firmware(fw);
206
207         return commands;
208 }
209
210 static void panel_mipi_dbi_commands_execute(struct mipi_dbi *dbi,
211                                             struct panel_mipi_dbi_commands *commands)
212 {
213         unsigned int i = 0;
214
215         if (!commands)
216                 return;
217
218         while (i < commands->len) {
219                 u8 command = commands->buf[i++];
220                 u8 num_parameters = commands->buf[i++];
221                 const u8 *parameters = &commands->buf[i];
222
223                 if (command == 0x00 && num_parameters == 1)
224                         msleep(parameters[0]);
225                 else if (num_parameters)
226                         mipi_dbi_command_stackbuf(dbi, command, parameters, num_parameters);
227                 else
228                         mipi_dbi_command(dbi, command);
229
230                 i += num_parameters;
231         }
232 }
233
234 static void panel_mipi_dbi_enable(struct drm_simple_display_pipe *pipe,
235                                   struct drm_crtc_state *crtc_state,
236                                   struct drm_plane_state *plane_state)
237 {
238         struct mipi_dbi_dev *dbidev = drm_to_mipi_dbi_dev(pipe->crtc.dev);
239         struct mipi_dbi *dbi = &dbidev->dbi;
240         int ret, idx;
241
242         if (!drm_dev_enter(pipe->crtc.dev, &idx))
243                 return;
244
245         drm_dbg(pipe->crtc.dev, "\n");
246
247         ret = mipi_dbi_poweron_conditional_reset(dbidev);
248         if (ret < 0)
249                 goto out_exit;
250         if (!ret)
251                 panel_mipi_dbi_commands_execute(dbi, dbidev->driver_private);
252
253         mipi_dbi_enable_flush(dbidev, crtc_state, plane_state);
254 out_exit:
255         drm_dev_exit(idx);
256 }
257
258 static const struct drm_simple_display_pipe_funcs panel_mipi_dbi_pipe_funcs = {
259         DRM_MIPI_DBI_SIMPLE_DISPLAY_PIPE_FUNCS(panel_mipi_dbi_enable),
260 };
261
262 DEFINE_DRM_GEM_DMA_FOPS(panel_mipi_dbi_fops);
263
264 static const struct drm_driver panel_mipi_dbi_driver = {
265         .driver_features        = DRIVER_GEM | DRIVER_MODESET | DRIVER_ATOMIC,
266         .fops                   = &panel_mipi_dbi_fops,
267         DRM_GEM_DMA_DRIVER_OPS_VMAP,
268         DRM_FBDEV_DMA_DRIVER_OPS,
269         .debugfs_init           = mipi_dbi_debugfs_init,
270         .name                   = "panel-mipi-dbi",
271         .desc                   = "MIPI DBI compatible display panel",
272         .date                   = "20220103",
273         .major                  = 1,
274         .minor                  = 0,
275 };
276
277 static int panel_mipi_dbi_get_mode(struct mipi_dbi_dev *dbidev, struct drm_display_mode *mode)
278 {
279         struct device *dev = dbidev->drm.dev;
280         u16 hback_porch, vback_porch;
281         int ret;
282
283         ret = of_get_drm_panel_display_mode(dev->of_node, mode, NULL);
284         if (ret) {
285                 dev_err(dev, "%pOF: failed to get panel-timing (error=%d)\n", dev->of_node, ret);
286                 return ret;
287         }
288
289         mode->type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED;
290
291         hback_porch = mode->htotal - mode->hsync_end;
292         vback_porch = mode->vtotal - mode->vsync_end;
293
294         /*
295          * Make sure width and height are set and that only back porch and
296          * pixelclock are set in the other timing values. Also check that
297          * width and height don't exceed the 16-bit value specified by MIPI DCS.
298          */
299         if (!mode->hdisplay || !mode->vdisplay || mode->flags ||
300             mode->hsync_end > mode->hdisplay || (hback_porch + mode->hdisplay) > 0xffff ||
301             mode->vsync_end > mode->vdisplay || (vback_porch + mode->vdisplay) > 0xffff) {
302                 dev_err(dev, "%pOF: panel-timing out of bounds\n", dev->of_node);
303                 return -EINVAL;
304         }
305
306         /* The driver doesn't use the pixel clock but it is mandatory so fake one if not set */
307         if (!mode->clock)
308                 mode->clock = mode->htotal * mode->vtotal * 60 / 1000;
309
310         dbidev->top_offset = vback_porch;
311         dbidev->left_offset = hback_porch;
312
313         return 0;
314 }
315
316 static int panel_mipi_dbi_spi_probe(struct spi_device *spi)
317 {
318         struct device *dev = &spi->dev;
319         struct drm_display_mode mode;
320         struct mipi_dbi_dev *dbidev;
321         struct drm_device *drm;
322         struct mipi_dbi *dbi;
323         struct gpio_desc *dc;
324         unsigned int bpp;
325         size_t buf_size;
326         u32 formats[2];
327         int ret;
328
329         dbidev = devm_drm_dev_alloc(dev, &panel_mipi_dbi_driver, struct mipi_dbi_dev, drm);
330         if (IS_ERR(dbidev))
331                 return PTR_ERR(dbidev);
332
333         dbi = &dbidev->dbi;
334         drm = &dbidev->drm;
335
336         ret = panel_mipi_dbi_get_mode(dbidev, &mode);
337         if (ret)
338                 return ret;
339
340         dbidev->regulator = devm_regulator_get(dev, "power");
341         if (IS_ERR(dbidev->regulator))
342                 return dev_err_probe(dev, PTR_ERR(dbidev->regulator),
343                                      "Failed to get regulator 'power'\n");
344
345         dbidev->io_regulator = devm_regulator_get(dev, "io");
346         if (IS_ERR(dbidev->io_regulator))
347                 return dev_err_probe(dev, PTR_ERR(dbidev->io_regulator),
348                                      "Failed to get regulator 'io'\n");
349
350         dbidev->backlight = devm_of_find_backlight(dev);
351         if (IS_ERR(dbidev->backlight))
352                 return dev_err_probe(dev, PTR_ERR(dbidev->backlight), "Failed to get backlight\n");
353
354         dbi->reset = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_HIGH);
355         if (IS_ERR(dbi->reset))
356                 return dev_err_probe(dev, PTR_ERR(dbi->reset), "Failed to get GPIO 'reset'\n");
357
358         /* Multiple panels can share the "dc" GPIO, but only if they are on the same SPI bus! */
359         dc = devm_gpiod_get_optional(dev, "dc", GPIOD_OUT_LOW | GPIOD_FLAGS_BIT_NONEXCLUSIVE);
360         if (IS_ERR(dc))
361                 return dev_err_probe(dev, PTR_ERR(dc), "Failed to get GPIO 'dc'\n");
362
363         ret = mipi_dbi_spi_init(spi, dbi, dc);
364         if (ret)
365                 return ret;
366
367         if (device_property_present(dev, "write-only"))
368                 dbi->read_commands = NULL;
369
370         dbidev->driver_private = panel_mipi_dbi_commands_from_fw(dev);
371         if (IS_ERR(dbidev->driver_private))
372                 return PTR_ERR(dbidev->driver_private);
373
374         ret = panel_mipi_dbi_get_format(dev, formats, &bpp);
375         if (ret)
376                 return ret;
377
378         buf_size = DIV_ROUND_UP(mode.hdisplay * mode.vdisplay * bpp, 8);
379         ret = mipi_dbi_dev_init_with_formats(dbidev, &panel_mipi_dbi_pipe_funcs,
380                                              formats, ARRAY_SIZE(formats),
381                                              &mode, 0, buf_size);
382         if (ret)
383                 return ret;
384
385         drm_mode_config_reset(drm);
386
387         ret = drm_dev_register(drm, 0);
388         if (ret)
389                 return ret;
390
391         spi_set_drvdata(spi, drm);
392
393         drm_client_setup(drm, NULL);
394
395         return 0;
396 }
397
398 static void panel_mipi_dbi_spi_remove(struct spi_device *spi)
399 {
400         struct drm_device *drm = spi_get_drvdata(spi);
401
402         drm_dev_unplug(drm);
403         drm_atomic_helper_shutdown(drm);
404 }
405
406 static void panel_mipi_dbi_spi_shutdown(struct spi_device *spi)
407 {
408         drm_atomic_helper_shutdown(spi_get_drvdata(spi));
409 }
410
411 static int __maybe_unused panel_mipi_dbi_pm_suspend(struct device *dev)
412 {
413         return drm_mode_config_helper_suspend(dev_get_drvdata(dev));
414 }
415
416 static int __maybe_unused panel_mipi_dbi_pm_resume(struct device *dev)
417 {
418         drm_mode_config_helper_resume(dev_get_drvdata(dev));
419
420         return 0;
421 }
422
423 static const struct dev_pm_ops panel_mipi_dbi_pm_ops = {
424         SET_SYSTEM_SLEEP_PM_OPS(panel_mipi_dbi_pm_suspend, panel_mipi_dbi_pm_resume)
425 };
426
427 static const struct of_device_id panel_mipi_dbi_spi_of_match[] = {
428         { .compatible = "panel-mipi-dbi-spi" },
429         {},
430 };
431 MODULE_DEVICE_TABLE(of, panel_mipi_dbi_spi_of_match);
432
433 static const struct spi_device_id panel_mipi_dbi_spi_id[] = {
434         { "panel-mipi-dbi-spi", 0 },
435         { },
436 };
437 MODULE_DEVICE_TABLE(spi, panel_mipi_dbi_spi_id);
438
439 static struct spi_driver panel_mipi_dbi_spi_driver = {
440         .driver = {
441                 .name = "panel-mipi-dbi-spi",
442                 .of_match_table = panel_mipi_dbi_spi_of_match,
443                 .pm = &panel_mipi_dbi_pm_ops,
444         },
445         .id_table = panel_mipi_dbi_spi_id,
446         .probe = panel_mipi_dbi_spi_probe,
447         .remove = panel_mipi_dbi_spi_remove,
448         .shutdown = panel_mipi_dbi_spi_shutdown,
449 };
450 module_spi_driver(panel_mipi_dbi_spi_driver);
451
452 MODULE_DESCRIPTION("MIPI DBI compatible display panel driver");
453 MODULE_AUTHOR("Noralf Trønnes");
454 MODULE_LICENSE("GPL");
This page took 0.052505 seconds and 4 git commands to generate.