panel-boe-tv101wum-nl6.c 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890
  1. // SPDX-License-Identifier: GPL-2.0
  2. /*
  3. * Copyright (c) 2018 MediaTek Inc.
  4. * Author: Jitao Shi <jitao.shi@mediatek.com>
  5. */
  6. #include <linux/delay.h>
  7. #include <linux/gpio/consumer.h>
  8. #include <linux/module.h>
  9. #include <linux/of.h>
  10. #include <linux/of_device.h>
  11. #include <linux/regulator/consumer.h>
  12. #include <drm/drm_connector.h>
  13. #include <drm/drm_crtc.h>
  14. #include <drm/drm_mipi_dsi.h>
  15. #include <drm/drm_panel.h>
  16. #include <video/mipi_display.h>
  17. struct panel_desc {
  18. const struct drm_display_mode *modes;
  19. unsigned int bpc;
  20. /**
  21. * @width_mm: width of the panel's active display area
  22. * @height_mm: height of the panel's active display area
  23. */
  24. struct {
  25. unsigned int width_mm;
  26. unsigned int height_mm;
  27. } size;
  28. unsigned long mode_flags;
  29. enum mipi_dsi_pixel_format format;
  30. const struct panel_init_cmd *init_cmds;
  31. unsigned int lanes;
  32. bool discharge_on_disable;
  33. };
  34. struct boe_panel {
  35. struct drm_panel base;
  36. struct mipi_dsi_device *dsi;
  37. const struct panel_desc *desc;
  38. enum drm_panel_orientation orientation;
  39. struct regulator *pp1800;
  40. struct regulator *avee;
  41. struct regulator *avdd;
  42. struct gpio_desc *enable_gpio;
  43. bool prepared;
  44. };
  45. enum dsi_cmd_type {
  46. INIT_DCS_CMD,
  47. DELAY_CMD,
  48. };
  49. struct panel_init_cmd {
  50. enum dsi_cmd_type type;
  51. size_t len;
  52. const char *data;
  53. };
  54. #define _INIT_DCS_CMD(...) { \
  55. .type = INIT_DCS_CMD, \
  56. .len = sizeof((char[]){__VA_ARGS__}), \
  57. .data = (char[]){__VA_ARGS__} }
  58. #define _INIT_DELAY_CMD(...) { \
  59. .type = DELAY_CMD,\
  60. .len = sizeof((char[]){__VA_ARGS__}), \
  61. .data = (char[]){__VA_ARGS__} }
  62. static const struct panel_init_cmd boe_init_cmd[] = {
  63. _INIT_DELAY_CMD(24),
  64. _INIT_DCS_CMD(0xB0, 0x05),
  65. _INIT_DCS_CMD(0xB1, 0xE5),
  66. _INIT_DCS_CMD(0xB3, 0x52),
  67. _INIT_DCS_CMD(0xB0, 0x00),
  68. _INIT_DCS_CMD(0xB3, 0x88),
  69. _INIT_DCS_CMD(0xB0, 0x04),
  70. _INIT_DCS_CMD(0xB8, 0x00),
  71. _INIT_DCS_CMD(0xB0, 0x00),
  72. _INIT_DCS_CMD(0xB6, 0x03),
  73. _INIT_DCS_CMD(0xBA, 0x8B),
  74. _INIT_DCS_CMD(0xBF, 0x1A),
  75. _INIT_DCS_CMD(0xC0, 0x0F),
  76. _INIT_DCS_CMD(0xC2, 0x0C),
  77. _INIT_DCS_CMD(0xC3, 0x02),
  78. _INIT_DCS_CMD(0xC4, 0x0C),
  79. _INIT_DCS_CMD(0xC5, 0x02),
  80. _INIT_DCS_CMD(0xB0, 0x01),
  81. _INIT_DCS_CMD(0xE0, 0x26),
  82. _INIT_DCS_CMD(0xE1, 0x26),
  83. _INIT_DCS_CMD(0xDC, 0x00),
  84. _INIT_DCS_CMD(0xDD, 0x00),
  85. _INIT_DCS_CMD(0xCC, 0x26),
  86. _INIT_DCS_CMD(0xCD, 0x26),
  87. _INIT_DCS_CMD(0xC8, 0x00),
  88. _INIT_DCS_CMD(0xC9, 0x00),
  89. _INIT_DCS_CMD(0xD2, 0x03),
  90. _INIT_DCS_CMD(0xD3, 0x03),
  91. _INIT_DCS_CMD(0xE6, 0x04),
  92. _INIT_DCS_CMD(0xE7, 0x04),
  93. _INIT_DCS_CMD(0xC4, 0x09),
  94. _INIT_DCS_CMD(0xC5, 0x09),
  95. _INIT_DCS_CMD(0xD8, 0x0A),
  96. _INIT_DCS_CMD(0xD9, 0x0A),
  97. _INIT_DCS_CMD(0xC2, 0x0B),
  98. _INIT_DCS_CMD(0xC3, 0x0B),
  99. _INIT_DCS_CMD(0xD6, 0x0C),
  100. _INIT_DCS_CMD(0xD7, 0x0C),
  101. _INIT_DCS_CMD(0xC0, 0x05),
  102. _INIT_DCS_CMD(0xC1, 0x05),
  103. _INIT_DCS_CMD(0xD4, 0x06),
  104. _INIT_DCS_CMD(0xD5, 0x06),
  105. _INIT_DCS_CMD(0xCA, 0x07),
  106. _INIT_DCS_CMD(0xCB, 0x07),
  107. _INIT_DCS_CMD(0xDE, 0x08),
  108. _INIT_DCS_CMD(0xDF, 0x08),
  109. _INIT_DCS_CMD(0xB0, 0x02),
  110. _INIT_DCS_CMD(0xC0, 0x00),
  111. _INIT_DCS_CMD(0xC1, 0x0D),
  112. _INIT_DCS_CMD(0xC2, 0x17),
  113. _INIT_DCS_CMD(0xC3, 0x26),
  114. _INIT_DCS_CMD(0xC4, 0x31),
  115. _INIT_DCS_CMD(0xC5, 0x1C),
  116. _INIT_DCS_CMD(0xC6, 0x2C),
  117. _INIT_DCS_CMD(0xC7, 0x33),
  118. _INIT_DCS_CMD(0xC8, 0x31),
  119. _INIT_DCS_CMD(0xC9, 0x37),
  120. _INIT_DCS_CMD(0xCA, 0x37),
  121. _INIT_DCS_CMD(0xCB, 0x37),
  122. _INIT_DCS_CMD(0xCC, 0x39),
  123. _INIT_DCS_CMD(0xCD, 0x2E),
  124. _INIT_DCS_CMD(0xCE, 0x2F),
  125. _INIT_DCS_CMD(0xCF, 0x2F),
  126. _INIT_DCS_CMD(0xD0, 0x07),
  127. _INIT_DCS_CMD(0xD2, 0x00),
  128. _INIT_DCS_CMD(0xD3, 0x0D),
  129. _INIT_DCS_CMD(0xD4, 0x17),
  130. _INIT_DCS_CMD(0xD5, 0x26),
  131. _INIT_DCS_CMD(0xD6, 0x31),
  132. _INIT_DCS_CMD(0xD7, 0x3F),
  133. _INIT_DCS_CMD(0xD8, 0x3F),
  134. _INIT_DCS_CMD(0xD9, 0x3F),
  135. _INIT_DCS_CMD(0xDA, 0x3F),
  136. _INIT_DCS_CMD(0xDB, 0x37),
  137. _INIT_DCS_CMD(0xDC, 0x37),
  138. _INIT_DCS_CMD(0xDD, 0x37),
  139. _INIT_DCS_CMD(0xDE, 0x39),
  140. _INIT_DCS_CMD(0xDF, 0x2E),
  141. _INIT_DCS_CMD(0xE0, 0x2F),
  142. _INIT_DCS_CMD(0xE1, 0x2F),
  143. _INIT_DCS_CMD(0xE2, 0x07),
  144. _INIT_DCS_CMD(0xB0, 0x03),
  145. _INIT_DCS_CMD(0xC8, 0x0B),
  146. _INIT_DCS_CMD(0xC9, 0x07),
  147. _INIT_DCS_CMD(0xC3, 0x00),
  148. _INIT_DCS_CMD(0xE7, 0x00),
  149. _INIT_DCS_CMD(0xC5, 0x2A),
  150. _INIT_DCS_CMD(0xDE, 0x2A),
  151. _INIT_DCS_CMD(0xCA, 0x43),
  152. _INIT_DCS_CMD(0xC9, 0x07),
  153. _INIT_DCS_CMD(0xE4, 0xC0),
  154. _INIT_DCS_CMD(0xE5, 0x0D),
  155. _INIT_DCS_CMD(0xCB, 0x00),
  156. _INIT_DCS_CMD(0xB0, 0x06),
  157. _INIT_DCS_CMD(0xB8, 0xA5),
  158. _INIT_DCS_CMD(0xC0, 0xA5),
  159. _INIT_DCS_CMD(0xC7, 0x0F),
  160. _INIT_DCS_CMD(0xD5, 0x32),
  161. _INIT_DCS_CMD(0xB8, 0x00),
  162. _INIT_DCS_CMD(0xC0, 0x00),
  163. _INIT_DCS_CMD(0xBC, 0x00),
  164. _INIT_DCS_CMD(0xB0, 0x07),
  165. _INIT_DCS_CMD(0xB1, 0x00),
  166. _INIT_DCS_CMD(0xB2, 0x02),
  167. _INIT_DCS_CMD(0xB3, 0x0F),
  168. _INIT_DCS_CMD(0xB4, 0x25),
  169. _INIT_DCS_CMD(0xB5, 0x39),
  170. _INIT_DCS_CMD(0xB6, 0x4E),
  171. _INIT_DCS_CMD(0xB7, 0x72),
  172. _INIT_DCS_CMD(0xB8, 0x97),
  173. _INIT_DCS_CMD(0xB9, 0xDC),
  174. _INIT_DCS_CMD(0xBA, 0x22),
  175. _INIT_DCS_CMD(0xBB, 0xA4),
  176. _INIT_DCS_CMD(0xBC, 0x2B),
  177. _INIT_DCS_CMD(0xBD, 0x2F),
  178. _INIT_DCS_CMD(0xBE, 0xA9),
  179. _INIT_DCS_CMD(0xBF, 0x25),
  180. _INIT_DCS_CMD(0xC0, 0x61),
  181. _INIT_DCS_CMD(0xC1, 0x97),
  182. _INIT_DCS_CMD(0xC2, 0xB2),
  183. _INIT_DCS_CMD(0xC3, 0xCD),
  184. _INIT_DCS_CMD(0xC4, 0xD9),
  185. _INIT_DCS_CMD(0xC5, 0xE7),
  186. _INIT_DCS_CMD(0xC6, 0xF4),
  187. _INIT_DCS_CMD(0xC7, 0xFA),
  188. _INIT_DCS_CMD(0xC8, 0xFC),
  189. _INIT_DCS_CMD(0xC9, 0x00),
  190. _INIT_DCS_CMD(0xCA, 0x00),
  191. _INIT_DCS_CMD(0xCB, 0x16),
  192. _INIT_DCS_CMD(0xCC, 0xAF),
  193. _INIT_DCS_CMD(0xCD, 0xFF),
  194. _INIT_DCS_CMD(0xCE, 0xFF),
  195. _INIT_DCS_CMD(0xB0, 0x08),
  196. _INIT_DCS_CMD(0xB1, 0x04),
  197. _INIT_DCS_CMD(0xB2, 0x05),
  198. _INIT_DCS_CMD(0xB3, 0x11),
  199. _INIT_DCS_CMD(0xB4, 0x24),
  200. _INIT_DCS_CMD(0xB5, 0x39),
  201. _INIT_DCS_CMD(0xB6, 0x4F),
  202. _INIT_DCS_CMD(0xB7, 0x72),
  203. _INIT_DCS_CMD(0xB8, 0x98),
  204. _INIT_DCS_CMD(0xB9, 0xDC),
  205. _INIT_DCS_CMD(0xBA, 0x23),
  206. _INIT_DCS_CMD(0xBB, 0xA6),
  207. _INIT_DCS_CMD(0xBC, 0x2C),
  208. _INIT_DCS_CMD(0xBD, 0x30),
  209. _INIT_DCS_CMD(0xBE, 0xAA),
  210. _INIT_DCS_CMD(0xBF, 0x26),
  211. _INIT_DCS_CMD(0xC0, 0x62),
  212. _INIT_DCS_CMD(0xC1, 0x9B),
  213. _INIT_DCS_CMD(0xC2, 0xB5),
  214. _INIT_DCS_CMD(0xC3, 0xCF),
  215. _INIT_DCS_CMD(0xC4, 0xDB),
  216. _INIT_DCS_CMD(0xC5, 0xE8),
  217. _INIT_DCS_CMD(0xC6, 0xF5),
  218. _INIT_DCS_CMD(0xC7, 0xFA),
  219. _INIT_DCS_CMD(0xC8, 0xFC),
  220. _INIT_DCS_CMD(0xC9, 0x00),
  221. _INIT_DCS_CMD(0xCA, 0x00),
  222. _INIT_DCS_CMD(0xCB, 0x16),
  223. _INIT_DCS_CMD(0xCC, 0xAF),
  224. _INIT_DCS_CMD(0xCD, 0xFF),
  225. _INIT_DCS_CMD(0xCE, 0xFF),
  226. _INIT_DCS_CMD(0xB0, 0x09),
  227. _INIT_DCS_CMD(0xB1, 0x04),
  228. _INIT_DCS_CMD(0xB2, 0x02),
  229. _INIT_DCS_CMD(0xB3, 0x16),
  230. _INIT_DCS_CMD(0xB4, 0x24),
  231. _INIT_DCS_CMD(0xB5, 0x3B),
  232. _INIT_DCS_CMD(0xB6, 0x4F),
  233. _INIT_DCS_CMD(0xB7, 0x73),
  234. _INIT_DCS_CMD(0xB8, 0x99),
  235. _INIT_DCS_CMD(0xB9, 0xE0),
  236. _INIT_DCS_CMD(0xBA, 0x26),
  237. _INIT_DCS_CMD(0xBB, 0xAD),
  238. _INIT_DCS_CMD(0xBC, 0x36),
  239. _INIT_DCS_CMD(0xBD, 0x3A),
  240. _INIT_DCS_CMD(0xBE, 0xAE),
  241. _INIT_DCS_CMD(0xBF, 0x2A),
  242. _INIT_DCS_CMD(0xC0, 0x66),
  243. _INIT_DCS_CMD(0xC1, 0x9E),
  244. _INIT_DCS_CMD(0xC2, 0xB8),
  245. _INIT_DCS_CMD(0xC3, 0xD1),
  246. _INIT_DCS_CMD(0xC4, 0xDD),
  247. _INIT_DCS_CMD(0xC5, 0xE9),
  248. _INIT_DCS_CMD(0xC6, 0xF6),
  249. _INIT_DCS_CMD(0xC7, 0xFA),
  250. _INIT_DCS_CMD(0xC8, 0xFC),
  251. _INIT_DCS_CMD(0xC9, 0x00),
  252. _INIT_DCS_CMD(0xCA, 0x00),
  253. _INIT_DCS_CMD(0xCB, 0x16),
  254. _INIT_DCS_CMD(0xCC, 0xAF),
  255. _INIT_DCS_CMD(0xCD, 0xFF),
  256. _INIT_DCS_CMD(0xCE, 0xFF),
  257. _INIT_DCS_CMD(0xB0, 0x0A),
  258. _INIT_DCS_CMD(0xB1, 0x00),
  259. _INIT_DCS_CMD(0xB2, 0x02),
  260. _INIT_DCS_CMD(0xB3, 0x0F),
  261. _INIT_DCS_CMD(0xB4, 0x25),
  262. _INIT_DCS_CMD(0xB5, 0x39),
  263. _INIT_DCS_CMD(0xB6, 0x4E),
  264. _INIT_DCS_CMD(0xB7, 0x72),
  265. _INIT_DCS_CMD(0xB8, 0x97),
  266. _INIT_DCS_CMD(0xB9, 0xDC),
  267. _INIT_DCS_CMD(0xBA, 0x22),
  268. _INIT_DCS_CMD(0xBB, 0xA4),
  269. _INIT_DCS_CMD(0xBC, 0x2B),
  270. _INIT_DCS_CMD(0xBD, 0x2F),
  271. _INIT_DCS_CMD(0xBE, 0xA9),
  272. _INIT_DCS_CMD(0xBF, 0x25),
  273. _INIT_DCS_CMD(0xC0, 0x61),
  274. _INIT_DCS_CMD(0xC1, 0x97),
  275. _INIT_DCS_CMD(0xC2, 0xB2),
  276. _INIT_DCS_CMD(0xC3, 0xCD),
  277. _INIT_DCS_CMD(0xC4, 0xD9),
  278. _INIT_DCS_CMD(0xC5, 0xE7),
  279. _INIT_DCS_CMD(0xC6, 0xF4),
  280. _INIT_DCS_CMD(0xC7, 0xFA),
  281. _INIT_DCS_CMD(0xC8, 0xFC),
  282. _INIT_DCS_CMD(0xC9, 0x00),
  283. _INIT_DCS_CMD(0xCA, 0x00),
  284. _INIT_DCS_CMD(0xCB, 0x16),
  285. _INIT_DCS_CMD(0xCC, 0xAF),
  286. _INIT_DCS_CMD(0xCD, 0xFF),
  287. _INIT_DCS_CMD(0xCE, 0xFF),
  288. _INIT_DCS_CMD(0xB0, 0x0B),
  289. _INIT_DCS_CMD(0xB1, 0x04),
  290. _INIT_DCS_CMD(0xB2, 0x05),
  291. _INIT_DCS_CMD(0xB3, 0x11),
  292. _INIT_DCS_CMD(0xB4, 0x24),
  293. _INIT_DCS_CMD(0xB5, 0x39),
  294. _INIT_DCS_CMD(0xB6, 0x4F),
  295. _INIT_DCS_CMD(0xB7, 0x72),
  296. _INIT_DCS_CMD(0xB8, 0x98),
  297. _INIT_DCS_CMD(0xB9, 0xDC),
  298. _INIT_DCS_CMD(0xBA, 0x23),
  299. _INIT_DCS_CMD(0xBB, 0xA6),
  300. _INIT_DCS_CMD(0xBC, 0x2C),
  301. _INIT_DCS_CMD(0xBD, 0x30),
  302. _INIT_DCS_CMD(0xBE, 0xAA),
  303. _INIT_DCS_CMD(0xBF, 0x26),
  304. _INIT_DCS_CMD(0xC0, 0x62),
  305. _INIT_DCS_CMD(0xC1, 0x9B),
  306. _INIT_DCS_CMD(0xC2, 0xB5),
  307. _INIT_DCS_CMD(0xC3, 0xCF),
  308. _INIT_DCS_CMD(0xC4, 0xDB),
  309. _INIT_DCS_CMD(0xC5, 0xE8),
  310. _INIT_DCS_CMD(0xC6, 0xF5),
  311. _INIT_DCS_CMD(0xC7, 0xFA),
  312. _INIT_DCS_CMD(0xC8, 0xFC),
  313. _INIT_DCS_CMD(0xC9, 0x00),
  314. _INIT_DCS_CMD(0xCA, 0x00),
  315. _INIT_DCS_CMD(0xCB, 0x16),
  316. _INIT_DCS_CMD(0xCC, 0xAF),
  317. _INIT_DCS_CMD(0xCD, 0xFF),
  318. _INIT_DCS_CMD(0xCE, 0xFF),
  319. _INIT_DCS_CMD(0xB0, 0x0C),
  320. _INIT_DCS_CMD(0xB1, 0x04),
  321. _INIT_DCS_CMD(0xB2, 0x02),
  322. _INIT_DCS_CMD(0xB3, 0x16),
  323. _INIT_DCS_CMD(0xB4, 0x24),
  324. _INIT_DCS_CMD(0xB5, 0x3B),
  325. _INIT_DCS_CMD(0xB6, 0x4F),
  326. _INIT_DCS_CMD(0xB7, 0x73),
  327. _INIT_DCS_CMD(0xB8, 0x99),
  328. _INIT_DCS_CMD(0xB9, 0xE0),
  329. _INIT_DCS_CMD(0xBA, 0x26),
  330. _INIT_DCS_CMD(0xBB, 0xAD),
  331. _INIT_DCS_CMD(0xBC, 0x36),
  332. _INIT_DCS_CMD(0xBD, 0x3A),
  333. _INIT_DCS_CMD(0xBE, 0xAE),
  334. _INIT_DCS_CMD(0xBF, 0x2A),
  335. _INIT_DCS_CMD(0xC0, 0x66),
  336. _INIT_DCS_CMD(0xC1, 0x9E),
  337. _INIT_DCS_CMD(0xC2, 0xB8),
  338. _INIT_DCS_CMD(0xC3, 0xD1),
  339. _INIT_DCS_CMD(0xC4, 0xDD),
  340. _INIT_DCS_CMD(0xC5, 0xE9),
  341. _INIT_DCS_CMD(0xC6, 0xF6),
  342. _INIT_DCS_CMD(0xC7, 0xFA),
  343. _INIT_DCS_CMD(0xC8, 0xFC),
  344. _INIT_DCS_CMD(0xC9, 0x00),
  345. _INIT_DCS_CMD(0xCA, 0x00),
  346. _INIT_DCS_CMD(0xCB, 0x16),
  347. _INIT_DCS_CMD(0xCC, 0xAF),
  348. _INIT_DCS_CMD(0xCD, 0xFF),
  349. _INIT_DCS_CMD(0xCE, 0xFF),
  350. _INIT_DCS_CMD(0xB0, 0x00),
  351. _INIT_DCS_CMD(0xB3, 0x08),
  352. _INIT_DCS_CMD(0xB0, 0x04),
  353. _INIT_DCS_CMD(0xB8, 0x68),
  354. _INIT_DELAY_CMD(150),
  355. {},
  356. };
  357. static const struct panel_init_cmd auo_kd101n80_45na_init_cmd[] = {
  358. _INIT_DELAY_CMD(24),
  359. _INIT_DCS_CMD(0x11),
  360. _INIT_DELAY_CMD(120),
  361. _INIT_DCS_CMD(0x29),
  362. _INIT_DELAY_CMD(120),
  363. {},
  364. };
  365. static const struct panel_init_cmd auo_b101uan08_3_init_cmd[] = {
  366. _INIT_DELAY_CMD(24),
  367. _INIT_DCS_CMD(0xB0, 0x01),
  368. _INIT_DCS_CMD(0xC0, 0x48),
  369. _INIT_DCS_CMD(0xC1, 0x48),
  370. _INIT_DCS_CMD(0xC2, 0x47),
  371. _INIT_DCS_CMD(0xC3, 0x47),
  372. _INIT_DCS_CMD(0xC4, 0x46),
  373. _INIT_DCS_CMD(0xC5, 0x46),
  374. _INIT_DCS_CMD(0xC6, 0x45),
  375. _INIT_DCS_CMD(0xC7, 0x45),
  376. _INIT_DCS_CMD(0xC8, 0x64),
  377. _INIT_DCS_CMD(0xC9, 0x64),
  378. _INIT_DCS_CMD(0xCA, 0x4F),
  379. _INIT_DCS_CMD(0xCB, 0x4F),
  380. _INIT_DCS_CMD(0xCC, 0x40),
  381. _INIT_DCS_CMD(0xCD, 0x40),
  382. _INIT_DCS_CMD(0xCE, 0x66),
  383. _INIT_DCS_CMD(0xCF, 0x66),
  384. _INIT_DCS_CMD(0xD0, 0x4F),
  385. _INIT_DCS_CMD(0xD1, 0x4F),
  386. _INIT_DCS_CMD(0xD2, 0x41),
  387. _INIT_DCS_CMD(0xD3, 0x41),
  388. _INIT_DCS_CMD(0xD4, 0x48),
  389. _INIT_DCS_CMD(0xD5, 0x48),
  390. _INIT_DCS_CMD(0xD6, 0x47),
  391. _INIT_DCS_CMD(0xD7, 0x47),
  392. _INIT_DCS_CMD(0xD8, 0x46),
  393. _INIT_DCS_CMD(0xD9, 0x46),
  394. _INIT_DCS_CMD(0xDA, 0x45),
  395. _INIT_DCS_CMD(0xDB, 0x45),
  396. _INIT_DCS_CMD(0xDC, 0x64),
  397. _INIT_DCS_CMD(0xDD, 0x64),
  398. _INIT_DCS_CMD(0xDE, 0x4F),
  399. _INIT_DCS_CMD(0xDF, 0x4F),
  400. _INIT_DCS_CMD(0xE0, 0x40),
  401. _INIT_DCS_CMD(0xE1, 0x40),
  402. _INIT_DCS_CMD(0xE2, 0x66),
  403. _INIT_DCS_CMD(0xE3, 0x66),
  404. _INIT_DCS_CMD(0xE4, 0x4F),
  405. _INIT_DCS_CMD(0xE5, 0x4F),
  406. _INIT_DCS_CMD(0xE6, 0x41),
  407. _INIT_DCS_CMD(0xE7, 0x41),
  408. _INIT_DELAY_CMD(150),
  409. {},
  410. };
  411. static inline struct boe_panel *to_boe_panel(struct drm_panel *panel)
  412. {
  413. return container_of(panel, struct boe_panel, base);
  414. }
  415. static int boe_panel_init_dcs_cmd(struct boe_panel *boe)
  416. {
  417. struct mipi_dsi_device *dsi = boe->dsi;
  418. struct drm_panel *panel = &boe->base;
  419. int i, err = 0;
  420. if (boe->desc->init_cmds) {
  421. const struct panel_init_cmd *init_cmds = boe->desc->init_cmds;
  422. for (i = 0; init_cmds[i].len != 0; i++) {
  423. const struct panel_init_cmd *cmd = &init_cmds[i];
  424. switch (cmd->type) {
  425. case DELAY_CMD:
  426. msleep(cmd->data[0]);
  427. err = 0;
  428. break;
  429. case INIT_DCS_CMD:
  430. err = mipi_dsi_dcs_write(dsi, cmd->data[0],
  431. cmd->len <= 1 ? NULL :
  432. &cmd->data[1],
  433. cmd->len - 1);
  434. break;
  435. default:
  436. err = -EINVAL;
  437. }
  438. if (err < 0) {
  439. dev_err(panel->dev,
  440. "failed to write command %u\n", i);
  441. return err;
  442. }
  443. }
  444. }
  445. return 0;
  446. }
  447. static int boe_panel_enter_sleep_mode(struct boe_panel *boe)
  448. {
  449. struct mipi_dsi_device *dsi = boe->dsi;
  450. int ret;
  451. dsi->mode_flags &= ~MIPI_DSI_MODE_LPM;
  452. ret = mipi_dsi_dcs_set_display_off(dsi);
  453. if (ret < 0)
  454. return ret;
  455. ret = mipi_dsi_dcs_enter_sleep_mode(dsi);
  456. if (ret < 0)
  457. return ret;
  458. return 0;
  459. }
  460. static int boe_panel_unprepare(struct drm_panel *panel)
  461. {
  462. struct boe_panel *boe = to_boe_panel(panel);
  463. int ret;
  464. if (!boe->prepared)
  465. return 0;
  466. ret = boe_panel_enter_sleep_mode(boe);
  467. if (ret < 0) {
  468. dev_err(panel->dev, "failed to set panel off: %d\n", ret);
  469. return ret;
  470. }
  471. msleep(150);
  472. if (boe->desc->discharge_on_disable) {
  473. regulator_disable(boe->avee);
  474. regulator_disable(boe->avdd);
  475. usleep_range(5000, 7000);
  476. gpiod_set_value(boe->enable_gpio, 0);
  477. usleep_range(5000, 7000);
  478. regulator_disable(boe->pp1800);
  479. } else {
  480. gpiod_set_value(boe->enable_gpio, 0);
  481. usleep_range(500, 1000);
  482. regulator_disable(boe->avee);
  483. regulator_disable(boe->avdd);
  484. usleep_range(5000, 7000);
  485. regulator_disable(boe->pp1800);
  486. }
  487. boe->prepared = false;
  488. return 0;
  489. }
  490. static int boe_panel_prepare(struct drm_panel *panel)
  491. {
  492. struct boe_panel *boe = to_boe_panel(panel);
  493. int ret;
  494. if (boe->prepared)
  495. return 0;
  496. gpiod_set_value(boe->enable_gpio, 0);
  497. usleep_range(1000, 1500);
  498. ret = regulator_enable(boe->pp1800);
  499. if (ret < 0)
  500. return ret;
  501. usleep_range(3000, 5000);
  502. ret = regulator_enable(boe->avdd);
  503. if (ret < 0)
  504. goto poweroff1v8;
  505. ret = regulator_enable(boe->avee);
  506. if (ret < 0)
  507. goto poweroffavdd;
  508. usleep_range(5000, 10000);
  509. gpiod_set_value(boe->enable_gpio, 1);
  510. usleep_range(1000, 2000);
  511. gpiod_set_value(boe->enable_gpio, 0);
  512. usleep_range(1000, 2000);
  513. gpiod_set_value(boe->enable_gpio, 1);
  514. usleep_range(6000, 10000);
  515. ret = boe_panel_init_dcs_cmd(boe);
  516. if (ret < 0) {
  517. dev_err(panel->dev, "failed to init panel: %d\n", ret);
  518. goto poweroff;
  519. }
  520. boe->prepared = true;
  521. return 0;
  522. poweroff:
  523. regulator_disable(boe->avee);
  524. poweroffavdd:
  525. regulator_disable(boe->avdd);
  526. poweroff1v8:
  527. usleep_range(5000, 7000);
  528. regulator_disable(boe->pp1800);
  529. gpiod_set_value(boe->enable_gpio, 0);
  530. return ret;
  531. }
  532. static int boe_panel_enable(struct drm_panel *panel)
  533. {
  534. msleep(130);
  535. return 0;
  536. }
  537. static const struct drm_display_mode boe_tv101wum_nl6_default_mode = {
  538. .clock = 159425,
  539. .hdisplay = 1200,
  540. .hsync_start = 1200 + 100,
  541. .hsync_end = 1200 + 100 + 40,
  542. .htotal = 1200 + 100 + 40 + 24,
  543. .vdisplay = 1920,
  544. .vsync_start = 1920 + 10,
  545. .vsync_end = 1920 + 10 + 14,
  546. .vtotal = 1920 + 10 + 14 + 4,
  547. };
  548. static const struct panel_desc boe_tv101wum_nl6_desc = {
  549. .modes = &boe_tv101wum_nl6_default_mode,
  550. .bpc = 8,
  551. .size = {
  552. .width_mm = 135,
  553. .height_mm = 216,
  554. },
  555. .lanes = 4,
  556. .format = MIPI_DSI_FMT_RGB888,
  557. .mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_SYNC_PULSE |
  558. MIPI_DSI_MODE_LPM,
  559. .init_cmds = boe_init_cmd,
  560. .discharge_on_disable = false,
  561. };
  562. static const struct drm_display_mode auo_kd101n80_45na_default_mode = {
  563. .clock = 157000,
  564. .hdisplay = 1200,
  565. .hsync_start = 1200 + 60,
  566. .hsync_end = 1200 + 60 + 24,
  567. .htotal = 1200 + 60 + 24 + 56,
  568. .vdisplay = 1920,
  569. .vsync_start = 1920 + 16,
  570. .vsync_end = 1920 + 16 + 4,
  571. .vtotal = 1920 + 16 + 4 + 16,
  572. };
  573. static const struct panel_desc auo_kd101n80_45na_desc = {
  574. .modes = &auo_kd101n80_45na_default_mode,
  575. .bpc = 8,
  576. .size = {
  577. .width_mm = 135,
  578. .height_mm = 216,
  579. },
  580. .lanes = 4,
  581. .format = MIPI_DSI_FMT_RGB888,
  582. .mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_SYNC_PULSE |
  583. MIPI_DSI_MODE_LPM,
  584. .init_cmds = auo_kd101n80_45na_init_cmd,
  585. .discharge_on_disable = true,
  586. };
  587. static const struct drm_display_mode boe_tv101wum_n53_default_mode = {
  588. .clock = 159916,
  589. .hdisplay = 1200,
  590. .hsync_start = 1200 + 80,
  591. .hsync_end = 1200 + 80 + 24,
  592. .htotal = 1200 + 80 + 24 + 60,
  593. .vdisplay = 1920,
  594. .vsync_start = 1920 + 20,
  595. .vsync_end = 1920 + 20 + 4,
  596. .vtotal = 1920 + 20 + 4 + 10,
  597. .type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED,
  598. };
  599. static const struct panel_desc boe_tv101wum_n53_desc = {
  600. .modes = &boe_tv101wum_n53_default_mode,
  601. .bpc = 8,
  602. .size = {
  603. .width_mm = 135,
  604. .height_mm = 216,
  605. },
  606. .lanes = 4,
  607. .format = MIPI_DSI_FMT_RGB888,
  608. .mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_SYNC_PULSE |
  609. MIPI_DSI_MODE_LPM,
  610. .init_cmds = boe_init_cmd,
  611. };
  612. static const struct drm_display_mode auo_b101uan08_3_default_mode = {
  613. .clock = 159667,
  614. .hdisplay = 1200,
  615. .hsync_start = 1200 + 60,
  616. .hsync_end = 1200 + 60 + 4,
  617. .htotal = 1200 + 60 + 4 + 80,
  618. .vdisplay = 1920,
  619. .vsync_start = 1920 + 34,
  620. .vsync_end = 1920 + 34 + 2,
  621. .vtotal = 1920 + 34 + 2 + 24,
  622. .type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED,
  623. };
  624. static const struct panel_desc auo_b101uan08_3_desc = {
  625. .modes = &auo_b101uan08_3_default_mode,
  626. .bpc = 8,
  627. .size = {
  628. .width_mm = 135,
  629. .height_mm = 216,
  630. },
  631. .lanes = 4,
  632. .format = MIPI_DSI_FMT_RGB888,
  633. .mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_SYNC_PULSE |
  634. MIPI_DSI_MODE_LPM,
  635. .init_cmds = auo_b101uan08_3_init_cmd,
  636. };
  637. static const struct drm_display_mode boe_tv105wum_nw0_default_mode = {
  638. .clock = 159916,
  639. .hdisplay = 1200,
  640. .hsync_start = 1200 + 80,
  641. .hsync_end = 1200 + 80 + 24,
  642. .htotal = 1200 + 80 + 24 + 60,
  643. .vdisplay = 1920,
  644. .vsync_start = 1920 + 20,
  645. .vsync_end = 1920 + 20 + 4,
  646. .vtotal = 1920 + 20 + 4 + 10,
  647. .type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED,
  648. };
  649. static const struct panel_desc boe_tv105wum_nw0_desc = {
  650. .modes = &boe_tv105wum_nw0_default_mode,
  651. .bpc = 8,
  652. .size = {
  653. .width_mm = 141,
  654. .height_mm = 226,
  655. },
  656. .lanes = 4,
  657. .format = MIPI_DSI_FMT_RGB888,
  658. .mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_SYNC_PULSE |
  659. MIPI_DSI_MODE_LPM,
  660. .init_cmds = boe_init_cmd,
  661. };
  662. static int boe_panel_get_modes(struct drm_panel *panel,
  663. struct drm_connector *connector)
  664. {
  665. struct boe_panel *boe = to_boe_panel(panel);
  666. const struct drm_display_mode *m = boe->desc->modes;
  667. struct drm_display_mode *mode;
  668. mode = drm_mode_duplicate(connector->dev, m);
  669. if (!mode) {
  670. dev_err(panel->dev, "failed to add mode %ux%u@%u\n",
  671. m->hdisplay, m->vdisplay, drm_mode_vrefresh(m));
  672. return -ENOMEM;
  673. }
  674. mode->type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED;
  675. drm_mode_set_name(mode);
  676. drm_mode_probed_add(connector, mode);
  677. connector->display_info.width_mm = boe->desc->size.width_mm;
  678. connector->display_info.height_mm = boe->desc->size.height_mm;
  679. connector->display_info.bpc = boe->desc->bpc;
  680. drm_connector_set_panel_orientation(connector, boe->orientation);
  681. return 1;
  682. }
  683. static const struct drm_panel_funcs boe_panel_funcs = {
  684. .unprepare = boe_panel_unprepare,
  685. .prepare = boe_panel_prepare,
  686. .enable = boe_panel_enable,
  687. .get_modes = boe_panel_get_modes,
  688. };
  689. static int boe_panel_add(struct boe_panel *boe)
  690. {
  691. struct device *dev = &boe->dsi->dev;
  692. int err;
  693. boe->avdd = devm_regulator_get(dev, "avdd");
  694. if (IS_ERR(boe->avdd))
  695. return PTR_ERR(boe->avdd);
  696. boe->avee = devm_regulator_get(dev, "avee");
  697. if (IS_ERR(boe->avee))
  698. return PTR_ERR(boe->avee);
  699. boe->pp1800 = devm_regulator_get(dev, "pp1800");
  700. if (IS_ERR(boe->pp1800))
  701. return PTR_ERR(boe->pp1800);
  702. boe->enable_gpio = devm_gpiod_get(dev, "enable", GPIOD_OUT_LOW);
  703. if (IS_ERR(boe->enable_gpio)) {
  704. dev_err(dev, "cannot get reset-gpios %ld\n",
  705. PTR_ERR(boe->enable_gpio));
  706. return PTR_ERR(boe->enable_gpio);
  707. }
  708. gpiod_set_value(boe->enable_gpio, 0);
  709. drm_panel_init(&boe->base, dev, &boe_panel_funcs,
  710. DRM_MODE_CONNECTOR_DSI);
  711. err = of_drm_get_panel_orientation(dev->of_node, &boe->orientation);
  712. if (err < 0) {
  713. dev_err(dev, "%pOF: failed to get orientation %d\n", dev->of_node, err);
  714. return err;
  715. }
  716. err = drm_panel_of_backlight(&boe->base);
  717. if (err)
  718. return err;
  719. boe->base.funcs = &boe_panel_funcs;
  720. boe->base.dev = &boe->dsi->dev;
  721. drm_panel_add(&boe->base);
  722. return 0;
  723. }
  724. static int boe_panel_probe(struct mipi_dsi_device *dsi)
  725. {
  726. struct boe_panel *boe;
  727. int ret;
  728. const struct panel_desc *desc;
  729. boe = devm_kzalloc(&dsi->dev, sizeof(*boe), GFP_KERNEL);
  730. if (!boe)
  731. return -ENOMEM;
  732. desc = of_device_get_match_data(&dsi->dev);
  733. dsi->lanes = desc->lanes;
  734. dsi->format = desc->format;
  735. dsi->mode_flags = desc->mode_flags;
  736. boe->desc = desc;
  737. boe->dsi = dsi;
  738. ret = boe_panel_add(boe);
  739. if (ret < 0)
  740. return ret;
  741. mipi_dsi_set_drvdata(dsi, boe);
  742. ret = mipi_dsi_attach(dsi);
  743. if (ret)
  744. drm_panel_remove(&boe->base);
  745. return ret;
  746. }
  747. static void boe_panel_shutdown(struct mipi_dsi_device *dsi)
  748. {
  749. struct boe_panel *boe = mipi_dsi_get_drvdata(dsi);
  750. drm_panel_disable(&boe->base);
  751. drm_panel_unprepare(&boe->base);
  752. }
  753. static int boe_panel_remove(struct mipi_dsi_device *dsi)
  754. {
  755. struct boe_panel *boe = mipi_dsi_get_drvdata(dsi);
  756. int ret;
  757. boe_panel_shutdown(dsi);
  758. ret = mipi_dsi_detach(dsi);
  759. if (ret < 0)
  760. dev_err(&dsi->dev, "failed to detach from DSI host: %d\n", ret);
  761. if (boe->base.dev)
  762. drm_panel_remove(&boe->base);
  763. return 0;
  764. }
  765. static const struct of_device_id boe_of_match[] = {
  766. { .compatible = "boe,tv101wum-nl6",
  767. .data = &boe_tv101wum_nl6_desc
  768. },
  769. { .compatible = "auo,kd101n80-45na",
  770. .data = &auo_kd101n80_45na_desc
  771. },
  772. { .compatible = "boe,tv101wum-n53",
  773. .data = &boe_tv101wum_n53_desc
  774. },
  775. { .compatible = "auo,b101uan08.3",
  776. .data = &auo_b101uan08_3_desc
  777. },
  778. { .compatible = "boe,tv105wum-nw0",
  779. .data = &boe_tv105wum_nw0_desc
  780. },
  781. { /* sentinel */ }
  782. };
  783. MODULE_DEVICE_TABLE(of, boe_of_match);
  784. static struct mipi_dsi_driver boe_panel_driver = {
  785. .driver = {
  786. .name = "panel-boe-tv101wum-nl6",
  787. .of_match_table = boe_of_match,
  788. },
  789. .probe = boe_panel_probe,
  790. .remove = boe_panel_remove,
  791. .shutdown = boe_panel_shutdown,
  792. };
  793. module_mipi_dsi_driver(boe_panel_driver);
  794. MODULE_AUTHOR("Jitao Shi <jitao.shi@mediatek.com>");
  795. MODULE_DESCRIPTION("BOE tv101wum-nl6 1200x1920 video mode panel driver");
  796. MODULE_LICENSE("GPL v2");