1 // SPDX-License-Identifier: GPL-2.0
3 * Raydium RM67191 MIPI-DSI panel driver
8 #include <linux/backlight.h>
9 #include <linux/delay.h>
10 #include <linux/gpio/consumer.h>
11 #include <linux/module.h>
13 #include <linux/regulator/consumer.h>
15 #include <video/mipi_display.h>
16 #include <video/of_videomode.h>
17 #include <video/videomode.h>
19 #include <drm/drm_crtc.h>
20 #include <drm/drm_mipi_dsi.h>
21 #include <drm/drm_panel.h>
22 #include <drm/drm_print.h>
24 /* Panel specific color-format bits */
25 #define COL_FMT_16BPP 0x55
26 #define COL_FMT_18BPP 0x66
27 #define COL_FMT_24BPP 0x77
29 /* Write Manufacture Command Set Control */
30 #define WRMAUCCTR 0xFE
32 /* Manufacturer Command Set pages (CMD2) */
33 struct cmd_set_entry
{
39 * There is no description in the Reference Manual about these commands.
40 * We received them from vendor, so just use them as is.
42 static const struct cmd_set_entry manufacturer_cmd_set
[] = {
188 static const u32 rad_bus_formats
[] = {
189 MEDIA_BUS_FMT_RGB888_1X24
,
190 MEDIA_BUS_FMT_RGB666_1X18
,
191 MEDIA_BUS_FMT_RGB565_1X16
,
194 static const u32 rad_bus_flags
= DRM_BUS_FLAG_DE_LOW
|
195 DRM_BUS_FLAG_PIXDATA_NEGEDGE
;
198 struct drm_panel panel
;
199 struct mipi_dsi_device
*dsi
;
201 struct gpio_desc
*reset
;
202 struct backlight_device
*backlight
;
204 struct regulator_bulk_data
*supplies
;
205 unsigned int num_supplies
;
211 static const struct drm_display_mode default_mode
= {
214 .hsync_start
= 1080 + 20,
215 .hsync_end
= 1080 + 20 + 2,
216 .htotal
= 1080 + 20 + 2 + 34,
218 .vsync_start
= 1920 + 10,
219 .vsync_end
= 1920 + 10 + 2,
220 .vtotal
= 1920 + 10 + 2 + 4,
224 .flags
= DRM_MODE_FLAG_NHSYNC
|
225 DRM_MODE_FLAG_NVSYNC
,
228 static inline struct rad_panel
*to_rad_panel(struct drm_panel
*panel
)
230 return container_of(panel
, struct rad_panel
, panel
);
233 static int rad_panel_push_cmd_list(struct mipi_dsi_device
*dsi
)
236 size_t count
= ARRAY_SIZE(manufacturer_cmd_set
);
239 for (i
= 0; i
< count
; i
++) {
240 const struct cmd_set_entry
*entry
= &manufacturer_cmd_set
[i
];
241 u8 buffer
[2] = { entry
->cmd
, entry
->param
};
243 ret
= mipi_dsi_generic_write(dsi
, &buffer
, sizeof(buffer
));
251 static int color_format_from_dsi_format(enum mipi_dsi_pixel_format format
)
254 case MIPI_DSI_FMT_RGB565
:
255 return COL_FMT_16BPP
;
256 case MIPI_DSI_FMT_RGB666
:
257 case MIPI_DSI_FMT_RGB666_PACKED
:
258 return COL_FMT_18BPP
;
259 case MIPI_DSI_FMT_RGB888
:
260 return COL_FMT_24BPP
;
262 return COL_FMT_24BPP
; /* for backward compatibility */
266 static int rad_panel_prepare(struct drm_panel
*panel
)
268 struct rad_panel
*rad
= to_rad_panel(panel
);
274 ret
= regulator_bulk_enable(rad
->num_supplies
, rad
->supplies
);
279 gpiod_set_value_cansleep(rad
->reset
, 1);
280 usleep_range(3000, 5000);
281 gpiod_set_value_cansleep(rad
->reset
, 0);
282 usleep_range(18000, 20000);
285 rad
->prepared
= true;
290 static int rad_panel_unprepare(struct drm_panel
*panel
)
292 struct rad_panel
*rad
= to_rad_panel(panel
);
299 * Right after asserting the reset, we need to release it, so that the
300 * touch driver can have an active connection with the touch controller
301 * even after the display is turned off.
304 gpiod_set_value_cansleep(rad
->reset
, 1);
305 usleep_range(15000, 17000);
306 gpiod_set_value_cansleep(rad
->reset
, 0);
309 ret
= regulator_bulk_disable(rad
->num_supplies
, rad
->supplies
);
313 rad
->prepared
= false;
318 static int rad_panel_enable(struct drm_panel
*panel
)
320 struct rad_panel
*rad
= to_rad_panel(panel
);
321 struct mipi_dsi_device
*dsi
= rad
->dsi
;
322 struct device
*dev
= &dsi
->dev
;
323 int color_format
= color_format_from_dsi_format(dsi
->format
);
329 dsi
->mode_flags
|= MIPI_DSI_MODE_LPM
;
331 ret
= rad_panel_push_cmd_list(dsi
);
333 DRM_DEV_ERROR(dev
, "Failed to send MCS (%d)\n", ret
);
337 /* Select User Command Set table (CMD1) */
338 ret
= mipi_dsi_generic_write(dsi
, (u8
[]){ WRMAUCCTR
, 0x00 }, 2);
343 ret
= mipi_dsi_dcs_soft_reset(dsi
);
345 DRM_DEV_ERROR(dev
, "Failed to do Software Reset (%d)\n", ret
);
349 usleep_range(15000, 17000);
352 ret
= mipi_dsi_generic_write(dsi
, (u8
[]){ 0xC2, 0x0B }, 2);
354 DRM_DEV_ERROR(dev
, "Failed to set DSI mode (%d)\n", ret
);
358 ret
= mipi_dsi_dcs_set_tear_on(dsi
, MIPI_DSI_DCS_TEAR_MODE_VBLANK
);
360 DRM_DEV_ERROR(dev
, "Failed to set tear ON (%d)\n", ret
);
363 /* Set tear scanline */
364 ret
= mipi_dsi_dcs_set_tear_scanline(dsi
, 0x380);
366 DRM_DEV_ERROR(dev
, "Failed to set tear scanline (%d)\n", ret
);
369 /* Set pixel format */
370 ret
= mipi_dsi_dcs_set_pixel_format(dsi
, color_format
);
371 DRM_DEV_DEBUG_DRIVER(dev
, "Interface color format set to 0x%x\n",
374 DRM_DEV_ERROR(dev
, "Failed to set pixel format (%d)\n", ret
);
377 /* Exit sleep mode */
378 ret
= mipi_dsi_dcs_exit_sleep_mode(dsi
);
380 DRM_DEV_ERROR(dev
, "Failed to exit sleep mode (%d)\n", ret
);
384 usleep_range(5000, 7000);
386 ret
= mipi_dsi_dcs_set_display_on(dsi
);
388 DRM_DEV_ERROR(dev
, "Failed to set display ON (%d)\n", ret
);
392 backlight_enable(rad
->backlight
);
399 gpiod_set_value_cansleep(rad
->reset
, 1);
404 static int rad_panel_disable(struct drm_panel
*panel
)
406 struct rad_panel
*rad
= to_rad_panel(panel
);
407 struct mipi_dsi_device
*dsi
= rad
->dsi
;
408 struct device
*dev
= &dsi
->dev
;
414 dsi
->mode_flags
|= MIPI_DSI_MODE_LPM
;
416 backlight_disable(rad
->backlight
);
418 usleep_range(10000, 12000);
420 ret
= mipi_dsi_dcs_set_display_off(dsi
);
422 DRM_DEV_ERROR(dev
, "Failed to set display OFF (%d)\n", ret
);
426 usleep_range(5000, 10000);
428 ret
= mipi_dsi_dcs_enter_sleep_mode(dsi
);
430 DRM_DEV_ERROR(dev
, "Failed to enter sleep mode (%d)\n", ret
);
434 rad
->enabled
= false;
439 static int rad_panel_get_modes(struct drm_panel
*panel
,
440 struct drm_connector
*connector
)
442 struct drm_display_mode
*mode
;
444 mode
= drm_mode_duplicate(connector
->dev
, &default_mode
);
446 DRM_DEV_ERROR(panel
->dev
, "failed to add mode %ux%ux@%u\n",
447 default_mode
.hdisplay
, default_mode
.vdisplay
,
448 default_mode
.vrefresh
);
452 drm_mode_set_name(mode
);
453 mode
->type
= DRM_MODE_TYPE_DRIVER
| DRM_MODE_TYPE_PREFERRED
;
454 drm_mode_probed_add(connector
, mode
);
456 connector
->display_info
.width_mm
= mode
->width_mm
;
457 connector
->display_info
.height_mm
= mode
->height_mm
;
458 connector
->display_info
.bus_flags
= rad_bus_flags
;
460 drm_display_info_set_bus_formats(&connector
->display_info
,
462 ARRAY_SIZE(rad_bus_formats
));
466 static int rad_bl_get_brightness(struct backlight_device
*bl
)
468 struct mipi_dsi_device
*dsi
= bl_get_data(bl
);
469 struct rad_panel
*rad
= mipi_dsi_get_drvdata(dsi
);
476 dsi
->mode_flags
&= ~MIPI_DSI_MODE_LPM
;
478 ret
= mipi_dsi_dcs_get_display_brightness(dsi
, &brightness
);
482 bl
->props
.brightness
= brightness
;
484 return brightness
& 0xff;
487 static int rad_bl_update_status(struct backlight_device
*bl
)
489 struct mipi_dsi_device
*dsi
= bl_get_data(bl
);
490 struct rad_panel
*rad
= mipi_dsi_get_drvdata(dsi
);
496 dsi
->mode_flags
&= ~MIPI_DSI_MODE_LPM
;
498 ret
= mipi_dsi_dcs_set_display_brightness(dsi
, bl
->props
.brightness
);
505 static const struct backlight_ops rad_bl_ops
= {
506 .update_status
= rad_bl_update_status
,
507 .get_brightness
= rad_bl_get_brightness
,
510 static const struct drm_panel_funcs rad_panel_funcs
= {
511 .prepare
= rad_panel_prepare
,
512 .unprepare
= rad_panel_unprepare
,
513 .enable
= rad_panel_enable
,
514 .disable
= rad_panel_disable
,
515 .get_modes
= rad_panel_get_modes
,
518 static const char * const rad_supply_names
[] = {
523 static int rad_init_regulators(struct rad_panel
*rad
)
525 struct device
*dev
= &rad
->dsi
->dev
;
528 rad
->num_supplies
= ARRAY_SIZE(rad_supply_names
);
529 rad
->supplies
= devm_kcalloc(dev
, rad
->num_supplies
,
530 sizeof(*rad
->supplies
), GFP_KERNEL
);
534 for (i
= 0; i
< rad
->num_supplies
; i
++)
535 rad
->supplies
[i
].supply
= rad_supply_names
[i
];
537 return devm_regulator_bulk_get(dev
, rad
->num_supplies
, rad
->supplies
);
540 static int rad_panel_probe(struct mipi_dsi_device
*dsi
)
542 struct device
*dev
= &dsi
->dev
;
543 struct device_node
*np
= dev
->of_node
;
544 struct rad_panel
*panel
;
545 struct backlight_properties bl_props
;
549 panel
= devm_kzalloc(&dsi
->dev
, sizeof(*panel
), GFP_KERNEL
);
553 mipi_dsi_set_drvdata(dsi
, panel
);
557 dsi
->format
= MIPI_DSI_FMT_RGB888
;
558 dsi
->mode_flags
= MIPI_DSI_MODE_VIDEO_HSE
| MIPI_DSI_MODE_VIDEO
|
559 MIPI_DSI_CLOCK_NON_CONTINUOUS
;
561 ret
= of_property_read_u32(np
, "video-mode", &video_mode
);
563 switch (video_mode
) {
566 dsi
->mode_flags
|= MIPI_DSI_MODE_VIDEO_BURST
;
569 /* non-burst mode with sync event */
572 /* non-burst mode with sync pulse */
573 dsi
->mode_flags
|= MIPI_DSI_MODE_VIDEO_SYNC_PULSE
;
576 dev_warn(dev
, "invalid video mode %d\n", video_mode
);
581 ret
= of_property_read_u32(np
, "dsi-lanes", &dsi
->lanes
);
583 dev_err(dev
, "Failed to get dsi-lanes property (%d)\n", ret
);
587 panel
->reset
= devm_gpiod_get_optional(dev
, "reset", GPIOD_OUT_LOW
);
588 if (IS_ERR(panel
->reset
))
589 return PTR_ERR(panel
->reset
);
591 memset(&bl_props
, 0, sizeof(bl_props
));
592 bl_props
.type
= BACKLIGHT_RAW
;
593 bl_props
.brightness
= 255;
594 bl_props
.max_brightness
= 255;
596 panel
->backlight
= devm_backlight_device_register(dev
, dev_name(dev
),
597 dev
, dsi
, &rad_bl_ops
,
599 if (IS_ERR(panel
->backlight
)) {
600 ret
= PTR_ERR(panel
->backlight
);
601 dev_err(dev
, "Failed to register backlight (%d)\n", ret
);
605 ret
= rad_init_regulators(panel
);
609 drm_panel_init(&panel
->panel
, dev
, &rad_panel_funcs
,
610 DRM_MODE_CONNECTOR_DSI
);
611 dev_set_drvdata(dev
, panel
);
613 ret
= drm_panel_add(&panel
->panel
);
617 ret
= mipi_dsi_attach(dsi
);
619 drm_panel_remove(&panel
->panel
);
624 static int rad_panel_remove(struct mipi_dsi_device
*dsi
)
626 struct rad_panel
*rad
= mipi_dsi_get_drvdata(dsi
);
627 struct device
*dev
= &dsi
->dev
;
630 ret
= mipi_dsi_detach(dsi
);
632 DRM_DEV_ERROR(dev
, "Failed to detach from host (%d)\n",
635 drm_panel_remove(&rad
->panel
);
640 static void rad_panel_shutdown(struct mipi_dsi_device
*dsi
)
642 struct rad_panel
*rad
= mipi_dsi_get_drvdata(dsi
);
644 rad_panel_disable(&rad
->panel
);
645 rad_panel_unprepare(&rad
->panel
);
648 static const struct of_device_id rad_of_match
[] = {
649 { .compatible
= "raydium,rm67191", },
652 MODULE_DEVICE_TABLE(of
, rad_of_match
);
654 static struct mipi_dsi_driver rad_panel_driver
= {
656 .name
= "panel-raydium-rm67191",
657 .of_match_table
= rad_of_match
,
659 .probe
= rad_panel_probe
,
660 .remove
= rad_panel_remove
,
661 .shutdown
= rad_panel_shutdown
,
663 module_mipi_dsi_driver(rad_panel_driver
);
665 MODULE_AUTHOR("Robert Chiras <robert.chiras@nxp.com>");
666 MODULE_DESCRIPTION("DRM Driver for Raydium RM67191 MIPI DSI panel");
667 MODULE_LICENSE("GPL v2");