Lines Matching +full:panel +full:- +full:mipi +full:- +full:dbi +full:- +full:spi
1 // SPDX-License-Identifier: GPL-2.0
3 * DRM driver for MIPI DBI compatible display panels
15 #include <linux/spi/spi.h>
45 * MIPI commands to execute when the display pipeline is enabled.
53 * parameter: delay in miliseconds (the No Operation command is part of the MIPI Display
79 const struct panel_mipi_dbi_config *config = (struct panel_mipi_dbi_config *)fw->data; in panel_mipi_dbi_check_commands()
81 size_t size = fw->size, commands_len; in panel_mipi_dbi_check_commands()
86 return ERR_PTR(-EINVAL); in panel_mipi_dbi_check_commands()
89 if (memcmp(config->magic, panel_mipi_dbi_magic, sizeof(config->magic))) { in panel_mipi_dbi_check_commands()
90 dev_err(dev, "config: Bad magic: %15ph\n", config->magic); in panel_mipi_dbi_check_commands()
91 return ERR_PTR(-EINVAL); in panel_mipi_dbi_check_commands()
94 if (config->file_format_version != 1) { in panel_mipi_dbi_check_commands()
95 dev_err(dev, "config: version=%u is not supported\n", config->file_format_version); in panel_mipi_dbi_check_commands()
96 return ERR_PTR(-EINVAL); in panel_mipi_dbi_check_commands()
99 drm_dev_dbg(dev, DRM_UT_DRIVER, "size=%zu version=%u\n", size, config->file_format_version); in panel_mipi_dbi_check_commands()
101 commands_len = size - sizeof(*config); in panel_mipi_dbi_check_commands()
104 u8 command = config->commands[i++]; in panel_mipi_dbi_check_commands()
105 u8 num_parameters = config->commands[i++]; in panel_mipi_dbi_check_commands()
106 const u8 *parameters = &config->commands[i]; in panel_mipi_dbi_check_commands()
112 return ERR_PTR(-EINVAL); in panel_mipi_dbi_check_commands()
124 return ERR_PTR(-EINVAL); in panel_mipi_dbi_check_commands()
129 return ERR_PTR(-ENOMEM); in panel_mipi_dbi_check_commands()
131 commands->len = commands_len; in panel_mipi_dbi_check_commands()
132 commands->buf = devm_kmemdup(dev, config->commands, commands->len, GFP_KERNEL); in panel_mipi_dbi_check_commands()
133 if (!commands->buf) in panel_mipi_dbi_check_commands()
134 return ERR_PTR(-ENOMEM); in panel_mipi_dbi_check_commands()
147 ret = of_property_read_string_index(dev->of_node, "compatible", 0, &compatible); in panel_mipi_dbi_commands_from_fw()
166 static void panel_mipi_dbi_commands_execute(struct mipi_dbi *dbi, in panel_mipi_dbi_commands_execute() argument
174 while (i < commands->len) { in panel_mipi_dbi_commands_execute()
175 u8 command = commands->buf[i++]; in panel_mipi_dbi_commands_execute()
176 u8 num_parameters = commands->buf[i++]; in panel_mipi_dbi_commands_execute()
177 const u8 *parameters = &commands->buf[i]; in panel_mipi_dbi_commands_execute()
182 mipi_dbi_command_stackbuf(dbi, command, parameters, num_parameters); in panel_mipi_dbi_commands_execute()
184 mipi_dbi_command(dbi, command); in panel_mipi_dbi_commands_execute()
194 struct mipi_dbi_dev *dbidev = drm_to_mipi_dbi_dev(pipe->crtc.dev); in panel_mipi_dbi_enable()
195 struct mipi_dbi *dbi = &dbidev->dbi; in panel_mipi_dbi_enable() local
198 if (!drm_dev_enter(pipe->crtc.dev, &idx)) in panel_mipi_dbi_enable()
201 drm_dbg(pipe->crtc.dev, "\n"); in panel_mipi_dbi_enable()
207 panel_mipi_dbi_commands_execute(dbi, dbidev->driver_private); in panel_mipi_dbi_enable()
225 .name = "panel-mipi-dbi",
226 .desc = "MIPI DBI compatible display panel",
234 struct device *dev = dbidev->drm.dev; in panel_mipi_dbi_get_mode()
238 ret = of_get_drm_panel_display_mode(dev->of_node, mode, NULL); in panel_mipi_dbi_get_mode()
240 dev_err(dev, "%pOF: failed to get panel-timing (error=%d)\n", dev->of_node, ret); in panel_mipi_dbi_get_mode()
244 mode->type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED; in panel_mipi_dbi_get_mode()
246 hback_porch = mode->htotal - mode->hsync_end; in panel_mipi_dbi_get_mode()
247 vback_porch = mode->vtotal - mode->vsync_end; in panel_mipi_dbi_get_mode()
252 * width and height don't exceed the 16-bit value specified by MIPI DCS. in panel_mipi_dbi_get_mode()
254 if (!mode->hdisplay || !mode->vdisplay || mode->flags || in panel_mipi_dbi_get_mode()
255 mode->hsync_end > mode->hdisplay || (hback_porch + mode->hdisplay) > 0xffff || in panel_mipi_dbi_get_mode()
256 mode->vsync_end > mode->vdisplay || (vback_porch + mode->vdisplay) > 0xffff) { in panel_mipi_dbi_get_mode()
257 dev_err(dev, "%pOF: panel-timing out of bounds\n", dev->of_node); in panel_mipi_dbi_get_mode()
258 return -EINVAL; in panel_mipi_dbi_get_mode()
262 if (!mode->clock) in panel_mipi_dbi_get_mode()
263 mode->clock = mode->htotal * mode->vtotal * 60 / 1000; in panel_mipi_dbi_get_mode()
265 dbidev->top_offset = vback_porch; in panel_mipi_dbi_get_mode()
266 dbidev->left_offset = hback_porch; in panel_mipi_dbi_get_mode()
271 static int panel_mipi_dbi_spi_probe(struct spi_device *spi) in panel_mipi_dbi_spi_probe() argument
273 struct device *dev = &spi->dev; in panel_mipi_dbi_spi_probe()
277 struct mipi_dbi *dbi; in panel_mipi_dbi_spi_probe() local
285 dbi = &dbidev->dbi; in panel_mipi_dbi_spi_probe()
286 drm = &dbidev->drm; in panel_mipi_dbi_spi_probe()
292 dbidev->regulator = devm_regulator_get(dev, "power"); in panel_mipi_dbi_spi_probe()
293 if (IS_ERR(dbidev->regulator)) in panel_mipi_dbi_spi_probe()
294 return dev_err_probe(dev, PTR_ERR(dbidev->regulator), in panel_mipi_dbi_spi_probe()
297 dbidev->io_regulator = devm_regulator_get(dev, "io"); in panel_mipi_dbi_spi_probe()
298 if (IS_ERR(dbidev->io_regulator)) in panel_mipi_dbi_spi_probe()
299 return dev_err_probe(dev, PTR_ERR(dbidev->io_regulator), in panel_mipi_dbi_spi_probe()
302 dbidev->backlight = devm_of_find_backlight(dev); in panel_mipi_dbi_spi_probe()
303 if (IS_ERR(dbidev->backlight)) in panel_mipi_dbi_spi_probe()
304 return dev_err_probe(dev, PTR_ERR(dbidev->backlight), "Failed to get backlight\n"); in panel_mipi_dbi_spi_probe()
306 dbi->reset = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_HIGH); in panel_mipi_dbi_spi_probe()
307 if (IS_ERR(dbi->reset)) in panel_mipi_dbi_spi_probe()
308 return dev_err_probe(dev, PTR_ERR(dbi->reset), "Failed to get GPIO 'reset'\n"); in panel_mipi_dbi_spi_probe()
310 /* Multiple panels can share the "dc" GPIO, but only if they are on the same SPI bus! */ in panel_mipi_dbi_spi_probe()
315 ret = mipi_dbi_spi_init(spi, dbi, dc); in panel_mipi_dbi_spi_probe()
319 if (device_property_present(dev, "write-only")) in panel_mipi_dbi_spi_probe()
320 dbi->read_commands = NULL; in panel_mipi_dbi_spi_probe()
322 dbidev->driver_private = panel_mipi_dbi_commands_from_fw(dev); in panel_mipi_dbi_spi_probe()
323 if (IS_ERR(dbidev->driver_private)) in panel_mipi_dbi_spi_probe()
324 return PTR_ERR(dbidev->driver_private); in panel_mipi_dbi_spi_probe()
336 spi_set_drvdata(spi, drm); in panel_mipi_dbi_spi_probe()
343 static void panel_mipi_dbi_spi_remove(struct spi_device *spi) in panel_mipi_dbi_spi_remove() argument
345 struct drm_device *drm = spi_get_drvdata(spi); in panel_mipi_dbi_spi_remove()
351 static void panel_mipi_dbi_spi_shutdown(struct spi_device *spi) in panel_mipi_dbi_spi_shutdown() argument
353 drm_atomic_helper_shutdown(spi_get_drvdata(spi)); in panel_mipi_dbi_spi_shutdown()
373 { .compatible = "panel-mipi-dbi-spi" },
379 { "panel-mipi-dbi-spi", 0 },
382 MODULE_DEVICE_TABLE(spi, panel_mipi_dbi_spi_id);
386 .name = "panel-mipi-dbi-spi",
398 MODULE_DESCRIPTION("MIPI DBI compatible display panel driver");