panel-sony-tulip-truly-nt35521.c 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. * Copyright (c) 2021, Linaro Limited
  4. *
  5. * Generated with linux-mdss-dsi-panel-driver-generator from vendor device tree:
  6. * Copyright (c) 2013, The Linux Foundation. All rights reserved.
  7. */
  8. #include <linux/backlight.h>
  9. #include <linux/delay.h>
  10. #include <linux/gpio/consumer.h>
  11. #include <linux/module.h>
  12. #include <linux/of.h>
  13. #include <linux/regulator/consumer.h>
  14. #include <drm/drm_mipi_dsi.h>
  15. #include <drm/drm_modes.h>
  16. #include <drm/drm_panel.h>
  17. struct truly_nt35521 {
  18. struct drm_panel panel;
  19. struct mipi_dsi_device *dsi;
  20. struct regulator_bulk_data supplies[2];
  21. struct gpio_desc *reset_gpio;
  22. struct gpio_desc *blen_gpio;
  23. bool prepared;
  24. bool enabled;
  25. };
  26. static inline
  27. struct truly_nt35521 *to_truly_nt35521(struct drm_panel *panel)
  28. {
  29. return container_of(panel, struct truly_nt35521, panel);
  30. }
  31. #define dsi_generic_write_seq(dsi, seq...) do { \
  32. static const u8 d[] = { seq }; \
  33. int ret; \
  34. ret = mipi_dsi_generic_write(dsi, d, ARRAY_SIZE(d)); \
  35. if (ret < 0) \
  36. return ret; \
  37. } while (0)
  38. static void truly_nt35521_reset(struct truly_nt35521 *ctx)
  39. {
  40. gpiod_set_value_cansleep(ctx->reset_gpio, 1);
  41. usleep_range(1000, 2000);
  42. gpiod_set_value_cansleep(ctx->reset_gpio, 1);
  43. usleep_range(10000, 11000);
  44. gpiod_set_value_cansleep(ctx->reset_gpio, 0);
  45. msleep(150);
  46. }
  47. static int truly_nt35521_on(struct truly_nt35521 *ctx)
  48. {
  49. struct mipi_dsi_device *dsi = ctx->dsi;
  50. struct device *dev = &dsi->dev;
  51. int ret;
  52. dsi->mode_flags |= MIPI_DSI_MODE_LPM;
  53. dsi_generic_write_seq(dsi, 0xf0, 0x55, 0xaa, 0x52, 0x08, 0x00);
  54. dsi_generic_write_seq(dsi, 0xff, 0xaa, 0x55, 0xa5, 0x80);
  55. dsi_generic_write_seq(dsi, 0x6f, 0x11, 0x00);
  56. dsi_generic_write_seq(dsi, 0xf7, 0x20, 0x00);
  57. dsi_generic_write_seq(dsi, 0x6f, 0x01);
  58. dsi_generic_write_seq(dsi, 0xb1, 0x21);
  59. dsi_generic_write_seq(dsi, 0xbd, 0x01, 0xa0, 0x10, 0x08, 0x01);
  60. dsi_generic_write_seq(dsi, 0xb8, 0x01, 0x02, 0x0c, 0x02);
  61. dsi_generic_write_seq(dsi, 0xbb, 0x11, 0x11);
  62. dsi_generic_write_seq(dsi, 0xbc, 0x00, 0x00);
  63. dsi_generic_write_seq(dsi, 0xb6, 0x02);
  64. dsi_generic_write_seq(dsi, 0xf0, 0x55, 0xaa, 0x52, 0x08, 0x01);
  65. dsi_generic_write_seq(dsi, 0xb0, 0x09, 0x09);
  66. dsi_generic_write_seq(dsi, 0xb1, 0x09, 0x09);
  67. dsi_generic_write_seq(dsi, 0xbc, 0x8c, 0x00);
  68. dsi_generic_write_seq(dsi, 0xbd, 0x8c, 0x00);
  69. dsi_generic_write_seq(dsi, 0xca, 0x00);
  70. dsi_generic_write_seq(dsi, 0xc0, 0x04);
  71. dsi_generic_write_seq(dsi, 0xbe, 0xb5);
  72. dsi_generic_write_seq(dsi, 0xb3, 0x35, 0x35);
  73. dsi_generic_write_seq(dsi, 0xb4, 0x25, 0x25);
  74. dsi_generic_write_seq(dsi, 0xb9, 0x43, 0x43);
  75. dsi_generic_write_seq(dsi, 0xba, 0x24, 0x24);
  76. dsi_generic_write_seq(dsi, 0xf0, 0x55, 0xaa, 0x52, 0x08, 0x02);
  77. dsi_generic_write_seq(dsi, 0xee, 0x03);
  78. dsi_generic_write_seq(dsi, 0xb0,
  79. 0x00, 0xb2, 0x00, 0xb3, 0x00, 0xb6, 0x00, 0xc3,
  80. 0x00, 0xce, 0x00, 0xe1, 0x00, 0xf3, 0x01, 0x11);
  81. dsi_generic_write_seq(dsi, 0xb1,
  82. 0x01, 0x2e, 0x01, 0x5c, 0x01, 0x82, 0x01, 0xc3,
  83. 0x01, 0xfe, 0x02, 0x00, 0x02, 0x37, 0x02, 0x77);
  84. dsi_generic_write_seq(dsi, 0xb2,
  85. 0x02, 0xa1, 0x02, 0xd7, 0x02, 0xfe, 0x03, 0x2c,
  86. 0x03, 0x4b, 0x03, 0x63, 0x03, 0x8f, 0x03, 0x90);
  87. dsi_generic_write_seq(dsi, 0xb3, 0x03, 0x96, 0x03, 0x98);
  88. dsi_generic_write_seq(dsi, 0xb4,
  89. 0x00, 0x81, 0x00, 0x8b, 0x00, 0x9c, 0x00, 0xa9,
  90. 0x00, 0xb5, 0x00, 0xcb, 0x00, 0xdf, 0x01, 0x02);
  91. dsi_generic_write_seq(dsi, 0xb5,
  92. 0x01, 0x1f, 0x01, 0x51, 0x01, 0x7a, 0x01, 0xbf,
  93. 0x01, 0xfa, 0x01, 0xfc, 0x02, 0x34, 0x02, 0x76);
  94. dsi_generic_write_seq(dsi, 0xb6,
  95. 0x02, 0x9f, 0x02, 0xd7, 0x02, 0xfc, 0x03, 0x2c,
  96. 0x03, 0x4a, 0x03, 0x63, 0x03, 0x8f, 0x03, 0xa2);
  97. dsi_generic_write_seq(dsi, 0xb7, 0x03, 0xb8, 0x03, 0xba);
  98. dsi_generic_write_seq(dsi, 0xb8,
  99. 0x00, 0x01, 0x00, 0x02, 0x00, 0x0e, 0x00, 0x2a,
  100. 0x00, 0x41, 0x00, 0x67, 0x00, 0x87, 0x00, 0xb9);
  101. dsi_generic_write_seq(dsi, 0xb9,
  102. 0x00, 0xe2, 0x01, 0x22, 0x01, 0x54, 0x01, 0xa3,
  103. 0x01, 0xe6, 0x01, 0xe7, 0x02, 0x24, 0x02, 0x67);
  104. dsi_generic_write_seq(dsi, 0xba,
  105. 0x02, 0x93, 0x02, 0xcd, 0x02, 0xf6, 0x03, 0x31,
  106. 0x03, 0x6c, 0x03, 0xe9, 0x03, 0xef, 0x03, 0xf4);
  107. dsi_generic_write_seq(dsi, 0xbb, 0x03, 0xf6, 0x03, 0xf7);
  108. dsi_generic_write_seq(dsi, 0xf0, 0x55, 0xaa, 0x52, 0x08, 0x03);
  109. dsi_generic_write_seq(dsi, 0xb0, 0x22, 0x00);
  110. dsi_generic_write_seq(dsi, 0xb1, 0x22, 0x00);
  111. dsi_generic_write_seq(dsi, 0xb2, 0x05, 0x00, 0x60, 0x00, 0x00);
  112. dsi_generic_write_seq(dsi, 0xb3, 0x05, 0x00, 0x60, 0x00, 0x00);
  113. dsi_generic_write_seq(dsi, 0xb4, 0x05, 0x00, 0x60, 0x00, 0x00);
  114. dsi_generic_write_seq(dsi, 0xb5, 0x05, 0x00, 0x60, 0x00, 0x00);
  115. dsi_generic_write_seq(dsi, 0xba, 0x53, 0x00, 0x60, 0x00, 0x00);
  116. dsi_generic_write_seq(dsi, 0xbb, 0x53, 0x00, 0x60, 0x00, 0x00);
  117. dsi_generic_write_seq(dsi, 0xbc, 0x53, 0x00, 0x60, 0x00, 0x00);
  118. dsi_generic_write_seq(dsi, 0xbd, 0x53, 0x00, 0x60, 0x00, 0x00);
  119. dsi_generic_write_seq(dsi, 0xc0, 0x00, 0x34, 0x00, 0x00);
  120. dsi_generic_write_seq(dsi, 0xc1, 0x00, 0x00, 0x34, 0x00);
  121. dsi_generic_write_seq(dsi, 0xc2, 0x00, 0x00, 0x34, 0x00);
  122. dsi_generic_write_seq(dsi, 0xc3, 0x00, 0x00, 0x34, 0x00);
  123. dsi_generic_write_seq(dsi, 0xc4, 0x60);
  124. dsi_generic_write_seq(dsi, 0xc5, 0xc0);
  125. dsi_generic_write_seq(dsi, 0xc6, 0x00);
  126. dsi_generic_write_seq(dsi, 0xc7, 0x00);
  127. dsi_generic_write_seq(dsi, 0xf0, 0x55, 0xaa, 0x52, 0x08, 0x05);
  128. dsi_generic_write_seq(dsi, 0xb0, 0x17, 0x06);
  129. dsi_generic_write_seq(dsi, 0xb1, 0x17, 0x06);
  130. dsi_generic_write_seq(dsi, 0xb2, 0x17, 0x06);
  131. dsi_generic_write_seq(dsi, 0xb3, 0x17, 0x06);
  132. dsi_generic_write_seq(dsi, 0xb4, 0x17, 0x06);
  133. dsi_generic_write_seq(dsi, 0xb5, 0x17, 0x06);
  134. dsi_generic_write_seq(dsi, 0xb6, 0x17, 0x06);
  135. dsi_generic_write_seq(dsi, 0xb7, 0x17, 0x06);
  136. dsi_generic_write_seq(dsi, 0xb8, 0x00);
  137. dsi_generic_write_seq(dsi, 0xb9, 0x00, 0x03);
  138. dsi_generic_write_seq(dsi, 0xba, 0x00, 0x00);
  139. dsi_generic_write_seq(dsi, 0xbb, 0x02, 0x03);
  140. dsi_generic_write_seq(dsi, 0xbc, 0x02, 0x03);
  141. dsi_generic_write_seq(dsi, 0xbd, 0x03, 0x03, 0x00, 0x03, 0x03);
  142. dsi_generic_write_seq(dsi, 0xc0, 0x0b);
  143. dsi_generic_write_seq(dsi, 0xc1, 0x09);
  144. dsi_generic_write_seq(dsi, 0xc2, 0xa6);
  145. dsi_generic_write_seq(dsi, 0xc3, 0x05);
  146. dsi_generic_write_seq(dsi, 0xc4, 0x00);
  147. dsi_generic_write_seq(dsi, 0xc5, 0x02);
  148. dsi_generic_write_seq(dsi, 0xc6, 0x22);
  149. dsi_generic_write_seq(dsi, 0xc7, 0x03);
  150. dsi_generic_write_seq(dsi, 0xc8, 0x07, 0x20);
  151. dsi_generic_write_seq(dsi, 0xc9, 0x03, 0x20);
  152. dsi_generic_write_seq(dsi, 0xca, 0x01, 0x60);
  153. dsi_generic_write_seq(dsi, 0xcb, 0x01, 0x60);
  154. dsi_generic_write_seq(dsi, 0xcc, 0x00, 0x00, 0x02);
  155. dsi_generic_write_seq(dsi, 0xcd, 0x00, 0x00, 0x02);
  156. dsi_generic_write_seq(dsi, 0xce, 0x00, 0x00, 0x02);
  157. dsi_generic_write_seq(dsi, 0xcf, 0x00, 0x00, 0x02);
  158. dsi_generic_write_seq(dsi, 0xd1, 0x00, 0x05, 0x01, 0x07, 0x10);
  159. dsi_generic_write_seq(dsi, 0xd2, 0x10, 0x05, 0x05, 0x03, 0x10);
  160. dsi_generic_write_seq(dsi, 0xd3, 0x20, 0x00, 0x43, 0x07, 0x10);
  161. dsi_generic_write_seq(dsi, 0xd4, 0x30, 0x00, 0x43, 0x07, 0x10);
  162. dsi_generic_write_seq(dsi, 0xd0,
  163. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00);
  164. dsi_generic_write_seq(dsi, 0xd5,
  165. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  166. 0x00, 0x00, 0x00);
  167. dsi_generic_write_seq(dsi, 0xd6,
  168. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  169. 0x00, 0x00, 0x00);
  170. dsi_generic_write_seq(dsi, 0xd7,
  171. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  172. 0x00, 0x00, 0x00);
  173. dsi_generic_write_seq(dsi, 0xd8, 0x00, 0x00, 0x00, 0x00, 0x00);
  174. dsi_generic_write_seq(dsi, 0xe5, 0x06);
  175. dsi_generic_write_seq(dsi, 0xe6, 0x06);
  176. dsi_generic_write_seq(dsi, 0xe7, 0x00);
  177. dsi_generic_write_seq(dsi, 0xe8, 0x06);
  178. dsi_generic_write_seq(dsi, 0xe9, 0x06);
  179. dsi_generic_write_seq(dsi, 0xea, 0x06);
  180. dsi_generic_write_seq(dsi, 0xeb, 0x00);
  181. dsi_generic_write_seq(dsi, 0xec, 0x00);
  182. dsi_generic_write_seq(dsi, 0xed, 0x30);
  183. dsi_generic_write_seq(dsi, 0xf0, 0x55, 0xaa, 0x52, 0x08, 0x06);
  184. dsi_generic_write_seq(dsi, 0xb0, 0x31, 0x31);
  185. dsi_generic_write_seq(dsi, 0xb1, 0x31, 0x31);
  186. dsi_generic_write_seq(dsi, 0xb2, 0x2d, 0x2e);
  187. dsi_generic_write_seq(dsi, 0xb3, 0x31, 0x34);
  188. dsi_generic_write_seq(dsi, 0xb4, 0x29, 0x2a);
  189. dsi_generic_write_seq(dsi, 0xb5, 0x12, 0x10);
  190. dsi_generic_write_seq(dsi, 0xb6, 0x18, 0x16);
  191. dsi_generic_write_seq(dsi, 0xb7, 0x00, 0x02);
  192. dsi_generic_write_seq(dsi, 0xb8, 0x08, 0x31);
  193. dsi_generic_write_seq(dsi, 0xb9, 0x31, 0x31);
  194. dsi_generic_write_seq(dsi, 0xba, 0x31, 0x31);
  195. dsi_generic_write_seq(dsi, 0xbb, 0x31, 0x08);
  196. dsi_generic_write_seq(dsi, 0xbc, 0x03, 0x01);
  197. dsi_generic_write_seq(dsi, 0xbd, 0x17, 0x19);
  198. dsi_generic_write_seq(dsi, 0xbe, 0x11, 0x13);
  199. dsi_generic_write_seq(dsi, 0xbf, 0x2a, 0x29);
  200. dsi_generic_write_seq(dsi, 0xc0, 0x34, 0x31);
  201. dsi_generic_write_seq(dsi, 0xc1, 0x2e, 0x2d);
  202. dsi_generic_write_seq(dsi, 0xc2, 0x31, 0x31);
  203. dsi_generic_write_seq(dsi, 0xc3, 0x31, 0x31);
  204. dsi_generic_write_seq(dsi, 0xc4, 0x31, 0x31);
  205. dsi_generic_write_seq(dsi, 0xc5, 0x31, 0x31);
  206. dsi_generic_write_seq(dsi, 0xc6, 0x2e, 0x2d);
  207. dsi_generic_write_seq(dsi, 0xc7, 0x31, 0x34);
  208. dsi_generic_write_seq(dsi, 0xc8, 0x29, 0x2a);
  209. dsi_generic_write_seq(dsi, 0xc9, 0x17, 0x19);
  210. dsi_generic_write_seq(dsi, 0xca, 0x11, 0x13);
  211. dsi_generic_write_seq(dsi, 0xcb, 0x03, 0x01);
  212. dsi_generic_write_seq(dsi, 0xcc, 0x08, 0x31);
  213. dsi_generic_write_seq(dsi, 0xcd, 0x31, 0x31);
  214. dsi_generic_write_seq(dsi, 0xce, 0x31, 0x31);
  215. dsi_generic_write_seq(dsi, 0xcf, 0x31, 0x08);
  216. dsi_generic_write_seq(dsi, 0xd0, 0x00, 0x02);
  217. dsi_generic_write_seq(dsi, 0xd1, 0x12, 0x10);
  218. dsi_generic_write_seq(dsi, 0xd2, 0x18, 0x16);
  219. dsi_generic_write_seq(dsi, 0xd3, 0x2a, 0x29);
  220. dsi_generic_write_seq(dsi, 0xd4, 0x34, 0x31);
  221. dsi_generic_write_seq(dsi, 0xd5, 0x2d, 0x2e);
  222. dsi_generic_write_seq(dsi, 0xd6, 0x31, 0x31);
  223. dsi_generic_write_seq(dsi, 0xd7, 0x31, 0x31);
  224. dsi_generic_write_seq(dsi, 0xe5, 0x31, 0x31);
  225. dsi_generic_write_seq(dsi, 0xe6, 0x31, 0x31);
  226. dsi_generic_write_seq(dsi, 0xd8, 0x00, 0x00, 0x00, 0x00, 0x00);
  227. dsi_generic_write_seq(dsi, 0xd9, 0x00, 0x00, 0x00, 0x00, 0x00);
  228. dsi_generic_write_seq(dsi, 0xe7, 0x00);
  229. dsi_generic_write_seq(dsi, 0x6f, 0x02);
  230. dsi_generic_write_seq(dsi, 0xf7, 0x47);
  231. dsi_generic_write_seq(dsi, 0x6f, 0x0a);
  232. dsi_generic_write_seq(dsi, 0xf7, 0x02);
  233. dsi_generic_write_seq(dsi, 0x6f, 0x17);
  234. dsi_generic_write_seq(dsi, 0xf4, 0x60);
  235. dsi_generic_write_seq(dsi, 0x6f, 0x01);
  236. dsi_generic_write_seq(dsi, 0xf9, 0x46);
  237. dsi_generic_write_seq(dsi, 0x6f, 0x11);
  238. dsi_generic_write_seq(dsi, 0xf3, 0x01);
  239. dsi_generic_write_seq(dsi, 0x35, 0x00);
  240. dsi_generic_write_seq(dsi, 0xf0, 0x55, 0xaa, 0x52, 0x08, 0x00);
  241. dsi_generic_write_seq(dsi, 0xd9, 0x02, 0x03, 0x00);
  242. dsi_generic_write_seq(dsi, 0xf0, 0x55, 0xaa, 0x52, 0x00, 0x00);
  243. dsi_generic_write_seq(dsi, 0xf0, 0x55, 0xaa, 0x52, 0x08, 0x00);
  244. dsi_generic_write_seq(dsi, 0xb1, 0x6c, 0x21);
  245. dsi_generic_write_seq(dsi, 0xf0, 0x55, 0xaa, 0x52, 0x00, 0x00);
  246. dsi_generic_write_seq(dsi, 0x35, 0x00);
  247. ret = mipi_dsi_dcs_exit_sleep_mode(dsi);
  248. if (ret < 0) {
  249. dev_err(dev, "Failed to exit sleep mode: %d\n", ret);
  250. return ret;
  251. }
  252. msleep(120);
  253. ret = mipi_dsi_dcs_set_display_on(dsi);
  254. if (ret < 0) {
  255. dev_err(dev, "Failed to set display on: %d\n", ret);
  256. return ret;
  257. }
  258. usleep_range(1000, 2000);
  259. dsi_generic_write_seq(dsi, 0x53, 0x24);
  260. return 0;
  261. }
  262. static int truly_nt35521_off(struct truly_nt35521 *ctx)
  263. {
  264. struct mipi_dsi_device *dsi = ctx->dsi;
  265. struct device *dev = &dsi->dev;
  266. int ret;
  267. dsi->mode_flags &= ~MIPI_DSI_MODE_LPM;
  268. ret = mipi_dsi_dcs_set_display_off(dsi);
  269. if (ret < 0) {
  270. dev_err(dev, "Failed to set display off: %d\n", ret);
  271. return ret;
  272. }
  273. msleep(50);
  274. ret = mipi_dsi_dcs_enter_sleep_mode(dsi);
  275. if (ret < 0) {
  276. dev_err(dev, "Failed to enter sleep mode: %d\n", ret);
  277. return ret;
  278. }
  279. msleep(150);
  280. return 0;
  281. }
  282. static int truly_nt35521_prepare(struct drm_panel *panel)
  283. {
  284. struct truly_nt35521 *ctx = to_truly_nt35521(panel);
  285. struct device *dev = &ctx->dsi->dev;
  286. int ret;
  287. if (ctx->prepared)
  288. return 0;
  289. ret = regulator_bulk_enable(ARRAY_SIZE(ctx->supplies), ctx->supplies);
  290. if (ret < 0) {
  291. dev_err(dev, "Failed to enable regulators: %d\n", ret);
  292. return ret;
  293. }
  294. truly_nt35521_reset(ctx);
  295. ret = truly_nt35521_on(ctx);
  296. if (ret < 0) {
  297. dev_err(dev, "Failed to initialize panel: %d\n", ret);
  298. gpiod_set_value_cansleep(ctx->reset_gpio, 1);
  299. return ret;
  300. }
  301. ctx->prepared = true;
  302. return 0;
  303. }
  304. static int truly_nt35521_unprepare(struct drm_panel *panel)
  305. {
  306. struct truly_nt35521 *ctx = to_truly_nt35521(panel);
  307. struct device *dev = &ctx->dsi->dev;
  308. int ret;
  309. if (!ctx->prepared)
  310. return 0;
  311. ret = truly_nt35521_off(ctx);
  312. if (ret < 0)
  313. dev_err(dev, "Failed to un-initialize panel: %d\n", ret);
  314. gpiod_set_value_cansleep(ctx->reset_gpio, 1);
  315. regulator_bulk_disable(ARRAY_SIZE(ctx->supplies),
  316. ctx->supplies);
  317. ctx->prepared = false;
  318. return 0;
  319. }
  320. static int truly_nt35521_enable(struct drm_panel *panel)
  321. {
  322. struct truly_nt35521 *ctx = to_truly_nt35521(panel);
  323. if (ctx->enabled)
  324. return 0;
  325. gpiod_set_value_cansleep(ctx->blen_gpio, 1);
  326. ctx->enabled = true;
  327. return 0;
  328. }
  329. static int truly_nt35521_disable(struct drm_panel *panel)
  330. {
  331. struct truly_nt35521 *ctx = to_truly_nt35521(panel);
  332. if (!ctx->enabled)
  333. return 0;
  334. gpiod_set_value_cansleep(ctx->blen_gpio, 0);
  335. ctx->enabled = false;
  336. return 0;
  337. }
  338. static const struct drm_display_mode truly_nt35521_mode = {
  339. .clock = (720 + 232 + 20 + 112) * (1280 + 18 + 1 + 18) * 60 / 1000,
  340. .hdisplay = 720,
  341. .hsync_start = 720 + 232,
  342. .hsync_end = 720 + 232 + 20,
  343. .htotal = 720 + 232 + 20 + 112,
  344. .vdisplay = 1280,
  345. .vsync_start = 1280 + 18,
  346. .vsync_end = 1280 + 18 + 1,
  347. .vtotal = 1280 + 18 + 1 + 18,
  348. .width_mm = 65,
  349. .height_mm = 116,
  350. };
  351. static int truly_nt35521_get_modes(struct drm_panel *panel,
  352. struct drm_connector *connector)
  353. {
  354. struct drm_display_mode *mode;
  355. mode = drm_mode_duplicate(connector->dev, &truly_nt35521_mode);
  356. if (!mode)
  357. return -ENOMEM;
  358. drm_mode_set_name(mode);
  359. mode->type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED;
  360. connector->display_info.width_mm = mode->width_mm;
  361. connector->display_info.height_mm = mode->height_mm;
  362. drm_mode_probed_add(connector, mode);
  363. return 1;
  364. }
  365. static const struct drm_panel_funcs truly_nt35521_panel_funcs = {
  366. .prepare = truly_nt35521_prepare,
  367. .unprepare = truly_nt35521_unprepare,
  368. .enable = truly_nt35521_enable,
  369. .disable = truly_nt35521_disable,
  370. .get_modes = truly_nt35521_get_modes,
  371. };
  372. static int truly_nt35521_bl_update_status(struct backlight_device *bl)
  373. {
  374. struct mipi_dsi_device *dsi = bl_get_data(bl);
  375. u16 brightness = backlight_get_brightness(bl);
  376. int ret;
  377. ret = mipi_dsi_dcs_set_display_brightness(dsi, brightness);
  378. if (ret < 0)
  379. return ret;
  380. return 0;
  381. }
  382. static int truly_nt35521_bl_get_brightness(struct backlight_device *bl)
  383. {
  384. struct mipi_dsi_device *dsi = bl_get_data(bl);
  385. u16 brightness;
  386. int ret;
  387. ret = mipi_dsi_dcs_get_display_brightness(dsi, &brightness);
  388. if (ret < 0)
  389. return ret;
  390. return brightness & 0xff;
  391. }
  392. static const struct backlight_ops truly_nt35521_bl_ops = {
  393. .update_status = truly_nt35521_bl_update_status,
  394. .get_brightness = truly_nt35521_bl_get_brightness,
  395. };
  396. static struct backlight_device *
  397. truly_nt35521_create_backlight(struct mipi_dsi_device *dsi)
  398. {
  399. struct device *dev = &dsi->dev;
  400. const struct backlight_properties props = {
  401. .type = BACKLIGHT_RAW,
  402. .brightness = 255,
  403. .max_brightness = 255,
  404. };
  405. return devm_backlight_device_register(dev, dev_name(dev), dev, dsi,
  406. &truly_nt35521_bl_ops, &props);
  407. }
  408. static int truly_nt35521_probe(struct mipi_dsi_device *dsi)
  409. {
  410. struct device *dev = &dsi->dev;
  411. struct truly_nt35521 *ctx;
  412. int ret;
  413. ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL);
  414. if (!ctx)
  415. return -ENOMEM;
  416. ctx->supplies[0].supply = "positive5";
  417. ctx->supplies[1].supply = "negative5";
  418. ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(ctx->supplies),
  419. ctx->supplies);
  420. if (ret < 0) {
  421. dev_err(dev, "Failed to get regulators: %d\n", ret);
  422. return ret;
  423. }
  424. ctx->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_HIGH);
  425. if (IS_ERR(ctx->reset_gpio))
  426. return dev_err_probe(dev, PTR_ERR(ctx->reset_gpio),
  427. "Failed to get reset-gpios\n");
  428. ctx->blen_gpio = devm_gpiod_get(dev, "backlight", GPIOD_OUT_LOW);
  429. if (IS_ERR(ctx->blen_gpio))
  430. return dev_err_probe(dev, PTR_ERR(ctx->blen_gpio),
  431. "Failed to get backlight-gpios\n");
  432. ctx->dsi = dsi;
  433. mipi_dsi_set_drvdata(dsi, ctx);
  434. dsi->lanes = 4;
  435. dsi->format = MIPI_DSI_FMT_RGB888;
  436. dsi->mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_BURST |
  437. MIPI_DSI_MODE_VIDEO_HSE | MIPI_DSI_MODE_NO_EOT_PACKET |
  438. MIPI_DSI_CLOCK_NON_CONTINUOUS;
  439. drm_panel_init(&ctx->panel, dev, &truly_nt35521_panel_funcs,
  440. DRM_MODE_CONNECTOR_DSI);
  441. ctx->panel.backlight = truly_nt35521_create_backlight(dsi);
  442. if (IS_ERR(ctx->panel.backlight))
  443. return dev_err_probe(dev, PTR_ERR(ctx->panel.backlight),
  444. "Failed to create backlight\n");
  445. drm_panel_add(&ctx->panel);
  446. ret = mipi_dsi_attach(dsi);
  447. if (ret < 0) {
  448. dev_err(dev, "Failed to attach to DSI host: %d\n", ret);
  449. drm_panel_remove(&ctx->panel);
  450. return ret;
  451. }
  452. return 0;
  453. }
  454. static void truly_nt35521_remove(struct mipi_dsi_device *dsi)
  455. {
  456. struct truly_nt35521 *ctx = mipi_dsi_get_drvdata(dsi);
  457. int ret;
  458. ret = mipi_dsi_detach(dsi);
  459. if (ret < 0)
  460. dev_err(&dsi->dev, "Failed to detach from DSI host: %d\n", ret);
  461. drm_panel_remove(&ctx->panel);
  462. }
  463. static const struct of_device_id truly_nt35521_of_match[] = {
  464. { .compatible = "sony,tulip-truly-nt35521" },
  465. { /* sentinel */ }
  466. };
  467. MODULE_DEVICE_TABLE(of, truly_nt35521_of_match);
  468. static struct mipi_dsi_driver truly_nt35521_driver = {
  469. .probe = truly_nt35521_probe,
  470. .remove = truly_nt35521_remove,
  471. .driver = {
  472. .name = "panel-truly-nt35521",
  473. .of_match_table = truly_nt35521_of_match,
  474. },
  475. };
  476. module_mipi_dsi_driver(truly_nt35521_driver);
  477. MODULE_AUTHOR("Shawn Guo <[email protected]>");
  478. MODULE_DESCRIPTION("DRM driver for Sony Tulip Truly NT35521 panel");
  479. MODULE_LICENSE("GPL v2");