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>
23 /* Panel specific color-format bits */
24 #define COL_FMT_16BPP 0x55
25 #define COL_FMT_18BPP 0x66
26 #define COL_FMT_24BPP 0x77
28 /* Write Manufacture Command Set Control */
29 #define WRMAUCCTR 0xFE
31 /* Manufacturer Command Set pages (CMD2) */
32 struct cmd_set_entry
{
38 * There is no description in the Reference Manual about these commands.
39 * We received them from vendor, so just use them as is.
41 static const struct cmd_set_entry manufacturer_cmd_set
[] = {
187 static const u32 rad_bus_formats
[] = {
188 MEDIA_BUS_FMT_RGB888_1X24
,
189 MEDIA_BUS_FMT_RGB666_1X18
,
190 MEDIA_BUS_FMT_RGB565_1X16
,
193 static const u32 rad_bus_flags
= DRM_BUS_FLAG_DE_LOW
|
194 DRM_BUS_FLAG_PIXDATA_SAMPLE_POSEDGE
;
197 struct drm_panel panel
;
198 struct mipi_dsi_device
*dsi
;
200 struct gpio_desc
*reset
;
201 struct backlight_device
*backlight
;
203 struct regulator_bulk_data
*supplies
;
204 unsigned int num_supplies
;
210 static const struct drm_display_mode default_mode
= {
213 .hsync_start
= 1080 + 20,
214 .hsync_end
= 1080 + 20 + 2,
215 .htotal
= 1080 + 20 + 2 + 34,
217 .vsync_start
= 1920 + 10,
218 .vsync_end
= 1920 + 10 + 2,
219 .vtotal
= 1920 + 10 + 2 + 4,
222 .flags
= DRM_MODE_FLAG_NHSYNC
|
223 DRM_MODE_FLAG_NVSYNC
,
226 static inline struct rad_panel
*to_rad_panel(struct drm_panel
*panel
)
228 return container_of(panel
, struct rad_panel
, panel
);
231 static int rad_panel_push_cmd_list(struct mipi_dsi_device
*dsi
)
234 size_t count
= ARRAY_SIZE(manufacturer_cmd_set
);
237 for (i
= 0; i
< count
; i
++) {
238 const struct cmd_set_entry
*entry
= &manufacturer_cmd_set
[i
];
239 u8 buffer
[2] = { entry
->cmd
, entry
->param
};
241 ret
= mipi_dsi_generic_write(dsi
, &buffer
, sizeof(buffer
));
249 static int color_format_from_dsi_format(enum mipi_dsi_pixel_format format
)
252 case MIPI_DSI_FMT_RGB565
:
253 return COL_FMT_16BPP
;
254 case MIPI_DSI_FMT_RGB666
:
255 case MIPI_DSI_FMT_RGB666_PACKED
:
256 return COL_FMT_18BPP
;
257 case MIPI_DSI_FMT_RGB888
:
258 return COL_FMT_24BPP
;
260 return COL_FMT_24BPP
; /* for backward compatibility */
264 static int rad_panel_prepare(struct drm_panel
*panel
)
266 struct rad_panel
*rad
= to_rad_panel(panel
);
272 ret
= regulator_bulk_enable(rad
->num_supplies
, rad
->supplies
);
277 gpiod_set_value_cansleep(rad
->reset
, 1);
278 usleep_range(3000, 5000);
279 gpiod_set_value_cansleep(rad
->reset
, 0);
280 usleep_range(18000, 20000);
283 rad
->prepared
= true;
288 static int rad_panel_unprepare(struct drm_panel
*panel
)
290 struct rad_panel
*rad
= to_rad_panel(panel
);
297 * Right after asserting the reset, we need to release it, so that the
298 * touch driver can have an active connection with the touch controller
299 * even after the display is turned off.
302 gpiod_set_value_cansleep(rad
->reset
, 1);
303 usleep_range(15000, 17000);
304 gpiod_set_value_cansleep(rad
->reset
, 0);
307 ret
= regulator_bulk_disable(rad
->num_supplies
, rad
->supplies
);
311 rad
->prepared
= false;
316 static int rad_panel_enable(struct drm_panel
*panel
)
318 struct rad_panel
*rad
= to_rad_panel(panel
);
319 struct mipi_dsi_device
*dsi
= rad
->dsi
;
320 struct device
*dev
= &dsi
->dev
;
321 int color_format
= color_format_from_dsi_format(dsi
->format
);
327 dsi
->mode_flags
|= MIPI_DSI_MODE_LPM
;
329 ret
= rad_panel_push_cmd_list(dsi
);
331 dev_err(dev
, "Failed to send MCS (%d)\n", ret
);
335 /* Select User Command Set table (CMD1) */
336 ret
= mipi_dsi_generic_write(dsi
, (u8
[]){ WRMAUCCTR
, 0x00 }, 2);
341 ret
= mipi_dsi_dcs_soft_reset(dsi
);
343 dev_err(dev
, "Failed to do Software Reset (%d)\n", ret
);
347 usleep_range(15000, 17000);
350 ret
= mipi_dsi_generic_write(dsi
, (u8
[]){ 0xC2, 0x0B }, 2);
352 dev_err(dev
, "Failed to set DSI mode (%d)\n", ret
);
356 ret
= mipi_dsi_dcs_set_tear_on(dsi
, MIPI_DSI_DCS_TEAR_MODE_VBLANK
);
358 dev_err(dev
, "Failed to set tear ON (%d)\n", ret
);
361 /* Set tear scanline */
362 ret
= mipi_dsi_dcs_set_tear_scanline(dsi
, 0x380);
364 dev_err(dev
, "Failed to set tear scanline (%d)\n", ret
);
367 /* Set pixel format */
368 ret
= mipi_dsi_dcs_set_pixel_format(dsi
, color_format
);
369 dev_dbg(dev
, "Interface color format set to 0x%x\n", color_format
);
371 dev_err(dev
, "Failed to set pixel format (%d)\n", ret
);
374 /* Exit sleep mode */
375 ret
= mipi_dsi_dcs_exit_sleep_mode(dsi
);
377 dev_err(dev
, "Failed to exit sleep mode (%d)\n", ret
);
381 usleep_range(5000, 7000);
383 ret
= mipi_dsi_dcs_set_display_on(dsi
);
385 dev_err(dev
, "Failed to set display ON (%d)\n", ret
);
389 backlight_enable(rad
->backlight
);
396 gpiod_set_value_cansleep(rad
->reset
, 1);
401 static int rad_panel_disable(struct drm_panel
*panel
)
403 struct rad_panel
*rad
= to_rad_panel(panel
);
404 struct mipi_dsi_device
*dsi
= rad
->dsi
;
405 struct device
*dev
= &dsi
->dev
;
411 dsi
->mode_flags
|= MIPI_DSI_MODE_LPM
;
413 backlight_disable(rad
->backlight
);
415 usleep_range(10000, 12000);
417 ret
= mipi_dsi_dcs_set_display_off(dsi
);
419 dev_err(dev
, "Failed to set display OFF (%d)\n", ret
);
423 usleep_range(5000, 10000);
425 ret
= mipi_dsi_dcs_enter_sleep_mode(dsi
);
427 dev_err(dev
, "Failed to enter sleep mode (%d)\n", ret
);
431 rad
->enabled
= false;
436 static int rad_panel_get_modes(struct drm_panel
*panel
,
437 struct drm_connector
*connector
)
439 struct drm_display_mode
*mode
;
441 mode
= drm_mode_duplicate(connector
->dev
, &default_mode
);
443 dev_err(panel
->dev
, "failed to add mode %ux%u@%u\n",
444 default_mode
.hdisplay
, default_mode
.vdisplay
,
445 drm_mode_vrefresh(&default_mode
));
449 drm_mode_set_name(mode
);
450 mode
->type
= DRM_MODE_TYPE_DRIVER
| DRM_MODE_TYPE_PREFERRED
;
451 drm_mode_probed_add(connector
, mode
);
453 connector
->display_info
.width_mm
= mode
->width_mm
;
454 connector
->display_info
.height_mm
= mode
->height_mm
;
455 connector
->display_info
.bus_flags
= rad_bus_flags
;
457 drm_display_info_set_bus_formats(&connector
->display_info
,
459 ARRAY_SIZE(rad_bus_formats
));
463 static int rad_bl_get_brightness(struct backlight_device
*bl
)
465 struct mipi_dsi_device
*dsi
= bl_get_data(bl
);
466 struct rad_panel
*rad
= mipi_dsi_get_drvdata(dsi
);
473 dsi
->mode_flags
&= ~MIPI_DSI_MODE_LPM
;
475 ret
= mipi_dsi_dcs_get_display_brightness(dsi
, &brightness
);
479 bl
->props
.brightness
= brightness
;
481 return brightness
& 0xff;
484 static int rad_bl_update_status(struct backlight_device
*bl
)
486 struct mipi_dsi_device
*dsi
= bl_get_data(bl
);
487 struct rad_panel
*rad
= mipi_dsi_get_drvdata(dsi
);
493 dsi
->mode_flags
&= ~MIPI_DSI_MODE_LPM
;
495 ret
= mipi_dsi_dcs_set_display_brightness(dsi
, bl
->props
.brightness
);
502 static const struct backlight_ops rad_bl_ops
= {
503 .update_status
= rad_bl_update_status
,
504 .get_brightness
= rad_bl_get_brightness
,
507 static const struct drm_panel_funcs rad_panel_funcs
= {
508 .prepare
= rad_panel_prepare
,
509 .unprepare
= rad_panel_unprepare
,
510 .enable
= rad_panel_enable
,
511 .disable
= rad_panel_disable
,
512 .get_modes
= rad_panel_get_modes
,
515 static const char * const rad_supply_names
[] = {
520 static int rad_init_regulators(struct rad_panel
*rad
)
522 struct device
*dev
= &rad
->dsi
->dev
;
525 rad
->num_supplies
= ARRAY_SIZE(rad_supply_names
);
526 rad
->supplies
= devm_kcalloc(dev
, rad
->num_supplies
,
527 sizeof(*rad
->supplies
), GFP_KERNEL
);
531 for (i
= 0; i
< rad
->num_supplies
; i
++)
532 rad
->supplies
[i
].supply
= rad_supply_names
[i
];
534 return devm_regulator_bulk_get(dev
, rad
->num_supplies
, rad
->supplies
);
537 static int rad_panel_probe(struct mipi_dsi_device
*dsi
)
539 struct device
*dev
= &dsi
->dev
;
540 struct device_node
*np
= dev
->of_node
;
541 struct rad_panel
*panel
;
542 struct backlight_properties bl_props
;
546 panel
= devm_kzalloc(&dsi
->dev
, sizeof(*panel
), GFP_KERNEL
);
550 mipi_dsi_set_drvdata(dsi
, panel
);
554 dsi
->format
= MIPI_DSI_FMT_RGB888
;
555 dsi
->mode_flags
= MIPI_DSI_MODE_VIDEO_HSE
| MIPI_DSI_MODE_VIDEO
;
557 ret
= of_property_read_u32(np
, "video-mode", &video_mode
);
559 switch (video_mode
) {
562 dsi
->mode_flags
|= MIPI_DSI_MODE_VIDEO_BURST
;
565 /* non-burst mode with sync event */
568 /* non-burst mode with sync pulse */
569 dsi
->mode_flags
|= MIPI_DSI_MODE_VIDEO_SYNC_PULSE
;
572 dev_warn(dev
, "invalid video mode %d\n", video_mode
);
577 ret
= of_property_read_u32(np
, "dsi-lanes", &dsi
->lanes
);
579 dev_err(dev
, "Failed to get dsi-lanes property (%d)\n", ret
);
583 panel
->reset
= devm_gpiod_get_optional(dev
, "reset", GPIOD_OUT_LOW
);
584 if (IS_ERR(panel
->reset
))
585 return PTR_ERR(panel
->reset
);
587 memset(&bl_props
, 0, sizeof(bl_props
));
588 bl_props
.type
= BACKLIGHT_RAW
;
589 bl_props
.brightness
= 255;
590 bl_props
.max_brightness
= 255;
592 panel
->backlight
= devm_backlight_device_register(dev
, dev_name(dev
),
593 dev
, dsi
, &rad_bl_ops
,
595 if (IS_ERR(panel
->backlight
)) {
596 ret
= PTR_ERR(panel
->backlight
);
597 dev_err(dev
, "Failed to register backlight (%d)\n", ret
);
601 ret
= rad_init_regulators(panel
);
605 drm_panel_init(&panel
->panel
, dev
, &rad_panel_funcs
,
606 DRM_MODE_CONNECTOR_DSI
);
607 dev_set_drvdata(dev
, panel
);
609 drm_panel_add(&panel
->panel
);
611 ret
= mipi_dsi_attach(dsi
);
613 drm_panel_remove(&panel
->panel
);
618 static int rad_panel_remove(struct mipi_dsi_device
*dsi
)
620 struct rad_panel
*rad
= mipi_dsi_get_drvdata(dsi
);
621 struct device
*dev
= &dsi
->dev
;
624 ret
= mipi_dsi_detach(dsi
);
626 dev_err(dev
, "Failed to detach from host (%d)\n", ret
);
628 drm_panel_remove(&rad
->panel
);
633 static void rad_panel_shutdown(struct mipi_dsi_device
*dsi
)
635 struct rad_panel
*rad
= mipi_dsi_get_drvdata(dsi
);
637 rad_panel_disable(&rad
->panel
);
638 rad_panel_unprepare(&rad
->panel
);
641 static const struct of_device_id rad_of_match
[] = {
642 { .compatible
= "raydium,rm67191", },
645 MODULE_DEVICE_TABLE(of
, rad_of_match
);
647 static struct mipi_dsi_driver rad_panel_driver
= {
649 .name
= "panel-raydium-rm67191",
650 .of_match_table
= rad_of_match
,
652 .probe
= rad_panel_probe
,
653 .remove
= rad_panel_remove
,
654 .shutdown
= rad_panel_shutdown
,
656 module_mipi_dsi_driver(rad_panel_driver
);
658 MODULE_AUTHOR("Robert Chiras <robert.chiras@nxp.com>");
659 MODULE_DESCRIPTION("DRM Driver for Raydium RM67191 MIPI DSI panel");
660 MODULE_LICENSE("GPL v2");