0001
0002
0003
0004
0005
0006
0007
0008 #include <linux/backlight.h>
0009 #include <linux/delay.h>
0010 #include <linux/gpio/consumer.h>
0011 #include <linux/media-bus-format.h>
0012 #include <linux/module.h>
0013 #include <linux/of.h>
0014 #include <linux/regulator/consumer.h>
0015
0016 #include <video/mipi_display.h>
0017 #include <video/of_videomode.h>
0018 #include <video/videomode.h>
0019
0020 #include <drm/drm_crtc.h>
0021 #include <drm/drm_mipi_dsi.h>
0022 #include <drm/drm_panel.h>
0023
0024
0025 #define COL_FMT_16BPP 0x55
0026 #define COL_FMT_18BPP 0x66
0027 #define COL_FMT_24BPP 0x77
0028
0029
0030 #define WRMAUCCTR 0xFE
0031
0032
0033 struct cmd_set_entry {
0034 u8 cmd;
0035 u8 param;
0036 };
0037
0038
0039
0040
0041
0042 static const struct cmd_set_entry manufacturer_cmd_set[] = {
0043 {0xFE, 0x0B},
0044 {0x28, 0x40},
0045 {0x29, 0x4F},
0046 {0xFE, 0x0E},
0047 {0x4B, 0x00},
0048 {0x4C, 0x0F},
0049 {0x4D, 0x20},
0050 {0x4E, 0x40},
0051 {0x4F, 0x60},
0052 {0x50, 0xA0},
0053 {0x51, 0xC0},
0054 {0x52, 0xE0},
0055 {0x53, 0xFF},
0056 {0xFE, 0x0D},
0057 {0x18, 0x08},
0058 {0x42, 0x00},
0059 {0x08, 0x41},
0060 {0x46, 0x02},
0061 {0x72, 0x09},
0062 {0xFE, 0x0A},
0063 {0x24, 0x17},
0064 {0x04, 0x07},
0065 {0x1A, 0x0C},
0066 {0x0F, 0x44},
0067 {0xFE, 0x04},
0068 {0x00, 0x0C},
0069 {0x05, 0x08},
0070 {0x06, 0x08},
0071 {0x08, 0x08},
0072 {0x09, 0x08},
0073 {0x0A, 0xE6},
0074 {0x0B, 0x8C},
0075 {0x1A, 0x12},
0076 {0x1E, 0xE0},
0077 {0x29, 0x93},
0078 {0x2A, 0x93},
0079 {0x2F, 0x02},
0080 {0x31, 0x02},
0081 {0x33, 0x05},
0082 {0x37, 0x2D},
0083 {0x38, 0x2D},
0084 {0x3A, 0x1E},
0085 {0x3B, 0x1E},
0086 {0x3D, 0x27},
0087 {0x3F, 0x80},
0088 {0x40, 0x40},
0089 {0x41, 0xE0},
0090 {0x4F, 0x2F},
0091 {0x50, 0x1E},
0092 {0xFE, 0x06},
0093 {0x00, 0xCC},
0094 {0x05, 0x05},
0095 {0x07, 0xA2},
0096 {0x08, 0xCC},
0097 {0x0D, 0x03},
0098 {0x0F, 0xA2},
0099 {0x32, 0xCC},
0100 {0x37, 0x05},
0101 {0x39, 0x83},
0102 {0x3A, 0xCC},
0103 {0x41, 0x04},
0104 {0x43, 0x83},
0105 {0x44, 0xCC},
0106 {0x49, 0x05},
0107 {0x4B, 0xA2},
0108 {0x4C, 0xCC},
0109 {0x51, 0x03},
0110 {0x53, 0xA2},
0111 {0x75, 0xCC},
0112 {0x7A, 0x03},
0113 {0x7C, 0x83},
0114 {0x7D, 0xCC},
0115 {0x82, 0x02},
0116 {0x84, 0x83},
0117 {0x85, 0xEC},
0118 {0x86, 0x0F},
0119 {0x87, 0xFF},
0120 {0x88, 0x00},
0121 {0x8A, 0x02},
0122 {0x8C, 0xA2},
0123 {0x8D, 0xEA},
0124 {0x8E, 0x01},
0125 {0x8F, 0xE8},
0126 {0xFE, 0x06},
0127 {0x90, 0x0A},
0128 {0x92, 0x06},
0129 {0x93, 0xA0},
0130 {0x94, 0xA8},
0131 {0x95, 0xEC},
0132 {0x96, 0x0F},
0133 {0x97, 0xFF},
0134 {0x98, 0x00},
0135 {0x9A, 0x02},
0136 {0x9C, 0xA2},
0137 {0xAC, 0x04},
0138 {0xFE, 0x06},
0139 {0xB1, 0x12},
0140 {0xB2, 0x17},
0141 {0xB3, 0x17},
0142 {0xB4, 0x17},
0143 {0xB5, 0x17},
0144 {0xB6, 0x11},
0145 {0xB7, 0x08},
0146 {0xB8, 0x09},
0147 {0xB9, 0x06},
0148 {0xBA, 0x07},
0149 {0xBB, 0x17},
0150 {0xBC, 0x17},
0151 {0xBD, 0x17},
0152 {0xBE, 0x17},
0153 {0xBF, 0x17},
0154 {0xC0, 0x17},
0155 {0xC1, 0x17},
0156 {0xC2, 0x17},
0157 {0xC3, 0x17},
0158 {0xC4, 0x0F},
0159 {0xC5, 0x0E},
0160 {0xC6, 0x00},
0161 {0xC7, 0x01},
0162 {0xC8, 0x10},
0163 {0xFE, 0x06},
0164 {0x95, 0xEC},
0165 {0x8D, 0xEE},
0166 {0x44, 0xEC},
0167 {0x4C, 0xEC},
0168 {0x32, 0xEC},
0169 {0x3A, 0xEC},
0170 {0x7D, 0xEC},
0171 {0x75, 0xEC},
0172 {0x00, 0xEC},
0173 {0x08, 0xEC},
0174 {0x85, 0xEC},
0175 {0xA6, 0x21},
0176 {0xA7, 0x05},
0177 {0xA9, 0x06},
0178 {0x82, 0x06},
0179 {0x41, 0x06},
0180 {0x7A, 0x07},
0181 {0x37, 0x07},
0182 {0x05, 0x06},
0183 {0x49, 0x06},
0184 {0x0D, 0x04},
0185 {0x51, 0x04},
0186 };
0187
0188 static const u32 rad_bus_formats[] = {
0189 MEDIA_BUS_FMT_RGB888_1X24,
0190 MEDIA_BUS_FMT_RGB666_1X18,
0191 MEDIA_BUS_FMT_RGB565_1X16,
0192 };
0193
0194 static const u32 rad_bus_flags = DRM_BUS_FLAG_DE_LOW |
0195 DRM_BUS_FLAG_PIXDATA_SAMPLE_POSEDGE;
0196
0197 struct rad_panel {
0198 struct drm_panel panel;
0199 struct mipi_dsi_device *dsi;
0200
0201 struct gpio_desc *reset;
0202 struct backlight_device *backlight;
0203
0204 struct regulator_bulk_data *supplies;
0205 unsigned int num_supplies;
0206
0207 bool prepared;
0208 bool enabled;
0209 };
0210
0211 static const struct drm_display_mode default_mode = {
0212 .clock = 132000,
0213 .hdisplay = 1080,
0214 .hsync_start = 1080 + 20,
0215 .hsync_end = 1080 + 20 + 2,
0216 .htotal = 1080 + 20 + 2 + 34,
0217 .vdisplay = 1920,
0218 .vsync_start = 1920 + 10,
0219 .vsync_end = 1920 + 10 + 2,
0220 .vtotal = 1920 + 10 + 2 + 4,
0221 .width_mm = 68,
0222 .height_mm = 121,
0223 .flags = DRM_MODE_FLAG_NHSYNC |
0224 DRM_MODE_FLAG_NVSYNC,
0225 };
0226
0227 static inline struct rad_panel *to_rad_panel(struct drm_panel *panel)
0228 {
0229 return container_of(panel, struct rad_panel, panel);
0230 }
0231
0232 static int rad_panel_push_cmd_list(struct mipi_dsi_device *dsi)
0233 {
0234 size_t i;
0235 size_t count = ARRAY_SIZE(manufacturer_cmd_set);
0236 int ret = 0;
0237
0238 for (i = 0; i < count; i++) {
0239 const struct cmd_set_entry *entry = &manufacturer_cmd_set[i];
0240 u8 buffer[2] = { entry->cmd, entry->param };
0241
0242 ret = mipi_dsi_generic_write(dsi, &buffer, sizeof(buffer));
0243 if (ret < 0)
0244 return ret;
0245 }
0246
0247 return ret;
0248 };
0249
0250 static int color_format_from_dsi_format(enum mipi_dsi_pixel_format format)
0251 {
0252 switch (format) {
0253 case MIPI_DSI_FMT_RGB565:
0254 return COL_FMT_16BPP;
0255 case MIPI_DSI_FMT_RGB666:
0256 case MIPI_DSI_FMT_RGB666_PACKED:
0257 return COL_FMT_18BPP;
0258 case MIPI_DSI_FMT_RGB888:
0259 return COL_FMT_24BPP;
0260 default:
0261 return COL_FMT_24BPP;
0262 }
0263 };
0264
0265 static int rad_panel_prepare(struct drm_panel *panel)
0266 {
0267 struct rad_panel *rad = to_rad_panel(panel);
0268 int ret;
0269
0270 if (rad->prepared)
0271 return 0;
0272
0273 ret = regulator_bulk_enable(rad->num_supplies, rad->supplies);
0274 if (ret)
0275 return ret;
0276
0277 if (rad->reset) {
0278 gpiod_set_value_cansleep(rad->reset, 1);
0279 usleep_range(3000, 5000);
0280 gpiod_set_value_cansleep(rad->reset, 0);
0281 usleep_range(18000, 20000);
0282 }
0283
0284 rad->prepared = true;
0285
0286 return 0;
0287 }
0288
0289 static int rad_panel_unprepare(struct drm_panel *panel)
0290 {
0291 struct rad_panel *rad = to_rad_panel(panel);
0292 int ret;
0293
0294 if (!rad->prepared)
0295 return 0;
0296
0297
0298
0299
0300
0301
0302 if (rad->reset) {
0303 gpiod_set_value_cansleep(rad->reset, 1);
0304 usleep_range(15000, 17000);
0305 gpiod_set_value_cansleep(rad->reset, 0);
0306 }
0307
0308 ret = regulator_bulk_disable(rad->num_supplies, rad->supplies);
0309 if (ret)
0310 return ret;
0311
0312 rad->prepared = false;
0313
0314 return 0;
0315 }
0316
0317 static int rad_panel_enable(struct drm_panel *panel)
0318 {
0319 struct rad_panel *rad = to_rad_panel(panel);
0320 struct mipi_dsi_device *dsi = rad->dsi;
0321 struct device *dev = &dsi->dev;
0322 int color_format = color_format_from_dsi_format(dsi->format);
0323 int ret;
0324
0325 if (rad->enabled)
0326 return 0;
0327
0328 dsi->mode_flags |= MIPI_DSI_MODE_LPM;
0329
0330 ret = rad_panel_push_cmd_list(dsi);
0331 if (ret < 0) {
0332 dev_err(dev, "Failed to send MCS (%d)\n", ret);
0333 goto fail;
0334 }
0335
0336
0337 ret = mipi_dsi_generic_write(dsi, (u8[]){ WRMAUCCTR, 0x00 }, 2);
0338 if (ret < 0)
0339 goto fail;
0340
0341
0342 ret = mipi_dsi_dcs_soft_reset(dsi);
0343 if (ret < 0) {
0344 dev_err(dev, "Failed to do Software Reset (%d)\n", ret);
0345 goto fail;
0346 }
0347
0348 usleep_range(15000, 17000);
0349
0350
0351 ret = mipi_dsi_generic_write(dsi, (u8[]){ 0xC2, 0x0B }, 2);
0352 if (ret < 0) {
0353 dev_err(dev, "Failed to set DSI mode (%d)\n", ret);
0354 goto fail;
0355 }
0356
0357 ret = mipi_dsi_dcs_set_tear_on(dsi, MIPI_DSI_DCS_TEAR_MODE_VBLANK);
0358 if (ret < 0) {
0359 dev_err(dev, "Failed to set tear ON (%d)\n", ret);
0360 goto fail;
0361 }
0362
0363 ret = mipi_dsi_dcs_set_tear_scanline(dsi, 0x380);
0364 if (ret < 0) {
0365 dev_err(dev, "Failed to set tear scanline (%d)\n", ret);
0366 goto fail;
0367 }
0368
0369 ret = mipi_dsi_dcs_set_pixel_format(dsi, color_format);
0370 dev_dbg(dev, "Interface color format set to 0x%x\n", color_format);
0371 if (ret < 0) {
0372 dev_err(dev, "Failed to set pixel format (%d)\n", ret);
0373 goto fail;
0374 }
0375
0376 ret = mipi_dsi_dcs_exit_sleep_mode(dsi);
0377 if (ret < 0) {
0378 dev_err(dev, "Failed to exit sleep mode (%d)\n", ret);
0379 goto fail;
0380 }
0381
0382 usleep_range(5000, 7000);
0383
0384 ret = mipi_dsi_dcs_set_display_on(dsi);
0385 if (ret < 0) {
0386 dev_err(dev, "Failed to set display ON (%d)\n", ret);
0387 goto fail;
0388 }
0389
0390 backlight_enable(rad->backlight);
0391
0392 rad->enabled = true;
0393
0394 return 0;
0395
0396 fail:
0397 gpiod_set_value_cansleep(rad->reset, 1);
0398
0399 return ret;
0400 }
0401
0402 static int rad_panel_disable(struct drm_panel *panel)
0403 {
0404 struct rad_panel *rad = to_rad_panel(panel);
0405 struct mipi_dsi_device *dsi = rad->dsi;
0406 struct device *dev = &dsi->dev;
0407 int ret;
0408
0409 if (!rad->enabled)
0410 return 0;
0411
0412 dsi->mode_flags |= MIPI_DSI_MODE_LPM;
0413
0414 backlight_disable(rad->backlight);
0415
0416 usleep_range(10000, 12000);
0417
0418 ret = mipi_dsi_dcs_set_display_off(dsi);
0419 if (ret < 0) {
0420 dev_err(dev, "Failed to set display OFF (%d)\n", ret);
0421 return ret;
0422 }
0423
0424 usleep_range(5000, 10000);
0425
0426 ret = mipi_dsi_dcs_enter_sleep_mode(dsi);
0427 if (ret < 0) {
0428 dev_err(dev, "Failed to enter sleep mode (%d)\n", ret);
0429 return ret;
0430 }
0431
0432 rad->enabled = false;
0433
0434 return 0;
0435 }
0436
0437 static int rad_panel_get_modes(struct drm_panel *panel,
0438 struct drm_connector *connector)
0439 {
0440 struct drm_display_mode *mode;
0441
0442 mode = drm_mode_duplicate(connector->dev, &default_mode);
0443 if (!mode) {
0444 dev_err(panel->dev, "failed to add mode %ux%u@%u\n",
0445 default_mode.hdisplay, default_mode.vdisplay,
0446 drm_mode_vrefresh(&default_mode));
0447 return -ENOMEM;
0448 }
0449
0450 drm_mode_set_name(mode);
0451 mode->type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED;
0452 drm_mode_probed_add(connector, mode);
0453
0454 connector->display_info.width_mm = mode->width_mm;
0455 connector->display_info.height_mm = mode->height_mm;
0456 connector->display_info.bus_flags = rad_bus_flags;
0457
0458 drm_display_info_set_bus_formats(&connector->display_info,
0459 rad_bus_formats,
0460 ARRAY_SIZE(rad_bus_formats));
0461 return 1;
0462 }
0463
0464 static int rad_bl_get_brightness(struct backlight_device *bl)
0465 {
0466 struct mipi_dsi_device *dsi = bl_get_data(bl);
0467 struct rad_panel *rad = mipi_dsi_get_drvdata(dsi);
0468 u16 brightness;
0469 int ret;
0470
0471 if (!rad->prepared)
0472 return 0;
0473
0474 dsi->mode_flags &= ~MIPI_DSI_MODE_LPM;
0475
0476 ret = mipi_dsi_dcs_get_display_brightness(dsi, &brightness);
0477 if (ret < 0)
0478 return ret;
0479
0480 bl->props.brightness = brightness;
0481
0482 return brightness & 0xff;
0483 }
0484
0485 static int rad_bl_update_status(struct backlight_device *bl)
0486 {
0487 struct mipi_dsi_device *dsi = bl_get_data(bl);
0488 struct rad_panel *rad = mipi_dsi_get_drvdata(dsi);
0489 int ret = 0;
0490
0491 if (!rad->prepared)
0492 return 0;
0493
0494 dsi->mode_flags &= ~MIPI_DSI_MODE_LPM;
0495
0496 ret = mipi_dsi_dcs_set_display_brightness(dsi, bl->props.brightness);
0497 if (ret < 0)
0498 return ret;
0499
0500 return 0;
0501 }
0502
0503 static const struct backlight_ops rad_bl_ops = {
0504 .update_status = rad_bl_update_status,
0505 .get_brightness = rad_bl_get_brightness,
0506 };
0507
0508 static const struct drm_panel_funcs rad_panel_funcs = {
0509 .prepare = rad_panel_prepare,
0510 .unprepare = rad_panel_unprepare,
0511 .enable = rad_panel_enable,
0512 .disable = rad_panel_disable,
0513 .get_modes = rad_panel_get_modes,
0514 };
0515
0516 static const char * const rad_supply_names[] = {
0517 "v3p3",
0518 "v1p8",
0519 };
0520
0521 static int rad_init_regulators(struct rad_panel *rad)
0522 {
0523 struct device *dev = &rad->dsi->dev;
0524 int i;
0525
0526 rad->num_supplies = ARRAY_SIZE(rad_supply_names);
0527 rad->supplies = devm_kcalloc(dev, rad->num_supplies,
0528 sizeof(*rad->supplies), GFP_KERNEL);
0529 if (!rad->supplies)
0530 return -ENOMEM;
0531
0532 for (i = 0; i < rad->num_supplies; i++)
0533 rad->supplies[i].supply = rad_supply_names[i];
0534
0535 return devm_regulator_bulk_get(dev, rad->num_supplies, rad->supplies);
0536 };
0537
0538 static int rad_panel_probe(struct mipi_dsi_device *dsi)
0539 {
0540 struct device *dev = &dsi->dev;
0541 struct device_node *np = dev->of_node;
0542 struct rad_panel *panel;
0543 struct backlight_properties bl_props;
0544 int ret;
0545 u32 video_mode;
0546
0547 panel = devm_kzalloc(&dsi->dev, sizeof(*panel), GFP_KERNEL);
0548 if (!panel)
0549 return -ENOMEM;
0550
0551 mipi_dsi_set_drvdata(dsi, panel);
0552
0553 panel->dsi = dsi;
0554
0555 dsi->format = MIPI_DSI_FMT_RGB888;
0556 dsi->mode_flags = MIPI_DSI_MODE_VIDEO_HSE | MIPI_DSI_MODE_VIDEO;
0557
0558 ret = of_property_read_u32(np, "video-mode", &video_mode);
0559 if (!ret) {
0560 switch (video_mode) {
0561 case 0:
0562
0563 dsi->mode_flags |= MIPI_DSI_MODE_VIDEO_BURST;
0564 break;
0565 case 1:
0566
0567 break;
0568 case 2:
0569
0570 dsi->mode_flags |= MIPI_DSI_MODE_VIDEO_SYNC_PULSE;
0571 break;
0572 default:
0573 dev_warn(dev, "invalid video mode %d\n", video_mode);
0574 break;
0575 }
0576 }
0577
0578 ret = of_property_read_u32(np, "dsi-lanes", &dsi->lanes);
0579 if (ret) {
0580 dev_err(dev, "Failed to get dsi-lanes property (%d)\n", ret);
0581 return ret;
0582 }
0583
0584 panel->reset = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_LOW);
0585 if (IS_ERR(panel->reset))
0586 return PTR_ERR(panel->reset);
0587
0588 memset(&bl_props, 0, sizeof(bl_props));
0589 bl_props.type = BACKLIGHT_RAW;
0590 bl_props.brightness = 255;
0591 bl_props.max_brightness = 255;
0592
0593 panel->backlight = devm_backlight_device_register(dev, dev_name(dev),
0594 dev, dsi, &rad_bl_ops,
0595 &bl_props);
0596 if (IS_ERR(panel->backlight)) {
0597 ret = PTR_ERR(panel->backlight);
0598 dev_err(dev, "Failed to register backlight (%d)\n", ret);
0599 return ret;
0600 }
0601
0602 ret = rad_init_regulators(panel);
0603 if (ret)
0604 return ret;
0605
0606 drm_panel_init(&panel->panel, dev, &rad_panel_funcs,
0607 DRM_MODE_CONNECTOR_DSI);
0608 dev_set_drvdata(dev, panel);
0609
0610 drm_panel_add(&panel->panel);
0611
0612 ret = mipi_dsi_attach(dsi);
0613 if (ret)
0614 drm_panel_remove(&panel->panel);
0615
0616 return ret;
0617 }
0618
0619 static int rad_panel_remove(struct mipi_dsi_device *dsi)
0620 {
0621 struct rad_panel *rad = mipi_dsi_get_drvdata(dsi);
0622 struct device *dev = &dsi->dev;
0623 int ret;
0624
0625 ret = mipi_dsi_detach(dsi);
0626 if (ret)
0627 dev_err(dev, "Failed to detach from host (%d)\n", ret);
0628
0629 drm_panel_remove(&rad->panel);
0630
0631 return 0;
0632 }
0633
0634 static void rad_panel_shutdown(struct mipi_dsi_device *dsi)
0635 {
0636 struct rad_panel *rad = mipi_dsi_get_drvdata(dsi);
0637
0638 rad_panel_disable(&rad->panel);
0639 rad_panel_unprepare(&rad->panel);
0640 }
0641
0642 static const struct of_device_id rad_of_match[] = {
0643 { .compatible = "raydium,rm67191", },
0644 { }
0645 };
0646 MODULE_DEVICE_TABLE(of, rad_of_match);
0647
0648 static struct mipi_dsi_driver rad_panel_driver = {
0649 .driver = {
0650 .name = "panel-raydium-rm67191",
0651 .of_match_table = rad_of_match,
0652 },
0653 .probe = rad_panel_probe,
0654 .remove = rad_panel_remove,
0655 .shutdown = rad_panel_shutdown,
0656 };
0657 module_mipi_dsi_driver(rad_panel_driver);
0658
0659 MODULE_AUTHOR("Robert Chiras <robert.chiras@nxp.com>");
0660 MODULE_DESCRIPTION("DRM Driver for Raydium RM67191 MIPI DSI panel");
0661 MODULE_LICENSE("GPL v2");