panel-raydium-rm67191.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659
  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. bool enabled;
  196. };
  197. static const struct drm_display_mode default_mode = {
  198. .clock = 132000,
  199. .hdisplay = 1080,
  200. .hsync_start = 1080 + 20,
  201. .hsync_end = 1080 + 20 + 2,
  202. .htotal = 1080 + 20 + 2 + 34,
  203. .vdisplay = 1920,
  204. .vsync_start = 1920 + 10,
  205. .vsync_end = 1920 + 10 + 2,
  206. .vtotal = 1920 + 10 + 2 + 4,
  207. .width_mm = 68,
  208. .height_mm = 121,
  209. .flags = DRM_MODE_FLAG_NHSYNC |
  210. DRM_MODE_FLAG_NVSYNC,
  211. };
  212. static inline struct rad_panel *to_rad_panel(struct drm_panel *panel)
  213. {
  214. return container_of(panel, struct rad_panel, panel);
  215. }
  216. static int rad_panel_push_cmd_list(struct mipi_dsi_device *dsi)
  217. {
  218. size_t i;
  219. size_t count = ARRAY_SIZE(manufacturer_cmd_set);
  220. int ret = 0;
  221. for (i = 0; i < count; i++) {
  222. const struct cmd_set_entry *entry = &manufacturer_cmd_set[i];
  223. u8 buffer[2] = { entry->cmd, entry->param };
  224. ret = mipi_dsi_generic_write(dsi, &buffer, sizeof(buffer));
  225. if (ret < 0)
  226. return ret;
  227. }
  228. return ret;
  229. };
  230. static int color_format_from_dsi_format(enum mipi_dsi_pixel_format format)
  231. {
  232. switch (format) {
  233. case MIPI_DSI_FMT_RGB565:
  234. return COL_FMT_16BPP;
  235. case MIPI_DSI_FMT_RGB666:
  236. case MIPI_DSI_FMT_RGB666_PACKED:
  237. return COL_FMT_18BPP;
  238. case MIPI_DSI_FMT_RGB888:
  239. return COL_FMT_24BPP;
  240. default:
  241. return COL_FMT_24BPP; /* for backward compatibility */
  242. }
  243. };
  244. static int rad_panel_prepare(struct drm_panel *panel)
  245. {
  246. struct rad_panel *rad = to_rad_panel(panel);
  247. int ret;
  248. if (rad->prepared)
  249. return 0;
  250. ret = regulator_bulk_enable(rad->num_supplies, rad->supplies);
  251. if (ret)
  252. return ret;
  253. if (rad->reset) {
  254. gpiod_set_value_cansleep(rad->reset, 1);
  255. usleep_range(3000, 5000);
  256. gpiod_set_value_cansleep(rad->reset, 0);
  257. usleep_range(18000, 20000);
  258. }
  259. rad->prepared = true;
  260. return 0;
  261. }
  262. static int rad_panel_unprepare(struct drm_panel *panel)
  263. {
  264. struct rad_panel *rad = to_rad_panel(panel);
  265. int ret;
  266. if (!rad->prepared)
  267. return 0;
  268. /*
  269. * Right after asserting the reset, we need to release it, so that the
  270. * touch driver can have an active connection with the touch controller
  271. * even after the display is turned off.
  272. */
  273. if (rad->reset) {
  274. gpiod_set_value_cansleep(rad->reset, 1);
  275. usleep_range(15000, 17000);
  276. gpiod_set_value_cansleep(rad->reset, 0);
  277. }
  278. ret = regulator_bulk_disable(rad->num_supplies, rad->supplies);
  279. if (ret)
  280. return ret;
  281. rad->prepared = false;
  282. return 0;
  283. }
  284. static int rad_panel_enable(struct drm_panel *panel)
  285. {
  286. struct rad_panel *rad = to_rad_panel(panel);
  287. struct mipi_dsi_device *dsi = rad->dsi;
  288. struct device *dev = &dsi->dev;
  289. int color_format = color_format_from_dsi_format(dsi->format);
  290. int ret;
  291. if (rad->enabled)
  292. return 0;
  293. dsi->mode_flags |= MIPI_DSI_MODE_LPM;
  294. ret = rad_panel_push_cmd_list(dsi);
  295. if (ret < 0) {
  296. dev_err(dev, "Failed to send MCS (%d)\n", ret);
  297. goto fail;
  298. }
  299. /* Select User Command Set table (CMD1) */
  300. ret = mipi_dsi_generic_write(dsi, (u8[]){ WRMAUCCTR, 0x00 }, 2);
  301. if (ret < 0)
  302. goto fail;
  303. /* Software reset */
  304. ret = mipi_dsi_dcs_soft_reset(dsi);
  305. if (ret < 0) {
  306. dev_err(dev, "Failed to do Software Reset (%d)\n", ret);
  307. goto fail;
  308. }
  309. usleep_range(15000, 17000);
  310. /* Set DSI mode */
  311. ret = mipi_dsi_generic_write(dsi, (u8[]){ 0xC2, 0x0B }, 2);
  312. if (ret < 0) {
  313. dev_err(dev, "Failed to set DSI mode (%d)\n", ret);
  314. goto fail;
  315. }
  316. /* Set tear ON */
  317. ret = mipi_dsi_dcs_set_tear_on(dsi, MIPI_DSI_DCS_TEAR_MODE_VBLANK);
  318. if (ret < 0) {
  319. dev_err(dev, "Failed to set tear ON (%d)\n", ret);
  320. goto fail;
  321. }
  322. /* Set tear scanline */
  323. ret = mipi_dsi_dcs_set_tear_scanline(dsi, 0x380);
  324. if (ret < 0) {
  325. dev_err(dev, "Failed to set tear scanline (%d)\n", ret);
  326. goto fail;
  327. }
  328. /* Set pixel format */
  329. ret = mipi_dsi_dcs_set_pixel_format(dsi, color_format);
  330. dev_dbg(dev, "Interface color format set to 0x%x\n", color_format);
  331. if (ret < 0) {
  332. dev_err(dev, "Failed to set pixel format (%d)\n", ret);
  333. goto fail;
  334. }
  335. /* Exit sleep mode */
  336. ret = mipi_dsi_dcs_exit_sleep_mode(dsi);
  337. if (ret < 0) {
  338. dev_err(dev, "Failed to exit sleep mode (%d)\n", ret);
  339. goto fail;
  340. }
  341. usleep_range(5000, 7000);
  342. ret = mipi_dsi_dcs_set_display_on(dsi);
  343. if (ret < 0) {
  344. dev_err(dev, "Failed to set display ON (%d)\n", ret);
  345. goto fail;
  346. }
  347. backlight_enable(rad->backlight);
  348. rad->enabled = true;
  349. return 0;
  350. fail:
  351. gpiod_set_value_cansleep(rad->reset, 1);
  352. return ret;
  353. }
  354. static int rad_panel_disable(struct drm_panel *panel)
  355. {
  356. struct rad_panel *rad = to_rad_panel(panel);
  357. struct mipi_dsi_device *dsi = rad->dsi;
  358. struct device *dev = &dsi->dev;
  359. int ret;
  360. if (!rad->enabled)
  361. return 0;
  362. dsi->mode_flags |= MIPI_DSI_MODE_LPM;
  363. backlight_disable(rad->backlight);
  364. usleep_range(10000, 12000);
  365. ret = mipi_dsi_dcs_set_display_off(dsi);
  366. if (ret < 0) {
  367. dev_err(dev, "Failed to set display OFF (%d)\n", ret);
  368. return ret;
  369. }
  370. usleep_range(5000, 10000);
  371. ret = mipi_dsi_dcs_enter_sleep_mode(dsi);
  372. if (ret < 0) {
  373. dev_err(dev, "Failed to enter sleep mode (%d)\n", ret);
  374. return ret;
  375. }
  376. rad->enabled = false;
  377. return 0;
  378. }
  379. static int rad_panel_get_modes(struct drm_panel *panel,
  380. struct drm_connector *connector)
  381. {
  382. struct drm_display_mode *mode;
  383. mode = drm_mode_duplicate(connector->dev, &default_mode);
  384. if (!mode) {
  385. dev_err(panel->dev, "failed to add mode %ux%u@%u\n",
  386. default_mode.hdisplay, default_mode.vdisplay,
  387. drm_mode_vrefresh(&default_mode));
  388. return -ENOMEM;
  389. }
  390. drm_mode_set_name(mode);
  391. mode->type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED;
  392. drm_mode_probed_add(connector, mode);
  393. connector->display_info.width_mm = mode->width_mm;
  394. connector->display_info.height_mm = mode->height_mm;
  395. connector->display_info.bus_flags = rad_bus_flags;
  396. drm_display_info_set_bus_formats(&connector->display_info,
  397. rad_bus_formats,
  398. ARRAY_SIZE(rad_bus_formats));
  399. return 1;
  400. }
  401. static int rad_bl_get_brightness(struct backlight_device *bl)
  402. {
  403. struct mipi_dsi_device *dsi = bl_get_data(bl);
  404. struct rad_panel *rad = mipi_dsi_get_drvdata(dsi);
  405. u16 brightness;
  406. int ret;
  407. if (!rad->prepared)
  408. return 0;
  409. dsi->mode_flags &= ~MIPI_DSI_MODE_LPM;
  410. ret = mipi_dsi_dcs_get_display_brightness(dsi, &brightness);
  411. if (ret < 0)
  412. return ret;
  413. bl->props.brightness = brightness;
  414. return brightness & 0xff;
  415. }
  416. static int rad_bl_update_status(struct backlight_device *bl)
  417. {
  418. struct mipi_dsi_device *dsi = bl_get_data(bl);
  419. struct rad_panel *rad = mipi_dsi_get_drvdata(dsi);
  420. int ret = 0;
  421. if (!rad->prepared)
  422. return 0;
  423. dsi->mode_flags &= ~MIPI_DSI_MODE_LPM;
  424. ret = mipi_dsi_dcs_set_display_brightness(dsi, bl->props.brightness);
  425. if (ret < 0)
  426. return ret;
  427. return 0;
  428. }
  429. static const struct backlight_ops rad_bl_ops = {
  430. .update_status = rad_bl_update_status,
  431. .get_brightness = rad_bl_get_brightness,
  432. };
  433. static const struct drm_panel_funcs rad_panel_funcs = {
  434. .prepare = rad_panel_prepare,
  435. .unprepare = rad_panel_unprepare,
  436. .enable = rad_panel_enable,
  437. .disable = rad_panel_disable,
  438. .get_modes = rad_panel_get_modes,
  439. };
  440. static const char * const rad_supply_names[] = {
  441. "v3p3",
  442. "v1p8",
  443. };
  444. static int rad_init_regulators(struct rad_panel *rad)
  445. {
  446. struct device *dev = &rad->dsi->dev;
  447. int i;
  448. rad->num_supplies = ARRAY_SIZE(rad_supply_names);
  449. rad->supplies = devm_kcalloc(dev, rad->num_supplies,
  450. sizeof(*rad->supplies), GFP_KERNEL);
  451. if (!rad->supplies)
  452. return -ENOMEM;
  453. for (i = 0; i < rad->num_supplies; i++)
  454. rad->supplies[i].supply = rad_supply_names[i];
  455. return devm_regulator_bulk_get(dev, rad->num_supplies, rad->supplies);
  456. };
  457. static int rad_panel_probe(struct mipi_dsi_device *dsi)
  458. {
  459. struct device *dev = &dsi->dev;
  460. struct device_node *np = dev->of_node;
  461. struct rad_panel *panel;
  462. struct backlight_properties bl_props;
  463. int ret;
  464. u32 video_mode;
  465. panel = devm_kzalloc(&dsi->dev, sizeof(*panel), GFP_KERNEL);
  466. if (!panel)
  467. return -ENOMEM;
  468. mipi_dsi_set_drvdata(dsi, panel);
  469. panel->dsi = dsi;
  470. dsi->format = MIPI_DSI_FMT_RGB888;
  471. dsi->mode_flags = MIPI_DSI_MODE_VIDEO_HSE | MIPI_DSI_MODE_VIDEO;
  472. ret = of_property_read_u32(np, "video-mode", &video_mode);
  473. if (!ret) {
  474. switch (video_mode) {
  475. case 0:
  476. /* burst mode */
  477. dsi->mode_flags |= MIPI_DSI_MODE_VIDEO_BURST;
  478. break;
  479. case 1:
  480. /* non-burst mode with sync event */
  481. break;
  482. case 2:
  483. /* non-burst mode with sync pulse */
  484. dsi->mode_flags |= MIPI_DSI_MODE_VIDEO_SYNC_PULSE;
  485. break;
  486. default:
  487. dev_warn(dev, "invalid video mode %d\n", video_mode);
  488. break;
  489. }
  490. }
  491. ret = of_property_read_u32(np, "dsi-lanes", &dsi->lanes);
  492. if (ret) {
  493. dev_err(dev, "Failed to get dsi-lanes property (%d)\n", ret);
  494. return ret;
  495. }
  496. panel->reset = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_LOW);
  497. if (IS_ERR(panel->reset))
  498. return PTR_ERR(panel->reset);
  499. memset(&bl_props, 0, sizeof(bl_props));
  500. bl_props.type = BACKLIGHT_RAW;
  501. bl_props.brightness = 255;
  502. bl_props.max_brightness = 255;
  503. panel->backlight = devm_backlight_device_register(dev, dev_name(dev),
  504. dev, dsi, &rad_bl_ops,
  505. &bl_props);
  506. if (IS_ERR(panel->backlight)) {
  507. ret = PTR_ERR(panel->backlight);
  508. dev_err(dev, "Failed to register backlight (%d)\n", ret);
  509. return ret;
  510. }
  511. ret = rad_init_regulators(panel);
  512. if (ret)
  513. return ret;
  514. drm_panel_init(&panel->panel, dev, &rad_panel_funcs,
  515. DRM_MODE_CONNECTOR_DSI);
  516. dev_set_drvdata(dev, panel);
  517. drm_panel_add(&panel->panel);
  518. ret = mipi_dsi_attach(dsi);
  519. if (ret)
  520. drm_panel_remove(&panel->panel);
  521. return ret;
  522. }
  523. static void rad_panel_remove(struct mipi_dsi_device *dsi)
  524. {
  525. struct rad_panel *rad = mipi_dsi_get_drvdata(dsi);
  526. struct device *dev = &dsi->dev;
  527. int ret;
  528. ret = mipi_dsi_detach(dsi);
  529. if (ret)
  530. dev_err(dev, "Failed to detach from host (%d)\n", ret);
  531. drm_panel_remove(&rad->panel);
  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 <[email protected]>");
  555. MODULE_DESCRIPTION("DRM Driver for Raydium RM67191 MIPI DSI panel");
  556. MODULE_LICENSE("GPL v2");