panel-dsi-cm.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. * Generic DSI Command Mode panel driver
  4. *
  5. * Copyright (C) 2013 Texas Instruments Incorporated - https://www.ti.com/
  6. * Author: Tomi Valkeinen <[email protected]>
  7. */
  8. #include <linux/backlight.h>
  9. #include <linux/delay.h>
  10. #include <linux/gpio/consumer.h>
  11. #include <linux/jiffies.h>
  12. #include <linux/module.h>
  13. #include <linux/of_device.h>
  14. #include <linux/regulator/consumer.h>
  15. #include <drm/drm_connector.h>
  16. #include <drm/drm_mipi_dsi.h>
  17. #include <drm/drm_modes.h>
  18. #include <drm/drm_panel.h>
  19. #include <video/mipi_display.h>
  20. #define DCS_GET_ID1 0xda
  21. #define DCS_GET_ID2 0xdb
  22. #define DCS_GET_ID3 0xdc
  23. #define DCS_REGULATOR_SUPPLY_NUM 2
  24. static const struct of_device_id dsicm_of_match[];
  25. struct dsic_panel_data {
  26. u32 xres;
  27. u32 yres;
  28. u32 refresh;
  29. u32 width_mm;
  30. u32 height_mm;
  31. u32 max_hs_rate;
  32. u32 max_lp_rate;
  33. bool te_support;
  34. };
  35. struct panel_drv_data {
  36. struct mipi_dsi_device *dsi;
  37. struct drm_panel panel;
  38. struct drm_display_mode mode;
  39. struct mutex lock;
  40. struct backlight_device *bldev;
  41. struct backlight_device *extbldev;
  42. unsigned long hw_guard_end; /* next value of jiffies when we can
  43. * issue the next sleep in/out command
  44. */
  45. unsigned long hw_guard_wait; /* max guard time in jiffies */
  46. const struct dsic_panel_data *panel_data;
  47. struct gpio_desc *reset_gpio;
  48. struct regulator_bulk_data supplies[DCS_REGULATOR_SUPPLY_NUM];
  49. bool use_dsi_backlight;
  50. /* runtime variables */
  51. bool enabled;
  52. bool intro_printed;
  53. };
  54. static inline struct panel_drv_data *panel_to_ddata(struct drm_panel *panel)
  55. {
  56. return container_of(panel, struct panel_drv_data, panel);
  57. }
  58. static void dsicm_bl_power(struct panel_drv_data *ddata, bool enable)
  59. {
  60. struct backlight_device *backlight;
  61. if (ddata->bldev)
  62. backlight = ddata->bldev;
  63. else if (ddata->extbldev)
  64. backlight = ddata->extbldev;
  65. else
  66. return;
  67. if (enable)
  68. backlight_enable(backlight);
  69. else
  70. backlight_disable(backlight);
  71. }
  72. static void hw_guard_start(struct panel_drv_data *ddata, int guard_msec)
  73. {
  74. ddata->hw_guard_wait = msecs_to_jiffies(guard_msec);
  75. ddata->hw_guard_end = jiffies + ddata->hw_guard_wait;
  76. }
  77. static void hw_guard_wait(struct panel_drv_data *ddata)
  78. {
  79. unsigned long wait = ddata->hw_guard_end - jiffies;
  80. if ((long)wait > 0 && wait <= ddata->hw_guard_wait) {
  81. set_current_state(TASK_UNINTERRUPTIBLE);
  82. schedule_timeout(wait);
  83. }
  84. }
  85. static int dsicm_dcs_read_1(struct panel_drv_data *ddata, u8 dcs_cmd, u8 *data)
  86. {
  87. return mipi_dsi_dcs_read(ddata->dsi, dcs_cmd, data, 1);
  88. }
  89. static int dsicm_dcs_write_1(struct panel_drv_data *ddata, u8 dcs_cmd, u8 param)
  90. {
  91. return mipi_dsi_dcs_write(ddata->dsi, dcs_cmd, &param, 1);
  92. }
  93. static int dsicm_sleep_in(struct panel_drv_data *ddata)
  94. {
  95. int r;
  96. hw_guard_wait(ddata);
  97. r = mipi_dsi_dcs_enter_sleep_mode(ddata->dsi);
  98. if (r)
  99. return r;
  100. hw_guard_start(ddata, 120);
  101. usleep_range(5000, 10000);
  102. return 0;
  103. }
  104. static int dsicm_sleep_out(struct panel_drv_data *ddata)
  105. {
  106. int r;
  107. hw_guard_wait(ddata);
  108. r = mipi_dsi_dcs_exit_sleep_mode(ddata->dsi);
  109. if (r)
  110. return r;
  111. hw_guard_start(ddata, 120);
  112. usleep_range(5000, 10000);
  113. return 0;
  114. }
  115. static int dsicm_get_id(struct panel_drv_data *ddata, u8 *id1, u8 *id2, u8 *id3)
  116. {
  117. int r;
  118. r = dsicm_dcs_read_1(ddata, DCS_GET_ID1, id1);
  119. if (r)
  120. return r;
  121. r = dsicm_dcs_read_1(ddata, DCS_GET_ID2, id2);
  122. if (r)
  123. return r;
  124. r = dsicm_dcs_read_1(ddata, DCS_GET_ID3, id3);
  125. if (r)
  126. return r;
  127. return 0;
  128. }
  129. static int dsicm_set_update_window(struct panel_drv_data *ddata)
  130. {
  131. struct mipi_dsi_device *dsi = ddata->dsi;
  132. int r;
  133. r = mipi_dsi_dcs_set_column_address(dsi, 0, ddata->mode.hdisplay - 1);
  134. if (r < 0)
  135. return r;
  136. r = mipi_dsi_dcs_set_page_address(dsi, 0, ddata->mode.vdisplay - 1);
  137. if (r < 0)
  138. return r;
  139. return 0;
  140. }
  141. static int dsicm_bl_update_status(struct backlight_device *dev)
  142. {
  143. struct panel_drv_data *ddata = dev_get_drvdata(&dev->dev);
  144. int r = 0;
  145. int level = backlight_get_brightness(dev);
  146. dev_dbg(&ddata->dsi->dev, "update brightness to %d\n", level);
  147. mutex_lock(&ddata->lock);
  148. if (ddata->enabled)
  149. r = dsicm_dcs_write_1(ddata, MIPI_DCS_SET_DISPLAY_BRIGHTNESS,
  150. level);
  151. mutex_unlock(&ddata->lock);
  152. return r;
  153. }
  154. static int dsicm_bl_get_intensity(struct backlight_device *dev)
  155. {
  156. return backlight_get_brightness(dev);
  157. }
  158. static const struct backlight_ops dsicm_bl_ops = {
  159. .get_brightness = dsicm_bl_get_intensity,
  160. .update_status = dsicm_bl_update_status,
  161. };
  162. static ssize_t num_dsi_errors_show(struct device *dev,
  163. struct device_attribute *attr, char *buf)
  164. {
  165. struct panel_drv_data *ddata = dev_get_drvdata(dev);
  166. u8 errors = 0;
  167. int r = -ENODEV;
  168. mutex_lock(&ddata->lock);
  169. if (ddata->enabled)
  170. r = dsicm_dcs_read_1(ddata, MIPI_DCS_GET_ERROR_COUNT_ON_DSI, &errors);
  171. mutex_unlock(&ddata->lock);
  172. if (r)
  173. return r;
  174. return sysfs_emit(buf, "%d\n", errors);
  175. }
  176. static ssize_t hw_revision_show(struct device *dev,
  177. struct device_attribute *attr, char *buf)
  178. {
  179. struct panel_drv_data *ddata = dev_get_drvdata(dev);
  180. u8 id1, id2, id3;
  181. int r = -ENODEV;
  182. mutex_lock(&ddata->lock);
  183. if (ddata->enabled)
  184. r = dsicm_get_id(ddata, &id1, &id2, &id3);
  185. mutex_unlock(&ddata->lock);
  186. if (r)
  187. return r;
  188. return sysfs_emit(buf, "%02x.%02x.%02x\n", id1, id2, id3);
  189. }
  190. static DEVICE_ATTR_RO(num_dsi_errors);
  191. static DEVICE_ATTR_RO(hw_revision);
  192. static struct attribute *dsicm_attrs[] = {
  193. &dev_attr_num_dsi_errors.attr,
  194. &dev_attr_hw_revision.attr,
  195. NULL,
  196. };
  197. static const struct attribute_group dsicm_attr_group = {
  198. .attrs = dsicm_attrs,
  199. };
  200. static void dsicm_hw_reset(struct panel_drv_data *ddata)
  201. {
  202. gpiod_set_value(ddata->reset_gpio, 1);
  203. udelay(10);
  204. /* reset the panel */
  205. gpiod_set_value(ddata->reset_gpio, 0);
  206. /* assert reset */
  207. udelay(10);
  208. gpiod_set_value(ddata->reset_gpio, 1);
  209. /* wait after releasing reset */
  210. usleep_range(5000, 10000);
  211. }
  212. static int dsicm_power_on(struct panel_drv_data *ddata)
  213. {
  214. u8 id1, id2, id3;
  215. int r;
  216. dsicm_hw_reset(ddata);
  217. ddata->dsi->mode_flags |= MIPI_DSI_MODE_LPM;
  218. r = dsicm_sleep_out(ddata);
  219. if (r)
  220. goto err;
  221. r = dsicm_get_id(ddata, &id1, &id2, &id3);
  222. if (r)
  223. goto err;
  224. r = dsicm_dcs_write_1(ddata, MIPI_DCS_SET_DISPLAY_BRIGHTNESS, 0xff);
  225. if (r)
  226. goto err;
  227. r = dsicm_dcs_write_1(ddata, MIPI_DCS_WRITE_CONTROL_DISPLAY,
  228. (1<<2) | (1<<5)); /* BL | BCTRL */
  229. if (r)
  230. goto err;
  231. r = mipi_dsi_dcs_set_pixel_format(ddata->dsi, MIPI_DCS_PIXEL_FMT_24BIT);
  232. if (r)
  233. goto err;
  234. r = dsicm_set_update_window(ddata);
  235. if (r)
  236. goto err;
  237. r = mipi_dsi_dcs_set_display_on(ddata->dsi);
  238. if (r)
  239. goto err;
  240. if (ddata->panel_data->te_support) {
  241. r = mipi_dsi_dcs_set_tear_on(ddata->dsi, MIPI_DSI_DCS_TEAR_MODE_VBLANK);
  242. if (r)
  243. goto err;
  244. }
  245. /* possible panel bug */
  246. msleep(100);
  247. ddata->enabled = true;
  248. if (!ddata->intro_printed) {
  249. dev_info(&ddata->dsi->dev, "panel revision %02x.%02x.%02x\n",
  250. id1, id2, id3);
  251. ddata->intro_printed = true;
  252. }
  253. ddata->dsi->mode_flags &= ~MIPI_DSI_MODE_LPM;
  254. return 0;
  255. err:
  256. dev_err(&ddata->dsi->dev, "error while enabling panel, issuing HW reset\n");
  257. dsicm_hw_reset(ddata);
  258. return r;
  259. }
  260. static int dsicm_power_off(struct panel_drv_data *ddata)
  261. {
  262. int r;
  263. ddata->enabled = false;
  264. r = mipi_dsi_dcs_set_display_off(ddata->dsi);
  265. if (!r)
  266. r = dsicm_sleep_in(ddata);
  267. if (r) {
  268. dev_err(&ddata->dsi->dev,
  269. "error disabling panel, issuing HW reset\n");
  270. dsicm_hw_reset(ddata);
  271. }
  272. return r;
  273. }
  274. static int dsicm_prepare(struct drm_panel *panel)
  275. {
  276. struct panel_drv_data *ddata = panel_to_ddata(panel);
  277. int r;
  278. r = regulator_bulk_enable(ARRAY_SIZE(ddata->supplies), ddata->supplies);
  279. if (r)
  280. dev_err(&ddata->dsi->dev, "failed to enable supplies: %d\n", r);
  281. return r;
  282. }
  283. static int dsicm_enable(struct drm_panel *panel)
  284. {
  285. struct panel_drv_data *ddata = panel_to_ddata(panel);
  286. int r;
  287. mutex_lock(&ddata->lock);
  288. r = dsicm_power_on(ddata);
  289. if (r)
  290. goto err;
  291. mutex_unlock(&ddata->lock);
  292. dsicm_bl_power(ddata, true);
  293. return 0;
  294. err:
  295. dev_err(&ddata->dsi->dev, "enable failed (%d)\n", r);
  296. mutex_unlock(&ddata->lock);
  297. return r;
  298. }
  299. static int dsicm_unprepare(struct drm_panel *panel)
  300. {
  301. struct panel_drv_data *ddata = panel_to_ddata(panel);
  302. int r;
  303. r = regulator_bulk_disable(ARRAY_SIZE(ddata->supplies), ddata->supplies);
  304. if (r)
  305. dev_err(&ddata->dsi->dev, "failed to disable supplies: %d\n", r);
  306. return r;
  307. }
  308. static int dsicm_disable(struct drm_panel *panel)
  309. {
  310. struct panel_drv_data *ddata = panel_to_ddata(panel);
  311. int r;
  312. dsicm_bl_power(ddata, false);
  313. mutex_lock(&ddata->lock);
  314. r = dsicm_power_off(ddata);
  315. mutex_unlock(&ddata->lock);
  316. return r;
  317. }
  318. static int dsicm_get_modes(struct drm_panel *panel,
  319. struct drm_connector *connector)
  320. {
  321. struct panel_drv_data *ddata = panel_to_ddata(panel);
  322. struct drm_display_mode *mode;
  323. mode = drm_mode_duplicate(connector->dev, &ddata->mode);
  324. if (!mode) {
  325. dev_err(&ddata->dsi->dev, "failed to add mode %ux%ux@%u kHz\n",
  326. ddata->mode.hdisplay, ddata->mode.vdisplay,
  327. ddata->mode.clock);
  328. return -ENOMEM;
  329. }
  330. connector->display_info.width_mm = ddata->panel_data->width_mm;
  331. connector->display_info.height_mm = ddata->panel_data->height_mm;
  332. drm_mode_probed_add(connector, mode);
  333. return 1;
  334. }
  335. static const struct drm_panel_funcs dsicm_panel_funcs = {
  336. .unprepare = dsicm_unprepare,
  337. .disable = dsicm_disable,
  338. .prepare = dsicm_prepare,
  339. .enable = dsicm_enable,
  340. .get_modes = dsicm_get_modes,
  341. };
  342. static int dsicm_probe_of(struct mipi_dsi_device *dsi)
  343. {
  344. struct backlight_device *backlight;
  345. struct panel_drv_data *ddata = mipi_dsi_get_drvdata(dsi);
  346. int err;
  347. struct drm_display_mode *mode = &ddata->mode;
  348. ddata->reset_gpio = devm_gpiod_get(&dsi->dev, "reset", GPIOD_OUT_LOW);
  349. if (IS_ERR(ddata->reset_gpio)) {
  350. err = PTR_ERR(ddata->reset_gpio);
  351. dev_err(&dsi->dev, "reset gpio request failed: %d", err);
  352. return err;
  353. }
  354. mode->hdisplay = mode->hsync_start = mode->hsync_end = mode->htotal =
  355. ddata->panel_data->xres;
  356. mode->vdisplay = mode->vsync_start = mode->vsync_end = mode->vtotal =
  357. ddata->panel_data->yres;
  358. mode->clock = ddata->panel_data->xres * ddata->panel_data->yres *
  359. ddata->panel_data->refresh / 1000;
  360. mode->width_mm = ddata->panel_data->width_mm;
  361. mode->height_mm = ddata->panel_data->height_mm;
  362. mode->type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED;
  363. drm_mode_set_name(mode);
  364. ddata->supplies[0].supply = "vpnl";
  365. ddata->supplies[1].supply = "vddi";
  366. err = devm_regulator_bulk_get(&dsi->dev, ARRAY_SIZE(ddata->supplies),
  367. ddata->supplies);
  368. if (err)
  369. return err;
  370. backlight = devm_of_find_backlight(&dsi->dev);
  371. if (IS_ERR(backlight))
  372. return PTR_ERR(backlight);
  373. /* If no backlight device is found assume native backlight support */
  374. if (backlight)
  375. ddata->extbldev = backlight;
  376. else
  377. ddata->use_dsi_backlight = true;
  378. return 0;
  379. }
  380. static int dsicm_probe(struct mipi_dsi_device *dsi)
  381. {
  382. struct panel_drv_data *ddata;
  383. struct backlight_device *bldev = NULL;
  384. struct device *dev = &dsi->dev;
  385. int r;
  386. dev_dbg(dev, "probe\n");
  387. ddata = devm_kzalloc(dev, sizeof(*ddata), GFP_KERNEL);
  388. if (!ddata)
  389. return -ENOMEM;
  390. mipi_dsi_set_drvdata(dsi, ddata);
  391. ddata->dsi = dsi;
  392. ddata->panel_data = of_device_get_match_data(dev);
  393. if (!ddata->panel_data)
  394. return -ENODEV;
  395. r = dsicm_probe_of(dsi);
  396. if (r)
  397. return r;
  398. mutex_init(&ddata->lock);
  399. dsicm_hw_reset(ddata);
  400. drm_panel_init(&ddata->panel, dev, &dsicm_panel_funcs,
  401. DRM_MODE_CONNECTOR_DSI);
  402. if (ddata->use_dsi_backlight) {
  403. struct backlight_properties props = { 0 };
  404. props.max_brightness = 255;
  405. props.type = BACKLIGHT_RAW;
  406. bldev = devm_backlight_device_register(dev, dev_name(dev),
  407. dev, ddata, &dsicm_bl_ops, &props);
  408. if (IS_ERR(bldev)) {
  409. r = PTR_ERR(bldev);
  410. goto err_bl;
  411. }
  412. ddata->bldev = bldev;
  413. }
  414. r = sysfs_create_group(&dev->kobj, &dsicm_attr_group);
  415. if (r) {
  416. dev_err(dev, "failed to create sysfs files\n");
  417. goto err_bl;
  418. }
  419. dsi->lanes = 2;
  420. dsi->format = MIPI_DSI_FMT_RGB888;
  421. dsi->mode_flags = MIPI_DSI_CLOCK_NON_CONTINUOUS |
  422. MIPI_DSI_MODE_NO_EOT_PACKET;
  423. dsi->hs_rate = ddata->panel_data->max_hs_rate;
  424. dsi->lp_rate = ddata->panel_data->max_lp_rate;
  425. drm_panel_add(&ddata->panel);
  426. r = mipi_dsi_attach(dsi);
  427. if (r < 0)
  428. goto err_dsi_attach;
  429. return 0;
  430. err_dsi_attach:
  431. drm_panel_remove(&ddata->panel);
  432. sysfs_remove_group(&dsi->dev.kobj, &dsicm_attr_group);
  433. err_bl:
  434. if (ddata->extbldev)
  435. put_device(&ddata->extbldev->dev);
  436. return r;
  437. }
  438. static void dsicm_remove(struct mipi_dsi_device *dsi)
  439. {
  440. struct panel_drv_data *ddata = mipi_dsi_get_drvdata(dsi);
  441. dev_dbg(&dsi->dev, "remove\n");
  442. mipi_dsi_detach(dsi);
  443. drm_panel_remove(&ddata->panel);
  444. sysfs_remove_group(&dsi->dev.kobj, &dsicm_attr_group);
  445. if (ddata->extbldev)
  446. put_device(&ddata->extbldev->dev);
  447. }
  448. static const struct dsic_panel_data taal_data = {
  449. .xres = 864,
  450. .yres = 480,
  451. .refresh = 60,
  452. .width_mm = 0,
  453. .height_mm = 0,
  454. .max_hs_rate = 300000000,
  455. .max_lp_rate = 10000000,
  456. .te_support = true,
  457. };
  458. static const struct dsic_panel_data himalaya_data = {
  459. .xres = 480,
  460. .yres = 864,
  461. .refresh = 60,
  462. .width_mm = 49,
  463. .height_mm = 88,
  464. .max_hs_rate = 300000000,
  465. .max_lp_rate = 10000000,
  466. .te_support = false,
  467. };
  468. static const struct dsic_panel_data droid4_data = {
  469. .xres = 540,
  470. .yres = 960,
  471. .refresh = 60,
  472. .width_mm = 50,
  473. .height_mm = 89,
  474. .max_hs_rate = 300000000,
  475. .max_lp_rate = 10000000,
  476. .te_support = false,
  477. };
  478. static const struct of_device_id dsicm_of_match[] = {
  479. { .compatible = "tpo,taal", .data = &taal_data },
  480. { .compatible = "nokia,himalaya", &himalaya_data },
  481. { .compatible = "motorola,droid4-panel", &droid4_data },
  482. {},
  483. };
  484. MODULE_DEVICE_TABLE(of, dsicm_of_match);
  485. static struct mipi_dsi_driver dsicm_driver = {
  486. .probe = dsicm_probe,
  487. .remove = dsicm_remove,
  488. .driver = {
  489. .name = "panel-dsi-cm",
  490. .of_match_table = dsicm_of_match,
  491. },
  492. };
  493. module_mipi_dsi_driver(dsicm_driver);
  494. MODULE_AUTHOR("Tomi Valkeinen <[email protected]>");
  495. MODULE_DESCRIPTION("Generic DSI Command Mode Panel Driver");
  496. MODULE_LICENSE("GPL");