panel-raydium-rm67191.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633
  1. // SPDX-License-Identifier: GPL-2.0
  2. /*
  3. * Raydium RM67191 MIPI-DSI panel driver
  4. *
  5. * Copyright 2019 NXP
  6. */
  7. #include <linux/backlight.h>
  8. #include <linux/delay.h>
  9. #include <linux/gpio/consumer.h>
  10. #include <linux/media-bus-format.h>
  11. #include <linux/module.h>
  12. #include <linux/of.h>
  13. #include <linux/regulator/consumer.h>
  14. #include <video/mipi_display.h>
  15. #include <video/of_videomode.h>
  16. #include <video/videomode.h>
  17. #include <drm/drm_crtc.h>
  18. #include <drm/drm_mipi_dsi.h>
  19. #include <drm/drm_panel.h>
  20. /* Panel specific color-format bits */
  21. #define COL_FMT_16BPP 0x55
  22. #define COL_FMT_18BPP 0x66
  23. #define COL_FMT_24BPP 0x77
  24. /* Write Manufacture Command Set Control */
  25. #define WRMAUCCTR 0xFE
  26. /* Manufacturer Command Set pages (CMD2) */
  27. struct cmd_set_entry {
  28. u8 cmd;
  29. u8 param;
  30. };
  31. /*
  32. * There is no description in the Reference Manual about these commands.
  33. * We received them from vendor, so just use them as is.
  34. */
  35. static const struct cmd_set_entry manufacturer_cmd_set[] = {
  36. {0xFE, 0x0B},
  37. {0x28, 0x40},
  38. {0x29, 0x4F},
  39. {0xFE, 0x0E},
  40. {0x4B, 0x00},
  41. {0x4C, 0x0F},
  42. {0x4D, 0x20},
  43. {0x4E, 0x40},
  44. {0x4F, 0x60},
  45. {0x50, 0xA0},
  46. {0x51, 0xC0},
  47. {0x52, 0xE0},
  48. {0x53, 0xFF},
  49. {0xFE, 0x0D},
  50. {0x18, 0x08},
  51. {0x42, 0x00},
  52. {0x08, 0x41},
  53. {0x46, 0x02},
  54. {0x72, 0x09},
  55. {0xFE, 0x0A},
  56. {0x24, 0x17},
  57. {0x04, 0x07},
  58. {0x1A, 0x0C},
  59. {0x0F, 0x44},
  60. {0xFE, 0x04},
  61. {0x00, 0x0C},
  62. {0x05, 0x08},
  63. {0x06, 0x08},
  64. {0x08, 0x08},
  65. {0x09, 0x08},
  66. {0x0A, 0xE6},
  67. {0x0B, 0x8C},
  68. {0x1A, 0x12},
  69. {0x1E, 0xE0},
  70. {0x29, 0x93},
  71. {0x2A, 0x93},
  72. {0x2F, 0x02},
  73. {0x31, 0x02},
  74. {0x33, 0x05},
  75. {0x37, 0x2D},
  76. {0x38, 0x2D},
  77. {0x3A, 0x1E},
  78. {0x3B, 0x1E},
  79. {0x3D, 0x27},
  80. {0x3F, 0x80},
  81. {0x40, 0x40},
  82. {0x41, 0xE0},
  83. {0x4F, 0x2F},
  84. {0x50, 0x1E},
  85. {0xFE, 0x06},
  86. {0x00, 0xCC},
  87. {0x05, 0x05},
  88. {0x07, 0xA2},
  89. {0x08, 0xCC},
  90. {0x0D, 0x03},
  91. {0x0F, 0xA2},
  92. {0x32, 0xCC},
  93. {0x37, 0x05},
  94. {0x39, 0x83},
  95. {0x3A, 0xCC},
  96. {0x41, 0x04},
  97. {0x43, 0x83},
  98. {0x44, 0xCC},
  99. {0x49, 0x05},
  100. {0x4B, 0xA2},
  101. {0x4C, 0xCC},
  102. {0x51, 0x03},
  103. {0x53, 0xA2},
  104. {0x75, 0xCC},
  105. {0x7A, 0x03},
  106. {0x7C, 0x83},
  107. {0x7D, 0xCC},
  108. {0x82, 0x02},
  109. {0x84, 0x83},
  110. {0x85, 0xEC},
  111. {0x86, 0x0F},
  112. {0x87, 0xFF},
  113. {0x88, 0x00},
  114. {0x8A, 0x02},
  115. {0x8C, 0xA2},
  116. {0x8D, 0xEA},
  117. {0x8E, 0x01},
  118. {0x8F, 0xE8},
  119. {0xFE, 0x06},
  120. {0x90, 0x0A},
  121. {0x92, 0x06},
  122. {0x93, 0xA0},
  123. {0x94, 0xA8},
  124. {0x95, 0xEC},
  125. {0x96, 0x0F},
  126. {0x97, 0xFF},
  127. {0x98, 0x00},
  128. {0x9A, 0x02},
  129. {0x9C, 0xA2},
  130. {0xAC, 0x04},
  131. {0xFE, 0x06},
  132. {0xB1, 0x12},
  133. {0xB2, 0x17},
  134. {0xB3, 0x17},
  135. {0xB4, 0x17},
  136. {0xB5, 0x17},
  137. {0xB6, 0x11},
  138. {0xB7, 0x08},
  139. {0xB8, 0x09},
  140. {0xB9, 0x06},
  141. {0xBA, 0x07},
  142. {0xBB, 0x17},
  143. {0xBC, 0x17},
  144. {0xBD, 0x17},
  145. {0xBE, 0x17},
  146. {0xBF, 0x17},
  147. {0xC0, 0x17},
  148. {0xC1, 0x17},
  149. {0xC2, 0x17},
  150. {0xC3, 0x17},
  151. {0xC4, 0x0F},
  152. {0xC5, 0x0E},
  153. {0xC6, 0x00},
  154. {0xC7, 0x01},
  155. {0xC8, 0x10},
  156. {0xFE, 0x06},
  157. {0x95, 0xEC},
  158. {0x8D, 0xEE},
  159. {0x44, 0xEC},
  160. {0x4C, 0xEC},
  161. {0x32, 0xEC},
  162. {0x3A, 0xEC},
  163. {0x7D, 0xEC},
  164. {0x75, 0xEC},
  165. {0x00, 0xEC},
  166. {0x08, 0xEC},
  167. {0x85, 0xEC},
  168. {0xA6, 0x21},
  169. {0xA7, 0x05},
  170. {0xA9, 0x06},
  171. {0x82, 0x06},
  172. {0x41, 0x06},
  173. {0x7A, 0x07},
  174. {0x37, 0x07},
  175. {0x05, 0x06},
  176. {0x49, 0x06},
  177. {0x0D, 0x04},
  178. {0x51, 0x04},
  179. };
  180. static const u32 rad_bus_formats[] = {
  181. MEDIA_BUS_FMT_RGB888_1X24,
  182. MEDIA_BUS_FMT_RGB666_1X18,
  183. MEDIA_BUS_FMT_RGB565_1X16,
  184. };
  185. static const u32 rad_bus_flags = DRM_BUS_FLAG_DE_LOW |
  186. DRM_BUS_FLAG_PIXDATA_SAMPLE_POSEDGE;
  187. struct rad_panel {
  188. struct drm_panel panel;
  189. struct mipi_dsi_device *dsi;
  190. struct gpio_desc *reset;
  191. struct backlight_device *backlight;
  192. struct regulator_bulk_data *supplies;
  193. unsigned int num_supplies;
  194. bool prepared;
  195. };
  196. static const struct drm_display_mode default_mode = {
  197. .clock = 132000,
  198. .hdisplay = 1080,
  199. .hsync_start = 1080 + 20,
  200. .hsync_end = 1080 + 20 + 2,
  201. .htotal = 1080 + 20 + 2 + 34,
  202. .vdisplay = 1920,
  203. .vsync_start = 1920 + 10,
  204. .vsync_end = 1920 + 10 + 2,
  205. .vtotal = 1920 + 10 + 2 + 4,
  206. .width_mm = 68,
  207. .height_mm = 121,
  208. .flags = DRM_MODE_FLAG_NHSYNC |
  209. DRM_MODE_FLAG_NVSYNC,
  210. };
  211. static inline struct rad_panel *to_rad_panel(struct drm_panel *panel)
  212. {
  213. return container_of(panel, struct rad_panel, panel);
  214. }
  215. static int rad_panel_push_cmd_list(struct mipi_dsi_device *dsi)
  216. {
  217. size_t i;
  218. size_t count = ARRAY_SIZE(manufacturer_cmd_set);
  219. int ret = 0;
  220. for (i = 0; i < count; i++) {
  221. const struct cmd_set_entry *entry = &manufacturer_cmd_set[i];
  222. u8 buffer[2] = { entry->cmd, entry->param };
  223. ret = mipi_dsi_generic_write(dsi, &buffer, sizeof(buffer));
  224. if (ret < 0)
  225. return ret;
  226. }
  227. return ret;
  228. };
  229. static int color_format_from_dsi_format(enum mipi_dsi_pixel_format format)
  230. {
  231. switch (format) {
  232. case MIPI_DSI_FMT_RGB565:
  233. return COL_FMT_16BPP;
  234. case MIPI_DSI_FMT_RGB666:
  235. case MIPI_DSI_FMT_RGB666_PACKED:
  236. return COL_FMT_18BPP;
  237. case MIPI_DSI_FMT_RGB888:
  238. return COL_FMT_24BPP;
  239. default:
  240. return COL_FMT_24BPP; /* for backward compatibility */
  241. }
  242. };
  243. static int rad_panel_prepare(struct drm_panel *panel)
  244. {
  245. struct rad_panel *rad = to_rad_panel(panel);
  246. int ret;
  247. ret = regulator_bulk_enable(rad->num_supplies, rad->supplies);
  248. if (ret)
  249. return ret;
  250. if (rad->reset) {
  251. gpiod_set_value_cansleep(rad->reset, 1);
  252. usleep_range(3000, 5000);
  253. gpiod_set_value_cansleep(rad->reset, 0);
  254. usleep_range(18000, 20000);
  255. }
  256. rad->prepared = true;
  257. return 0;
  258. }
  259. static int rad_panel_unprepare(struct drm_panel *panel)
  260. {
  261. struct rad_panel *rad = to_rad_panel(panel);
  262. int ret;
  263. /*
  264. * Right after asserting the reset, we need to release it, so that the
  265. * touch driver can have an active connection with the touch controller
  266. * even after the display is turned off.
  267. */
  268. if (rad->reset) {
  269. gpiod_set_value_cansleep(rad->reset, 1);
  270. usleep_range(15000, 17000);
  271. gpiod_set_value_cansleep(rad->reset, 0);
  272. }
  273. ret = regulator_bulk_disable(rad->num_supplies, rad->supplies);
  274. if (ret)
  275. return ret;
  276. rad->prepared = false;
  277. return 0;
  278. }
  279. static int rad_panel_enable(struct drm_panel *panel)
  280. {
  281. struct rad_panel *rad = to_rad_panel(panel);
  282. struct mipi_dsi_device *dsi = rad->dsi;
  283. struct device *dev = &dsi->dev;
  284. int color_format = color_format_from_dsi_format(dsi->format);
  285. int ret;
  286. dsi->mode_flags |= MIPI_DSI_MODE_LPM;
  287. ret = rad_panel_push_cmd_list(dsi);
  288. if (ret < 0) {
  289. dev_err(dev, "Failed to send MCS (%d)\n", ret);
  290. goto fail;
  291. }
  292. /* Select User Command Set table (CMD1) */
  293. ret = mipi_dsi_generic_write(dsi, (u8[]){ WRMAUCCTR, 0x00 }, 2);
  294. if (ret < 0)
  295. goto fail;
  296. /* Software reset */
  297. ret = mipi_dsi_dcs_soft_reset(dsi);
  298. if (ret < 0) {
  299. dev_err(dev, "Failed to do Software Reset (%d)\n", ret);
  300. goto fail;
  301. }
  302. usleep_range(15000, 17000);
  303. /* Set DSI mode */
  304. ret = mipi_dsi_generic_write(dsi, (u8[]){ 0xC2, 0x0B }, 2);
  305. if (ret < 0) {
  306. dev_err(dev, "Failed to set DSI mode (%d)\n", ret);
  307. goto fail;
  308. }
  309. /* Set tear ON */
  310. ret = mipi_dsi_dcs_set_tear_on(dsi, MIPI_DSI_DCS_TEAR_MODE_VBLANK);
  311. if (ret < 0) {
  312. dev_err(dev, "Failed to set tear ON (%d)\n", ret);
  313. goto fail;
  314. }
  315. /* Set tear scanline */
  316. ret = mipi_dsi_dcs_set_tear_scanline(dsi, 0x380);
  317. if (ret < 0) {
  318. dev_err(dev, "Failed to set tear scanline (%d)\n", ret);
  319. goto fail;
  320. }
  321. /* Set pixel format */
  322. ret = mipi_dsi_dcs_set_pixel_format(dsi, color_format);
  323. dev_dbg(dev, "Interface color format set to 0x%x\n", color_format);
  324. if (ret < 0) {
  325. dev_err(dev, "Failed to set pixel format (%d)\n", ret);
  326. goto fail;
  327. }
  328. /* Exit sleep mode */
  329. ret = mipi_dsi_dcs_exit_sleep_mode(dsi);
  330. if (ret < 0) {
  331. dev_err(dev, "Failed to exit sleep mode (%d)\n", ret);
  332. goto fail;
  333. }
  334. usleep_range(5000, 7000);
  335. ret = mipi_dsi_dcs_set_display_on(dsi);
  336. if (ret < 0) {
  337. dev_err(dev, "Failed to set display ON (%d)\n", ret);
  338. goto fail;
  339. }
  340. backlight_enable(rad->backlight);
  341. return 0;
  342. fail:
  343. gpiod_set_value_cansleep(rad->reset, 1);
  344. return ret;
  345. }
  346. static int rad_panel_disable(struct drm_panel *panel)
  347. {
  348. struct rad_panel *rad = to_rad_panel(panel);
  349. struct mipi_dsi_device *dsi = rad->dsi;
  350. struct device *dev = &dsi->dev;
  351. int ret;
  352. dsi->mode_flags |= MIPI_DSI_MODE_LPM;
  353. backlight_disable(rad->backlight);
  354. usleep_range(10000, 12000);
  355. ret = mipi_dsi_dcs_set_display_off(dsi);
  356. if (ret < 0) {
  357. dev_err(dev, "Failed to set display OFF (%d)\n", ret);
  358. return ret;
  359. }
  360. usleep_range(5000, 10000);
  361. ret = mipi_dsi_dcs_enter_sleep_mode(dsi);
  362. if (ret < 0) {
  363. dev_err(dev, "Failed to enter sleep mode (%d)\n", ret);
  364. return ret;
  365. }
  366. return 0;
  367. }
  368. static int rad_panel_get_modes(struct drm_panel *panel,
  369. struct drm_connector *connector)
  370. {
  371. struct drm_display_mode *mode;
  372. mode = drm_mode_duplicate(connector->dev, &default_mode);
  373. if (!mode) {
  374. dev_err(panel->dev, "failed to add mode %ux%u@%u\n",
  375. default_mode.hdisplay, default_mode.vdisplay,
  376. drm_mode_vrefresh(&default_mode));
  377. return -ENOMEM;
  378. }
  379. drm_mode_set_name(mode);
  380. mode->type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED;
  381. drm_mode_probed_add(connector, mode);
  382. connector->display_info.width_mm = mode->width_mm;
  383. connector->display_info.height_mm = mode->height_mm;
  384. connector->display_info.bus_flags = rad_bus_flags;
  385. drm_display_info_set_bus_formats(&connector->display_info,
  386. rad_bus_formats,
  387. ARRAY_SIZE(rad_bus_formats));
  388. return 1;
  389. }
  390. static int rad_bl_get_brightness(struct backlight_device *bl)
  391. {
  392. struct mipi_dsi_device *dsi = bl_get_data(bl);
  393. struct rad_panel *rad = mipi_dsi_get_drvdata(dsi);
  394. u16 brightness;
  395. int ret;
  396. if (!rad->prepared)
  397. return 0;
  398. dsi->mode_flags &= ~MIPI_DSI_MODE_LPM;
  399. ret = mipi_dsi_dcs_get_display_brightness(dsi, &brightness);
  400. if (ret < 0)
  401. return ret;
  402. bl->props.brightness = brightness;
  403. return brightness & 0xff;
  404. }
  405. static int rad_bl_update_status(struct backlight_device *bl)
  406. {
  407. struct mipi_dsi_device *dsi = bl_get_data(bl);
  408. struct rad_panel *rad = mipi_dsi_get_drvdata(dsi);
  409. int ret = 0;
  410. if (!rad->prepared)
  411. return 0;
  412. dsi->mode_flags &= ~MIPI_DSI_MODE_LPM;
  413. ret = mipi_dsi_dcs_set_display_brightness(dsi, bl->props.brightness);
  414. if (ret < 0)
  415. return ret;
  416. return 0;
  417. }
  418. static const struct backlight_ops rad_bl_ops = {
  419. .update_status = rad_bl_update_status,
  420. .get_brightness = rad_bl_get_brightness,
  421. };
  422. static const struct drm_panel_funcs rad_panel_funcs = {
  423. .prepare = rad_panel_prepare,
  424. .unprepare = rad_panel_unprepare,
  425. .enable = rad_panel_enable,
  426. .disable = rad_panel_disable,
  427. .get_modes = rad_panel_get_modes,
  428. };
  429. static const char * const rad_supply_names[] = {
  430. "v3p3",
  431. "v1p8",
  432. };
  433. static int rad_init_regulators(struct rad_panel *rad)
  434. {
  435. struct device *dev = &rad->dsi->dev;
  436. int i;
  437. rad->num_supplies = ARRAY_SIZE(rad_supply_names);
  438. rad->supplies = devm_kcalloc(dev, rad->num_supplies,
  439. sizeof(*rad->supplies), GFP_KERNEL);
  440. if (!rad->supplies)
  441. return -ENOMEM;
  442. for (i = 0; i < rad->num_supplies; i++)
  443. rad->supplies[i].supply = rad_supply_names[i];
  444. return devm_regulator_bulk_get(dev, rad->num_supplies, rad->supplies);
  445. };
  446. static int rad_panel_probe(struct mipi_dsi_device *dsi)
  447. {
  448. struct device *dev = &dsi->dev;
  449. struct device_node *np = dev->of_node;
  450. struct rad_panel *panel;
  451. struct backlight_properties bl_props;
  452. int ret;
  453. u32 video_mode;
  454. panel = devm_kzalloc(&dsi->dev, sizeof(*panel), GFP_KERNEL);
  455. if (!panel)
  456. return -ENOMEM;
  457. mipi_dsi_set_drvdata(dsi, panel);
  458. panel->dsi = dsi;
  459. dsi->format = MIPI_DSI_FMT_RGB888;
  460. dsi->mode_flags = MIPI_DSI_MODE_VIDEO_HSE | MIPI_DSI_MODE_VIDEO;
  461. ret = of_property_read_u32(np, "video-mode", &video_mode);
  462. if (!ret) {
  463. switch (video_mode) {
  464. case 0:
  465. /* burst mode */
  466. dsi->mode_flags |= MIPI_DSI_MODE_VIDEO_BURST;
  467. break;
  468. case 1:
  469. /* non-burst mode with sync event */
  470. break;
  471. case 2:
  472. /* non-burst mode with sync pulse */
  473. dsi->mode_flags |= MIPI_DSI_MODE_VIDEO_SYNC_PULSE;
  474. break;
  475. default:
  476. dev_warn(dev, "invalid video mode %d\n", video_mode);
  477. break;
  478. }
  479. }
  480. ret = of_property_read_u32(np, "dsi-lanes", &dsi->lanes);
  481. if (ret) {
  482. dev_err(dev, "Failed to get dsi-lanes property (%d)\n", ret);
  483. return ret;
  484. }
  485. panel->reset = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_LOW);
  486. if (IS_ERR(panel->reset))
  487. return PTR_ERR(panel->reset);
  488. memset(&bl_props, 0, sizeof(bl_props));
  489. bl_props.type = BACKLIGHT_RAW;
  490. bl_props.brightness = 255;
  491. bl_props.max_brightness = 255;
  492. panel->backlight = devm_backlight_device_register(dev, dev_name(dev),
  493. dev, dsi, &rad_bl_ops,
  494. &bl_props);
  495. if (IS_ERR(panel->backlight)) {
  496. ret = PTR_ERR(panel->backlight);
  497. dev_err(dev, "Failed to register backlight (%d)\n", ret);
  498. return ret;
  499. }
  500. ret = rad_init_regulators(panel);
  501. if (ret)
  502. return ret;
  503. drm_panel_init(&panel->panel, dev, &rad_panel_funcs,
  504. DRM_MODE_CONNECTOR_DSI);
  505. dev_set_drvdata(dev, panel);
  506. drm_panel_add(&panel->panel);
  507. ret = mipi_dsi_attach(dsi);
  508. if (ret)
  509. drm_panel_remove(&panel->panel);
  510. return ret;
  511. }
  512. static void rad_panel_remove(struct mipi_dsi_device *dsi)
  513. {
  514. struct rad_panel *rad = mipi_dsi_get_drvdata(dsi);
  515. struct device *dev = &dsi->dev;
  516. int ret;
  517. ret = mipi_dsi_detach(dsi);
  518. if (ret)
  519. dev_err(dev, "Failed to detach from host (%d)\n", ret);
  520. drm_panel_remove(&rad->panel);
  521. }
  522. static const struct of_device_id rad_of_match[] = {
  523. { .compatible = "raydium,rm67191", },
  524. { /* sentinel */ }
  525. };
  526. MODULE_DEVICE_TABLE(of, rad_of_match);
  527. static struct mipi_dsi_driver rad_panel_driver = {
  528. .driver = {
  529. .name = "panel-raydium-rm67191",
  530. .of_match_table = rad_of_match,
  531. },
  532. .probe = rad_panel_probe,
  533. .remove = rad_panel_remove,
  534. };
  535. module_mipi_dsi_driver(rad_panel_driver);
  536. MODULE_AUTHOR("Robert Chiras <robert.chiras@nxp.com>");
  537. MODULE_DESCRIPTION("DRM Driver for Raydium RM67191 MIPI DSI panel");
  538. MODULE_LICENSE("GPL v2");