panel-raydium-rm67191.c 14 KB

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