panel-simple.c 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269
  1. /*
  2. * Copyright (C) 2013, NVIDIA Corporation. All rights reserved.
  3. *
  4. * Permission is hereby granted, free of charge, to any person obtaining a
  5. * copy of this software and associated documentation files (the "Software"),
  6. * to deal in the Software without restriction, including without limitation
  7. * the rights to use, copy, modify, merge, publish, distribute, sub license,
  8. * and/or sell copies of the Software, and to permit persons to whom the
  9. * Software is furnished to do so, subject to the following conditions:
  10. *
  11. * The above copyright notice and this permission notice (including the
  12. * next paragraph) shall be included in all copies or substantial portions
  13. * of the Software.
  14. *
  15. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  16. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  17. * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
  18. * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  19. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  20. * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  21. * DEALINGS IN THE SOFTWARE.
  22. */
  23. #include <linux/backlight.h>
  24. #include <linux/gpio/consumer.h>
  25. #include <linux/module.h>
  26. #include <linux/of_platform.h>
  27. #include <linux/platform_device.h>
  28. #include <linux/regulator/consumer.h>
  29. #include <drm/drmP.h>
  30. #include <drm/drm_crtc.h>
  31. #include <drm/drm_mipi_dsi.h>
  32. #include <drm/drm_panel.h>
  33. #include <video/display_timing.h>
  34. #include <video/videomode.h>
  35. struct panel_desc {
  36. const struct drm_display_mode *modes;
  37. unsigned int num_modes;
  38. const struct display_timing *timings;
  39. unsigned int num_timings;
  40. unsigned int bpc;
  41. struct {
  42. unsigned int width;
  43. unsigned int height;
  44. } size;
  45. /**
  46. * @prepare: the time (in milliseconds) that it takes for the panel to
  47. * become ready and start receiving video data
  48. * @enable: the time (in milliseconds) that it takes for the panel to
  49. * display the first valid frame after starting to receive
  50. * video data
  51. * @disable: the time (in milliseconds) that it takes for the panel to
  52. * turn the display off (no content is visible)
  53. * @unprepare: the time (in milliseconds) that it takes for the panel
  54. * to power itself down completely
  55. */
  56. struct {
  57. unsigned int prepare;
  58. unsigned int enable;
  59. unsigned int disable;
  60. unsigned int unprepare;
  61. } delay;
  62. u32 bus_format;
  63. };
  64. struct panel_simple {
  65. struct drm_panel base;
  66. bool prepared;
  67. bool enabled;
  68. const struct panel_desc *desc;
  69. struct backlight_device *backlight;
  70. struct regulator *supply;
  71. struct i2c_adapter *ddc;
  72. struct gpio_desc *enable_gpio;
  73. };
  74. static inline struct panel_simple *to_panel_simple(struct drm_panel *panel)
  75. {
  76. return container_of(panel, struct panel_simple, base);
  77. }
  78. static int panel_simple_get_fixed_modes(struct panel_simple *panel)
  79. {
  80. struct drm_connector *connector = panel->base.connector;
  81. struct drm_device *drm = panel->base.drm;
  82. struct drm_display_mode *mode;
  83. unsigned int i, num = 0;
  84. if (!panel->desc)
  85. return 0;
  86. for (i = 0; i < panel->desc->num_timings; i++) {
  87. const struct display_timing *dt = &panel->desc->timings[i];
  88. struct videomode vm;
  89. videomode_from_timing(dt, &vm);
  90. mode = drm_mode_create(drm);
  91. if (!mode) {
  92. dev_err(drm->dev, "failed to add mode %ux%u\n",
  93. dt->hactive.typ, dt->vactive.typ);
  94. continue;
  95. }
  96. drm_display_mode_from_videomode(&vm, mode);
  97. drm_mode_set_name(mode);
  98. drm_mode_probed_add(connector, mode);
  99. num++;
  100. }
  101. for (i = 0; i < panel->desc->num_modes; i++) {
  102. const struct drm_display_mode *m = &panel->desc->modes[i];
  103. mode = drm_mode_duplicate(drm, m);
  104. if (!mode) {
  105. dev_err(drm->dev, "failed to add mode %ux%u@%u\n",
  106. m->hdisplay, m->vdisplay, m->vrefresh);
  107. continue;
  108. }
  109. drm_mode_set_name(mode);
  110. drm_mode_probed_add(connector, mode);
  111. num++;
  112. }
  113. connector->display_info.bpc = panel->desc->bpc;
  114. connector->display_info.width_mm = panel->desc->size.width;
  115. connector->display_info.height_mm = panel->desc->size.height;
  116. if (panel->desc->bus_format)
  117. drm_display_info_set_bus_formats(&connector->display_info,
  118. &panel->desc->bus_format, 1);
  119. return num;
  120. }
  121. static int panel_simple_disable(struct drm_panel *panel)
  122. {
  123. struct panel_simple *p = to_panel_simple(panel);
  124. if (!p->enabled)
  125. return 0;
  126. if (p->backlight) {
  127. p->backlight->props.power = FB_BLANK_POWERDOWN;
  128. backlight_update_status(p->backlight);
  129. }
  130. if (p->desc->delay.disable)
  131. msleep(p->desc->delay.disable);
  132. p->enabled = false;
  133. return 0;
  134. }
  135. static int panel_simple_unprepare(struct drm_panel *panel)
  136. {
  137. struct panel_simple *p = to_panel_simple(panel);
  138. if (!p->prepared)
  139. return 0;
  140. if (p->enable_gpio)
  141. gpiod_set_value_cansleep(p->enable_gpio, 0);
  142. regulator_disable(p->supply);
  143. if (p->desc->delay.unprepare)
  144. msleep(p->desc->delay.unprepare);
  145. p->prepared = false;
  146. return 0;
  147. }
  148. static int panel_simple_prepare(struct drm_panel *panel)
  149. {
  150. struct panel_simple *p = to_panel_simple(panel);
  151. int err;
  152. if (p->prepared)
  153. return 0;
  154. err = regulator_enable(p->supply);
  155. if (err < 0) {
  156. dev_err(panel->dev, "failed to enable supply: %d\n", err);
  157. return err;
  158. }
  159. if (p->enable_gpio)
  160. gpiod_set_value_cansleep(p->enable_gpio, 1);
  161. if (p->desc->delay.prepare)
  162. msleep(p->desc->delay.prepare);
  163. p->prepared = true;
  164. return 0;
  165. }
  166. static int panel_simple_enable(struct drm_panel *panel)
  167. {
  168. struct panel_simple *p = to_panel_simple(panel);
  169. if (p->enabled)
  170. return 0;
  171. if (p->desc->delay.enable)
  172. msleep(p->desc->delay.enable);
  173. if (p->backlight) {
  174. p->backlight->props.power = FB_BLANK_UNBLANK;
  175. backlight_update_status(p->backlight);
  176. }
  177. p->enabled = true;
  178. return 0;
  179. }
  180. static int panel_simple_get_modes(struct drm_panel *panel)
  181. {
  182. struct panel_simple *p = to_panel_simple(panel);
  183. int num = 0;
  184. /* probe EDID if a DDC bus is available */
  185. if (p->ddc) {
  186. struct edid *edid = drm_get_edid(panel->connector, p->ddc);
  187. drm_mode_connector_update_edid_property(panel->connector, edid);
  188. if (edid) {
  189. num += drm_add_edid_modes(panel->connector, edid);
  190. kfree(edid);
  191. }
  192. }
  193. /* add hard-coded panel modes */
  194. num += panel_simple_get_fixed_modes(p);
  195. return num;
  196. }
  197. static int panel_simple_get_timings(struct drm_panel *panel,
  198. unsigned int num_timings,
  199. struct display_timing *timings)
  200. {
  201. struct panel_simple *p = to_panel_simple(panel);
  202. unsigned int i;
  203. if (p->desc->num_timings < num_timings)
  204. num_timings = p->desc->num_timings;
  205. if (timings)
  206. for (i = 0; i < num_timings; i++)
  207. timings[i] = p->desc->timings[i];
  208. return p->desc->num_timings;
  209. }
  210. static const struct drm_panel_funcs panel_simple_funcs = {
  211. .disable = panel_simple_disable,
  212. .unprepare = panel_simple_unprepare,
  213. .prepare = panel_simple_prepare,
  214. .enable = panel_simple_enable,
  215. .get_modes = panel_simple_get_modes,
  216. .get_timings = panel_simple_get_timings,
  217. };
  218. static int panel_simple_probe(struct device *dev, const struct panel_desc *desc)
  219. {
  220. struct device_node *backlight, *ddc;
  221. struct panel_simple *panel;
  222. int err;
  223. panel = devm_kzalloc(dev, sizeof(*panel), GFP_KERNEL);
  224. if (!panel)
  225. return -ENOMEM;
  226. panel->enabled = false;
  227. panel->prepared = false;
  228. panel->desc = desc;
  229. panel->supply = devm_regulator_get(dev, "power");
  230. if (IS_ERR(panel->supply))
  231. return PTR_ERR(panel->supply);
  232. panel->enable_gpio = devm_gpiod_get_optional(dev, "enable",
  233. GPIOD_OUT_LOW);
  234. if (IS_ERR(panel->enable_gpio)) {
  235. err = PTR_ERR(panel->enable_gpio);
  236. dev_err(dev, "failed to request GPIO: %d\n", err);
  237. return err;
  238. }
  239. backlight = of_parse_phandle(dev->of_node, "backlight", 0);
  240. if (backlight) {
  241. panel->backlight = of_find_backlight_by_node(backlight);
  242. of_node_put(backlight);
  243. if (!panel->backlight)
  244. return -EPROBE_DEFER;
  245. }
  246. ddc = of_parse_phandle(dev->of_node, "ddc-i2c-bus", 0);
  247. if (ddc) {
  248. panel->ddc = of_find_i2c_adapter_by_node(ddc);
  249. of_node_put(ddc);
  250. if (!panel->ddc) {
  251. err = -EPROBE_DEFER;
  252. goto free_backlight;
  253. }
  254. }
  255. drm_panel_init(&panel->base);
  256. panel->base.dev = dev;
  257. panel->base.funcs = &panel_simple_funcs;
  258. err = drm_panel_add(&panel->base);
  259. if (err < 0)
  260. goto free_ddc;
  261. dev_set_drvdata(dev, panel);
  262. return 0;
  263. free_ddc:
  264. if (panel->ddc)
  265. put_device(&panel->ddc->dev);
  266. free_backlight:
  267. if (panel->backlight)
  268. put_device(&panel->backlight->dev);
  269. return err;
  270. }
  271. static int panel_simple_remove(struct device *dev)
  272. {
  273. struct panel_simple *panel = dev_get_drvdata(dev);
  274. drm_panel_detach(&panel->base);
  275. drm_panel_remove(&panel->base);
  276. panel_simple_disable(&panel->base);
  277. if (panel->ddc)
  278. put_device(&panel->ddc->dev);
  279. if (panel->backlight)
  280. put_device(&panel->backlight->dev);
  281. return 0;
  282. }
  283. static void panel_simple_shutdown(struct device *dev)
  284. {
  285. struct panel_simple *panel = dev_get_drvdata(dev);
  286. panel_simple_disable(&panel->base);
  287. }
  288. static const struct drm_display_mode auo_b101aw03_mode = {
  289. .clock = 51450,
  290. .hdisplay = 1024,
  291. .hsync_start = 1024 + 156,
  292. .hsync_end = 1024 + 156 + 8,
  293. .htotal = 1024 + 156 + 8 + 156,
  294. .vdisplay = 600,
  295. .vsync_start = 600 + 16,
  296. .vsync_end = 600 + 16 + 6,
  297. .vtotal = 600 + 16 + 6 + 16,
  298. .vrefresh = 60,
  299. };
  300. static const struct panel_desc auo_b101aw03 = {
  301. .modes = &auo_b101aw03_mode,
  302. .num_modes = 1,
  303. .bpc = 6,
  304. .size = {
  305. .width = 223,
  306. .height = 125,
  307. },
  308. };
  309. static const struct drm_display_mode auo_b101ean01_mode = {
  310. .clock = 72500,
  311. .hdisplay = 1280,
  312. .hsync_start = 1280 + 119,
  313. .hsync_end = 1280 + 119 + 32,
  314. .htotal = 1280 + 119 + 32 + 21,
  315. .vdisplay = 800,
  316. .vsync_start = 800 + 4,
  317. .vsync_end = 800 + 4 + 20,
  318. .vtotal = 800 + 4 + 20 + 8,
  319. .vrefresh = 60,
  320. };
  321. static const struct panel_desc auo_b101ean01 = {
  322. .modes = &auo_b101ean01_mode,
  323. .num_modes = 1,
  324. .bpc = 6,
  325. .size = {
  326. .width = 217,
  327. .height = 136,
  328. },
  329. };
  330. static const struct drm_display_mode auo_b101xtn01_mode = {
  331. .clock = 72000,
  332. .hdisplay = 1366,
  333. .hsync_start = 1366 + 20,
  334. .hsync_end = 1366 + 20 + 70,
  335. .htotal = 1366 + 20 + 70,
  336. .vdisplay = 768,
  337. .vsync_start = 768 + 14,
  338. .vsync_end = 768 + 14 + 42,
  339. .vtotal = 768 + 14 + 42,
  340. .vrefresh = 60,
  341. .flags = DRM_MODE_FLAG_NVSYNC | DRM_MODE_FLAG_NHSYNC,
  342. };
  343. static const struct panel_desc auo_b101xtn01 = {
  344. .modes = &auo_b101xtn01_mode,
  345. .num_modes = 1,
  346. .bpc = 6,
  347. .size = {
  348. .width = 223,
  349. .height = 125,
  350. },
  351. };
  352. static const struct drm_display_mode auo_b116xw03_mode = {
  353. .clock = 70589,
  354. .hdisplay = 1366,
  355. .hsync_start = 1366 + 40,
  356. .hsync_end = 1366 + 40 + 40,
  357. .htotal = 1366 + 40 + 40 + 32,
  358. .vdisplay = 768,
  359. .vsync_start = 768 + 10,
  360. .vsync_end = 768 + 10 + 12,
  361. .vtotal = 768 + 10 + 12 + 6,
  362. .vrefresh = 60,
  363. };
  364. static const struct panel_desc auo_b116xw03 = {
  365. .modes = &auo_b116xw03_mode,
  366. .num_modes = 1,
  367. .bpc = 6,
  368. .size = {
  369. .width = 256,
  370. .height = 144,
  371. },
  372. };
  373. static const struct drm_display_mode auo_b133xtn01_mode = {
  374. .clock = 69500,
  375. .hdisplay = 1366,
  376. .hsync_start = 1366 + 48,
  377. .hsync_end = 1366 + 48 + 32,
  378. .htotal = 1366 + 48 + 32 + 20,
  379. .vdisplay = 768,
  380. .vsync_start = 768 + 3,
  381. .vsync_end = 768 + 3 + 6,
  382. .vtotal = 768 + 3 + 6 + 13,
  383. .vrefresh = 60,
  384. };
  385. static const struct panel_desc auo_b133xtn01 = {
  386. .modes = &auo_b133xtn01_mode,
  387. .num_modes = 1,
  388. .bpc = 6,
  389. .size = {
  390. .width = 293,
  391. .height = 165,
  392. },
  393. };
  394. static const struct drm_display_mode auo_b133htn01_mode = {
  395. .clock = 150660,
  396. .hdisplay = 1920,
  397. .hsync_start = 1920 + 172,
  398. .hsync_end = 1920 + 172 + 80,
  399. .htotal = 1920 + 172 + 80 + 60,
  400. .vdisplay = 1080,
  401. .vsync_start = 1080 + 25,
  402. .vsync_end = 1080 + 25 + 10,
  403. .vtotal = 1080 + 25 + 10 + 10,
  404. .vrefresh = 60,
  405. };
  406. static const struct panel_desc auo_b133htn01 = {
  407. .modes = &auo_b133htn01_mode,
  408. .num_modes = 1,
  409. .bpc = 6,
  410. .size = {
  411. .width = 293,
  412. .height = 165,
  413. },
  414. .delay = {
  415. .prepare = 105,
  416. .enable = 20,
  417. .unprepare = 50,
  418. },
  419. };
  420. static const struct drm_display_mode avic_tm070ddh03_mode = {
  421. .clock = 51200,
  422. .hdisplay = 1024,
  423. .hsync_start = 1024 + 160,
  424. .hsync_end = 1024 + 160 + 4,
  425. .htotal = 1024 + 160 + 4 + 156,
  426. .vdisplay = 600,
  427. .vsync_start = 600 + 17,
  428. .vsync_end = 600 + 17 + 1,
  429. .vtotal = 600 + 17 + 1 + 17,
  430. .vrefresh = 60,
  431. };
  432. static const struct panel_desc avic_tm070ddh03 = {
  433. .modes = &avic_tm070ddh03_mode,
  434. .num_modes = 1,
  435. .bpc = 8,
  436. .size = {
  437. .width = 154,
  438. .height = 90,
  439. },
  440. .delay = {
  441. .prepare = 20,
  442. .enable = 200,
  443. .disable = 200,
  444. },
  445. };
  446. static const struct drm_display_mode chunghwa_claa101wa01a_mode = {
  447. .clock = 72070,
  448. .hdisplay = 1366,
  449. .hsync_start = 1366 + 58,
  450. .hsync_end = 1366 + 58 + 58,
  451. .htotal = 1366 + 58 + 58 + 58,
  452. .vdisplay = 768,
  453. .vsync_start = 768 + 4,
  454. .vsync_end = 768 + 4 + 4,
  455. .vtotal = 768 + 4 + 4 + 4,
  456. .vrefresh = 60,
  457. };
  458. static const struct panel_desc chunghwa_claa101wa01a = {
  459. .modes = &chunghwa_claa101wa01a_mode,
  460. .num_modes = 1,
  461. .bpc = 6,
  462. .size = {
  463. .width = 220,
  464. .height = 120,
  465. },
  466. };
  467. static const struct drm_display_mode chunghwa_claa101wb01_mode = {
  468. .clock = 69300,
  469. .hdisplay = 1366,
  470. .hsync_start = 1366 + 48,
  471. .hsync_end = 1366 + 48 + 32,
  472. .htotal = 1366 + 48 + 32 + 20,
  473. .vdisplay = 768,
  474. .vsync_start = 768 + 16,
  475. .vsync_end = 768 + 16 + 8,
  476. .vtotal = 768 + 16 + 8 + 16,
  477. .vrefresh = 60,
  478. };
  479. static const struct panel_desc chunghwa_claa101wb01 = {
  480. .modes = &chunghwa_claa101wb01_mode,
  481. .num_modes = 1,
  482. .bpc = 6,
  483. .size = {
  484. .width = 223,
  485. .height = 125,
  486. },
  487. };
  488. static const struct drm_display_mode edt_et057090dhu_mode = {
  489. .clock = 25175,
  490. .hdisplay = 640,
  491. .hsync_start = 640 + 16,
  492. .hsync_end = 640 + 16 + 30,
  493. .htotal = 640 + 16 + 30 + 114,
  494. .vdisplay = 480,
  495. .vsync_start = 480 + 10,
  496. .vsync_end = 480 + 10 + 3,
  497. .vtotal = 480 + 10 + 3 + 32,
  498. .vrefresh = 60,
  499. .flags = DRM_MODE_FLAG_NVSYNC | DRM_MODE_FLAG_NHSYNC,
  500. };
  501. static const struct panel_desc edt_et057090dhu = {
  502. .modes = &edt_et057090dhu_mode,
  503. .num_modes = 1,
  504. .bpc = 6,
  505. .size = {
  506. .width = 115,
  507. .height = 86,
  508. },
  509. };
  510. static const struct drm_display_mode edt_etm0700g0dh6_mode = {
  511. .clock = 33260,
  512. .hdisplay = 800,
  513. .hsync_start = 800 + 40,
  514. .hsync_end = 800 + 40 + 128,
  515. .htotal = 800 + 40 + 128 + 88,
  516. .vdisplay = 480,
  517. .vsync_start = 480 + 10,
  518. .vsync_end = 480 + 10 + 2,
  519. .vtotal = 480 + 10 + 2 + 33,
  520. .vrefresh = 60,
  521. .flags = DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC,
  522. };
  523. static const struct panel_desc edt_etm0700g0dh6 = {
  524. .modes = &edt_etm0700g0dh6_mode,
  525. .num_modes = 1,
  526. .bpc = 6,
  527. .size = {
  528. .width = 152,
  529. .height = 91,
  530. },
  531. };
  532. static const struct drm_display_mode foxlink_fl500wvr00_a0t_mode = {
  533. .clock = 32260,
  534. .hdisplay = 800,
  535. .hsync_start = 800 + 168,
  536. .hsync_end = 800 + 168 + 64,
  537. .htotal = 800 + 168 + 64 + 88,
  538. .vdisplay = 480,
  539. .vsync_start = 480 + 37,
  540. .vsync_end = 480 + 37 + 2,
  541. .vtotal = 480 + 37 + 2 + 8,
  542. .vrefresh = 60,
  543. };
  544. static const struct panel_desc foxlink_fl500wvr00_a0t = {
  545. .modes = &foxlink_fl500wvr00_a0t_mode,
  546. .num_modes = 1,
  547. .bpc = 8,
  548. .size = {
  549. .width = 108,
  550. .height = 65,
  551. },
  552. .bus_format = MEDIA_BUS_FMT_RGB888_1X24,
  553. };
  554. static const struct drm_display_mode giantplus_gpg482739qs5_mode = {
  555. .clock = 9000,
  556. .hdisplay = 480,
  557. .hsync_start = 480 + 5,
  558. .hsync_end = 480 + 5 + 1,
  559. .htotal = 480 + 5 + 1 + 40,
  560. .vdisplay = 272,
  561. .vsync_start = 272 + 8,
  562. .vsync_end = 272 + 8 + 1,
  563. .vtotal = 272 + 8 + 1 + 8,
  564. .vrefresh = 60,
  565. };
  566. static const struct panel_desc giantplus_gpg482739qs5 = {
  567. .modes = &giantplus_gpg482739qs5_mode,
  568. .num_modes = 1,
  569. .bpc = 8,
  570. .size = {
  571. .width = 95,
  572. .height = 54,
  573. },
  574. .bus_format = MEDIA_BUS_FMT_RGB888_1X24,
  575. };
  576. static const struct display_timing hannstar_hsd070pww1_timing = {
  577. .pixelclock = { 64300000, 71100000, 82000000 },
  578. .hactive = { 1280, 1280, 1280 },
  579. .hfront_porch = { 1, 1, 10 },
  580. .hback_porch = { 1, 1, 10 },
  581. .hsync_len = { 52, 158, 661 },
  582. .vactive = { 800, 800, 800 },
  583. .vfront_porch = { 1, 1, 10 },
  584. .vback_porch = { 1, 1, 10 },
  585. .vsync_len = { 1, 21, 203 },
  586. .flags = DISPLAY_FLAGS_DE_HIGH,
  587. };
  588. static const struct panel_desc hannstar_hsd070pww1 = {
  589. .timings = &hannstar_hsd070pww1_timing,
  590. .num_timings = 1,
  591. .bpc = 6,
  592. .size = {
  593. .width = 151,
  594. .height = 94,
  595. },
  596. };
  597. static const struct drm_display_mode hitachi_tx23d38vm0caa_mode = {
  598. .clock = 33333,
  599. .hdisplay = 800,
  600. .hsync_start = 800 + 85,
  601. .hsync_end = 800 + 85 + 86,
  602. .htotal = 800 + 85 + 86 + 85,
  603. .vdisplay = 480,
  604. .vsync_start = 480 + 16,
  605. .vsync_end = 480 + 16 + 13,
  606. .vtotal = 480 + 16 + 13 + 16,
  607. .vrefresh = 60,
  608. };
  609. static const struct panel_desc hitachi_tx23d38vm0caa = {
  610. .modes = &hitachi_tx23d38vm0caa_mode,
  611. .num_modes = 1,
  612. .bpc = 6,
  613. .size = {
  614. .width = 195,
  615. .height = 117,
  616. },
  617. };
  618. static const struct drm_display_mode innolux_at043tn24_mode = {
  619. .clock = 9000,
  620. .hdisplay = 480,
  621. .hsync_start = 480 + 2,
  622. .hsync_end = 480 + 2 + 41,
  623. .htotal = 480 + 2 + 41 + 2,
  624. .vdisplay = 272,
  625. .vsync_start = 272 + 2,
  626. .vsync_end = 272 + 2 + 11,
  627. .vtotal = 272 + 2 + 11 + 2,
  628. .vrefresh = 60,
  629. .flags = DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC,
  630. };
  631. static const struct panel_desc innolux_at043tn24 = {
  632. .modes = &innolux_at043tn24_mode,
  633. .num_modes = 1,
  634. .bpc = 8,
  635. .size = {
  636. .width = 95,
  637. .height = 54,
  638. },
  639. .bus_format = MEDIA_BUS_FMT_RGB888_1X24,
  640. };
  641. static const struct drm_display_mode innolux_g121i1_l01_mode = {
  642. .clock = 71000,
  643. .hdisplay = 1280,
  644. .hsync_start = 1280 + 64,
  645. .hsync_end = 1280 + 64 + 32,
  646. .htotal = 1280 + 64 + 32 + 64,
  647. .vdisplay = 800,
  648. .vsync_start = 800 + 9,
  649. .vsync_end = 800 + 9 + 6,
  650. .vtotal = 800 + 9 + 6 + 9,
  651. .vrefresh = 60,
  652. };
  653. static const struct panel_desc innolux_g121i1_l01 = {
  654. .modes = &innolux_g121i1_l01_mode,
  655. .num_modes = 1,
  656. .bpc = 6,
  657. .size = {
  658. .width = 261,
  659. .height = 163,
  660. },
  661. };
  662. static const struct drm_display_mode innolux_n116bge_mode = {
  663. .clock = 76420,
  664. .hdisplay = 1366,
  665. .hsync_start = 1366 + 136,
  666. .hsync_end = 1366 + 136 + 30,
  667. .htotal = 1366 + 136 + 30 + 60,
  668. .vdisplay = 768,
  669. .vsync_start = 768 + 8,
  670. .vsync_end = 768 + 8 + 12,
  671. .vtotal = 768 + 8 + 12 + 12,
  672. .vrefresh = 60,
  673. .flags = DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC,
  674. };
  675. static const struct panel_desc innolux_n116bge = {
  676. .modes = &innolux_n116bge_mode,
  677. .num_modes = 1,
  678. .bpc = 6,
  679. .size = {
  680. .width = 256,
  681. .height = 144,
  682. },
  683. };
  684. static const struct drm_display_mode innolux_n156bge_l21_mode = {
  685. .clock = 69300,
  686. .hdisplay = 1366,
  687. .hsync_start = 1366 + 16,
  688. .hsync_end = 1366 + 16 + 34,
  689. .htotal = 1366 + 16 + 34 + 50,
  690. .vdisplay = 768,
  691. .vsync_start = 768 + 2,
  692. .vsync_end = 768 + 2 + 6,
  693. .vtotal = 768 + 2 + 6 + 12,
  694. .vrefresh = 60,
  695. };
  696. static const struct panel_desc innolux_n156bge_l21 = {
  697. .modes = &innolux_n156bge_l21_mode,
  698. .num_modes = 1,
  699. .bpc = 6,
  700. .size = {
  701. .width = 344,
  702. .height = 193,
  703. },
  704. };
  705. static const struct drm_display_mode innolux_zj070na_01p_mode = {
  706. .clock = 51501,
  707. .hdisplay = 1024,
  708. .hsync_start = 1024 + 128,
  709. .hsync_end = 1024 + 128 + 64,
  710. .htotal = 1024 + 128 + 64 + 128,
  711. .vdisplay = 600,
  712. .vsync_start = 600 + 16,
  713. .vsync_end = 600 + 16 + 4,
  714. .vtotal = 600 + 16 + 4 + 16,
  715. .vrefresh = 60,
  716. };
  717. static const struct panel_desc innolux_zj070na_01p = {
  718. .modes = &innolux_zj070na_01p_mode,
  719. .num_modes = 1,
  720. .bpc = 6,
  721. .size = {
  722. .width = 1024,
  723. .height = 600,
  724. },
  725. };
  726. static const struct drm_display_mode lg_lp129qe_mode = {
  727. .clock = 285250,
  728. .hdisplay = 2560,
  729. .hsync_start = 2560 + 48,
  730. .hsync_end = 2560 + 48 + 32,
  731. .htotal = 2560 + 48 + 32 + 80,
  732. .vdisplay = 1700,
  733. .vsync_start = 1700 + 3,
  734. .vsync_end = 1700 + 3 + 10,
  735. .vtotal = 1700 + 3 + 10 + 36,
  736. .vrefresh = 60,
  737. };
  738. static const struct panel_desc lg_lp129qe = {
  739. .modes = &lg_lp129qe_mode,
  740. .num_modes = 1,
  741. .bpc = 8,
  742. .size = {
  743. .width = 272,
  744. .height = 181,
  745. },
  746. };
  747. static const struct drm_display_mode ortustech_com43h4m85ulc_mode = {
  748. .clock = 25000,
  749. .hdisplay = 480,
  750. .hsync_start = 480 + 10,
  751. .hsync_end = 480 + 10 + 10,
  752. .htotal = 480 + 10 + 10 + 15,
  753. .vdisplay = 800,
  754. .vsync_start = 800 + 3,
  755. .vsync_end = 800 + 3 + 3,
  756. .vtotal = 800 + 3 + 3 + 3,
  757. .vrefresh = 60,
  758. };
  759. static const struct panel_desc ortustech_com43h4m85ulc = {
  760. .modes = &ortustech_com43h4m85ulc_mode,
  761. .num_modes = 1,
  762. .bpc = 8,
  763. .size = {
  764. .width = 56,
  765. .height = 93,
  766. },
  767. .bus_format = MEDIA_BUS_FMT_RGB888_1X24,
  768. };
  769. static const struct drm_display_mode samsung_ltn101nt05_mode = {
  770. .clock = 54030,
  771. .hdisplay = 1024,
  772. .hsync_start = 1024 + 24,
  773. .hsync_end = 1024 + 24 + 136,
  774. .htotal = 1024 + 24 + 136 + 160,
  775. .vdisplay = 600,
  776. .vsync_start = 600 + 3,
  777. .vsync_end = 600 + 3 + 6,
  778. .vtotal = 600 + 3 + 6 + 61,
  779. .vrefresh = 60,
  780. };
  781. static const struct panel_desc samsung_ltn101nt05 = {
  782. .modes = &samsung_ltn101nt05_mode,
  783. .num_modes = 1,
  784. .bpc = 6,
  785. .size = {
  786. .width = 1024,
  787. .height = 600,
  788. },
  789. };
  790. static const struct drm_display_mode samsung_ltn140at29_301_mode = {
  791. .clock = 76300,
  792. .hdisplay = 1366,
  793. .hsync_start = 1366 + 64,
  794. .hsync_end = 1366 + 64 + 48,
  795. .htotal = 1366 + 64 + 48 + 128,
  796. .vdisplay = 768,
  797. .vsync_start = 768 + 2,
  798. .vsync_end = 768 + 2 + 5,
  799. .vtotal = 768 + 2 + 5 + 17,
  800. .vrefresh = 60,
  801. };
  802. static const struct panel_desc samsung_ltn140at29_301 = {
  803. .modes = &samsung_ltn140at29_301_mode,
  804. .num_modes = 1,
  805. .bpc = 6,
  806. .size = {
  807. .width = 320,
  808. .height = 187,
  809. },
  810. };
  811. static const struct drm_display_mode shelly_sca07010_bfn_lnn_mode = {
  812. .clock = 33300,
  813. .hdisplay = 800,
  814. .hsync_start = 800 + 1,
  815. .hsync_end = 800 + 1 + 64,
  816. .htotal = 800 + 1 + 64 + 64,
  817. .vdisplay = 480,
  818. .vsync_start = 480 + 1,
  819. .vsync_end = 480 + 1 + 23,
  820. .vtotal = 480 + 1 + 23 + 22,
  821. .vrefresh = 60,
  822. };
  823. static const struct panel_desc shelly_sca07010_bfn_lnn = {
  824. .modes = &shelly_sca07010_bfn_lnn_mode,
  825. .num_modes = 1,
  826. .size = {
  827. .width = 152,
  828. .height = 91,
  829. },
  830. .bus_format = MEDIA_BUS_FMT_RGB666_1X18,
  831. };
  832. static const struct of_device_id platform_of_match[] = {
  833. {
  834. .compatible = "auo,b101aw03",
  835. .data = &auo_b101aw03,
  836. }, {
  837. .compatible = "auo,b101ean01",
  838. .data = &auo_b101ean01,
  839. }, {
  840. .compatible = "auo,b101xtn01",
  841. .data = &auo_b101xtn01,
  842. }, {
  843. .compatible = "auo,b116xw03",
  844. .data = &auo_b116xw03,
  845. }, {
  846. .compatible = "auo,b133htn01",
  847. .data = &auo_b133htn01,
  848. }, {
  849. .compatible = "auo,b133xtn01",
  850. .data = &auo_b133xtn01,
  851. }, {
  852. .compatible = "avic,tm070ddh03",
  853. .data = &avic_tm070ddh03,
  854. }, {
  855. .compatible = "chunghwa,claa101wa01a",
  856. .data = &chunghwa_claa101wa01a
  857. }, {
  858. .compatible = "chunghwa,claa101wb01",
  859. .data = &chunghwa_claa101wb01
  860. }, {
  861. .compatible = "edt,et057090dhu",
  862. .data = &edt_et057090dhu,
  863. }, {
  864. .compatible = "edt,et070080dh6",
  865. .data = &edt_etm0700g0dh6,
  866. }, {
  867. .compatible = "edt,etm0700g0dh6",
  868. .data = &edt_etm0700g0dh6,
  869. }, {
  870. .compatible = "foxlink,fl500wvr00-a0t",
  871. .data = &foxlink_fl500wvr00_a0t,
  872. }, {
  873. .compatible = "giantplus,gpg482739qs5",
  874. .data = &giantplus_gpg482739qs5
  875. }, {
  876. .compatible = "hannstar,hsd070pww1",
  877. .data = &hannstar_hsd070pww1,
  878. }, {
  879. .compatible = "hit,tx23d38vm0caa",
  880. .data = &hitachi_tx23d38vm0caa
  881. }, {
  882. .compatible = "innolux,at043tn24",
  883. .data = &innolux_at043tn24,
  884. }, {
  885. .compatible ="innolux,g121i1-l01",
  886. .data = &innolux_g121i1_l01
  887. }, {
  888. .compatible = "innolux,n116bge",
  889. .data = &innolux_n116bge,
  890. }, {
  891. .compatible = "innolux,n156bge-l21",
  892. .data = &innolux_n156bge_l21,
  893. }, {
  894. .compatible = "innolux,zj070na-01p",
  895. .data = &innolux_zj070na_01p,
  896. }, {
  897. .compatible = "lg,lp129qe",
  898. .data = &lg_lp129qe,
  899. }, {
  900. .compatible = "ortustech,com43h4m85ulc",
  901. .data = &ortustech_com43h4m85ulc,
  902. }, {
  903. .compatible = "samsung,ltn101nt05",
  904. .data = &samsung_ltn101nt05,
  905. }, {
  906. .compatible = "samsung,ltn140at29-301",
  907. .data = &samsung_ltn140at29_301,
  908. }, {
  909. .compatible = "shelly,sca07010-bfn-lnn",
  910. .data = &shelly_sca07010_bfn_lnn,
  911. }, {
  912. /* sentinel */
  913. }
  914. };
  915. MODULE_DEVICE_TABLE(of, platform_of_match);
  916. static int panel_simple_platform_probe(struct platform_device *pdev)
  917. {
  918. const struct of_device_id *id;
  919. id = of_match_node(platform_of_match, pdev->dev.of_node);
  920. if (!id)
  921. return -ENODEV;
  922. return panel_simple_probe(&pdev->dev, id->data);
  923. }
  924. static int panel_simple_platform_remove(struct platform_device *pdev)
  925. {
  926. return panel_simple_remove(&pdev->dev);
  927. }
  928. static void panel_simple_platform_shutdown(struct platform_device *pdev)
  929. {
  930. panel_simple_shutdown(&pdev->dev);
  931. }
  932. static struct platform_driver panel_simple_platform_driver = {
  933. .driver = {
  934. .name = "panel-simple",
  935. .of_match_table = platform_of_match,
  936. },
  937. .probe = panel_simple_platform_probe,
  938. .remove = panel_simple_platform_remove,
  939. .shutdown = panel_simple_platform_shutdown,
  940. };
  941. struct panel_desc_dsi {
  942. struct panel_desc desc;
  943. unsigned long flags;
  944. enum mipi_dsi_pixel_format format;
  945. unsigned int lanes;
  946. };
  947. static const struct drm_display_mode lg_ld070wx3_sl01_mode = {
  948. .clock = 71000,
  949. .hdisplay = 800,
  950. .hsync_start = 800 + 32,
  951. .hsync_end = 800 + 32 + 1,
  952. .htotal = 800 + 32 + 1 + 57,
  953. .vdisplay = 1280,
  954. .vsync_start = 1280 + 28,
  955. .vsync_end = 1280 + 28 + 1,
  956. .vtotal = 1280 + 28 + 1 + 14,
  957. .vrefresh = 60,
  958. };
  959. static const struct panel_desc_dsi lg_ld070wx3_sl01 = {
  960. .desc = {
  961. .modes = &lg_ld070wx3_sl01_mode,
  962. .num_modes = 1,
  963. .bpc = 8,
  964. .size = {
  965. .width = 94,
  966. .height = 151,
  967. },
  968. },
  969. .flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_CLOCK_NON_CONTINUOUS,
  970. .format = MIPI_DSI_FMT_RGB888,
  971. .lanes = 4,
  972. };
  973. static const struct drm_display_mode lg_lh500wx1_sd03_mode = {
  974. .clock = 67000,
  975. .hdisplay = 720,
  976. .hsync_start = 720 + 12,
  977. .hsync_end = 720 + 12 + 4,
  978. .htotal = 720 + 12 + 4 + 112,
  979. .vdisplay = 1280,
  980. .vsync_start = 1280 + 8,
  981. .vsync_end = 1280 + 8 + 4,
  982. .vtotal = 1280 + 8 + 4 + 12,
  983. .vrefresh = 60,
  984. };
  985. static const struct panel_desc_dsi lg_lh500wx1_sd03 = {
  986. .desc = {
  987. .modes = &lg_lh500wx1_sd03_mode,
  988. .num_modes = 1,
  989. .bpc = 8,
  990. .size = {
  991. .width = 62,
  992. .height = 110,
  993. },
  994. },
  995. .flags = MIPI_DSI_MODE_VIDEO,
  996. .format = MIPI_DSI_FMT_RGB888,
  997. .lanes = 4,
  998. };
  999. static const struct drm_display_mode panasonic_vvx10f004b00_mode = {
  1000. .clock = 157200,
  1001. .hdisplay = 1920,
  1002. .hsync_start = 1920 + 154,
  1003. .hsync_end = 1920 + 154 + 16,
  1004. .htotal = 1920 + 154 + 16 + 32,
  1005. .vdisplay = 1200,
  1006. .vsync_start = 1200 + 17,
  1007. .vsync_end = 1200 + 17 + 2,
  1008. .vtotal = 1200 + 17 + 2 + 16,
  1009. .vrefresh = 60,
  1010. };
  1011. static const struct panel_desc_dsi panasonic_vvx10f004b00 = {
  1012. .desc = {
  1013. .modes = &panasonic_vvx10f004b00_mode,
  1014. .num_modes = 1,
  1015. .bpc = 8,
  1016. .size = {
  1017. .width = 217,
  1018. .height = 136,
  1019. },
  1020. },
  1021. .flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_SYNC_PULSE |
  1022. MIPI_DSI_CLOCK_NON_CONTINUOUS,
  1023. .format = MIPI_DSI_FMT_RGB888,
  1024. .lanes = 4,
  1025. };
  1026. static const struct of_device_id dsi_of_match[] = {
  1027. {
  1028. .compatible = "lg,ld070wx3-sl01",
  1029. .data = &lg_ld070wx3_sl01
  1030. }, {
  1031. .compatible = "lg,lh500wx1-sd03",
  1032. .data = &lg_lh500wx1_sd03
  1033. }, {
  1034. .compatible = "panasonic,vvx10f004b00",
  1035. .data = &panasonic_vvx10f004b00
  1036. }, {
  1037. /* sentinel */
  1038. }
  1039. };
  1040. MODULE_DEVICE_TABLE(of, dsi_of_match);
  1041. static int panel_simple_dsi_probe(struct mipi_dsi_device *dsi)
  1042. {
  1043. const struct panel_desc_dsi *desc;
  1044. const struct of_device_id *id;
  1045. int err;
  1046. id = of_match_node(dsi_of_match, dsi->dev.of_node);
  1047. if (!id)
  1048. return -ENODEV;
  1049. desc = id->data;
  1050. err = panel_simple_probe(&dsi->dev, &desc->desc);
  1051. if (err < 0)
  1052. return err;
  1053. dsi->mode_flags = desc->flags;
  1054. dsi->format = desc->format;
  1055. dsi->lanes = desc->lanes;
  1056. return mipi_dsi_attach(dsi);
  1057. }
  1058. static int panel_simple_dsi_remove(struct mipi_dsi_device *dsi)
  1059. {
  1060. int err;
  1061. err = mipi_dsi_detach(dsi);
  1062. if (err < 0)
  1063. dev_err(&dsi->dev, "failed to detach from DSI host: %d\n", err);
  1064. return panel_simple_remove(&dsi->dev);
  1065. }
  1066. static void panel_simple_dsi_shutdown(struct mipi_dsi_device *dsi)
  1067. {
  1068. panel_simple_shutdown(&dsi->dev);
  1069. }
  1070. static struct mipi_dsi_driver panel_simple_dsi_driver = {
  1071. .driver = {
  1072. .name = "panel-simple-dsi",
  1073. .of_match_table = dsi_of_match,
  1074. },
  1075. .probe = panel_simple_dsi_probe,
  1076. .remove = panel_simple_dsi_remove,
  1077. .shutdown = panel_simple_dsi_shutdown,
  1078. };
  1079. static int __init panel_simple_init(void)
  1080. {
  1081. int err;
  1082. err = platform_driver_register(&panel_simple_platform_driver);
  1083. if (err < 0)
  1084. return err;
  1085. if (IS_ENABLED(CONFIG_DRM_MIPI_DSI)) {
  1086. err = mipi_dsi_driver_register(&panel_simple_dsi_driver);
  1087. if (err < 0)
  1088. return err;
  1089. }
  1090. return 0;
  1091. }
  1092. module_init(panel_simple_init);
  1093. static void __exit panel_simple_exit(void)
  1094. {
  1095. if (IS_ENABLED(CONFIG_DRM_MIPI_DSI))
  1096. mipi_dsi_driver_unregister(&panel_simple_dsi_driver);
  1097. platform_driver_unregister(&panel_simple_platform_driver);
  1098. }
  1099. module_exit(panel_simple_exit);
  1100. MODULE_AUTHOR("Thierry Reding <treding@nvidia.com>");
  1101. MODULE_DESCRIPTION("DRM Driver for Simple Panels");
  1102. MODULE_LICENSE("GPL and additional rights");