sharp-memory.c 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669
  1. // SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
  2. #include <drm/clients/drm_client_setup.h>
  3. #include <drm/drm_atomic.h>
  4. #include <drm/drm_atomic_helper.h>
  5. #include <drm/drm_connector.h>
  6. #include <drm/drm_damage_helper.h>
  7. #include <drm/drm_drv.h>
  8. #include <drm/drm_fb_dma_helper.h>
  9. #include <drm/drm_fbdev_dma.h>
  10. #include <drm/drm_format_helper.h>
  11. #include <drm/drm_framebuffer.h>
  12. #include <drm/drm_gem_atomic_helper.h>
  13. #include <drm/drm_gem_dma_helper.h>
  14. #include <drm/drm_gem_framebuffer_helper.h>
  15. #include <drm/drm_managed.h>
  16. #include <drm/drm_modes.h>
  17. #include <drm/drm_probe_helper.h>
  18. #include <drm/drm_rect.h>
  19. #include <linux/bitrev.h>
  20. #include <linux/delay.h>
  21. #include <linux/gpio/consumer.h>
  22. #include <linux/kthread.h>
  23. #include <linux/mod_devicetable.h>
  24. #include <linux/module.h>
  25. #include <linux/mutex.h>
  26. #include <linux/pwm.h>
  27. #include <linux/spi/spi.h>
  28. #define SHARP_MODE_PERIOD 8
  29. #define SHARP_ADDR_PERIOD 8
  30. #define SHARP_DUMMY_PERIOD 8
  31. #define SHARP_MEMORY_DISPLAY_MAINTAIN_MODE 0
  32. #define SHARP_MEMORY_DISPLAY_UPDATE_MODE 1
  33. #define SHARP_MEMORY_DISPLAY_CLEAR_MODE 4
  34. enum sharp_memory_model {
  35. LS010B7DH04,
  36. LS011B7DH03,
  37. LS012B7DD01,
  38. LS013B7DH03,
  39. LS013B7DH05,
  40. LS018B7DH02,
  41. LS027B7DH01,
  42. LS027B7DH01A,
  43. LS032B7DD02,
  44. LS044Q7DH01,
  45. };
  46. enum sharp_memory_vcom_mode {
  47. SHARP_MEMORY_SOFTWARE_VCOM,
  48. SHARP_MEMORY_EXTERNAL_VCOM,
  49. SHARP_MEMORY_PWM_VCOM
  50. };
  51. struct sharp_memory_device {
  52. struct drm_device drm;
  53. struct spi_device *spi;
  54. const struct drm_display_mode *mode;
  55. struct drm_crtc crtc;
  56. struct drm_plane plane;
  57. struct drm_encoder encoder;
  58. struct drm_connector connector;
  59. struct gpio_desc *enable_gpio;
  60. struct task_struct *sw_vcom_signal;
  61. struct pwm_device *pwm_vcom_signal;
  62. enum sharp_memory_vcom_mode vcom_mode;
  63. u8 vcom;
  64. u32 pitch;
  65. u32 tx_buffer_size;
  66. u8 *tx_buffer;
  67. /* When vcom_mode == "software" a kthread is used to periodically send a
  68. * 'maintain display' message over spi. This mutex ensures tx_buffer access
  69. * and spi bus usage is synchronized in this case.
  70. */
  71. struct mutex tx_mutex;
  72. };
  73. static inline int sharp_memory_spi_write(struct spi_device *spi, void *buf, size_t len)
  74. {
  75. /* Reverse the bit order */
  76. for (u8 *b = buf; b < ((u8 *)buf) + len; ++b)
  77. *b = bitrev8(*b);
  78. return spi_write(spi, buf, len);
  79. }
  80. static inline struct sharp_memory_device *drm_to_sharp_memory_device(struct drm_device *drm)
  81. {
  82. return container_of(drm, struct sharp_memory_device, drm);
  83. }
  84. DEFINE_DRM_GEM_DMA_FOPS(sharp_memory_fops);
  85. static const struct drm_driver sharp_memory_drm_driver = {
  86. .driver_features = DRIVER_GEM | DRIVER_MODESET | DRIVER_ATOMIC,
  87. .fops = &sharp_memory_fops,
  88. DRM_GEM_DMA_DRIVER_OPS_VMAP,
  89. DRM_FBDEV_DMA_DRIVER_OPS,
  90. .name = "sharp_memory_display",
  91. .desc = "Sharp Display Memory LCD",
  92. .major = 1,
  93. .minor = 0,
  94. };
  95. static inline void sharp_memory_set_tx_buffer_mode(u8 *buffer, u8 mode, u8 vcom)
  96. {
  97. *buffer = mode | (vcom << 1);
  98. }
  99. static inline void sharp_memory_set_tx_buffer_addresses(u8 *buffer,
  100. struct drm_rect clip,
  101. u32 pitch)
  102. {
  103. for (u32 line = 0; line < clip.y2; ++line)
  104. buffer[line * pitch] = line + 1;
  105. }
  106. static void sharp_memory_set_tx_buffer_data(u8 *buffer,
  107. struct drm_framebuffer *fb,
  108. const struct iosys_map *vmap,
  109. struct drm_rect clip,
  110. u32 pitch,
  111. struct drm_format_conv_state *fmtcnv_state)
  112. {
  113. int ret;
  114. struct iosys_map dst;
  115. ret = drm_gem_fb_begin_cpu_access(fb, DMA_FROM_DEVICE);
  116. if (ret)
  117. return;
  118. iosys_map_set_vaddr(&dst, buffer);
  119. drm_fb_xrgb8888_to_mono(&dst, &pitch, vmap, fb, &clip, fmtcnv_state);
  120. drm_gem_fb_end_cpu_access(fb, DMA_FROM_DEVICE);
  121. }
  122. static int sharp_memory_update_display(struct sharp_memory_device *smd,
  123. struct drm_framebuffer *fb,
  124. const struct iosys_map *vmap,
  125. struct drm_rect clip,
  126. struct drm_format_conv_state *fmtcnv_state)
  127. {
  128. int ret;
  129. u32 pitch = smd->pitch;
  130. u8 vcom = smd->vcom;
  131. u8 *tx_buffer = smd->tx_buffer;
  132. u32 tx_buffer_size = smd->tx_buffer_size;
  133. mutex_lock(&smd->tx_mutex);
  134. /* Populate the transmit buffer with frame data */
  135. sharp_memory_set_tx_buffer_mode(&tx_buffer[0],
  136. SHARP_MEMORY_DISPLAY_UPDATE_MODE, vcom);
  137. sharp_memory_set_tx_buffer_addresses(&tx_buffer[1], clip, pitch);
  138. sharp_memory_set_tx_buffer_data(&tx_buffer[2], fb, vmap, clip, pitch, fmtcnv_state);
  139. ret = sharp_memory_spi_write(smd->spi, tx_buffer, tx_buffer_size);
  140. mutex_unlock(&smd->tx_mutex);
  141. return ret;
  142. }
  143. static int sharp_memory_maintain_display(struct sharp_memory_device *smd)
  144. {
  145. int ret;
  146. u8 vcom = smd->vcom;
  147. u8 *tx_buffer = smd->tx_buffer;
  148. mutex_lock(&smd->tx_mutex);
  149. sharp_memory_set_tx_buffer_mode(&tx_buffer[0], SHARP_MEMORY_DISPLAY_MAINTAIN_MODE, vcom);
  150. tx_buffer[1] = 0; /* Write dummy data */
  151. ret = sharp_memory_spi_write(smd->spi, tx_buffer, 2);
  152. mutex_unlock(&smd->tx_mutex);
  153. return ret;
  154. }
  155. static int sharp_memory_clear_display(struct sharp_memory_device *smd)
  156. {
  157. int ret;
  158. u8 vcom = smd->vcom;
  159. u8 *tx_buffer = smd->tx_buffer;
  160. mutex_lock(&smd->tx_mutex);
  161. sharp_memory_set_tx_buffer_mode(&tx_buffer[0], SHARP_MEMORY_DISPLAY_CLEAR_MODE, vcom);
  162. tx_buffer[1] = 0; /* write dummy data */
  163. ret = sharp_memory_spi_write(smd->spi, tx_buffer, 2);
  164. mutex_unlock(&smd->tx_mutex);
  165. return ret;
  166. }
  167. static void sharp_memory_fb_dirty(struct drm_framebuffer *fb, const struct iosys_map *vmap,
  168. struct drm_rect *rect,
  169. struct drm_format_conv_state *fmtconv_state)
  170. {
  171. struct drm_rect clip;
  172. struct sharp_memory_device *smd = drm_to_sharp_memory_device(fb->dev);
  173. /* Always update a full line regardless of what is dirty */
  174. clip.x1 = 0;
  175. clip.x2 = fb->width;
  176. clip.y1 = rect->y1;
  177. clip.y2 = rect->y2;
  178. sharp_memory_update_display(smd, fb, vmap, clip, fmtconv_state);
  179. }
  180. static int sharp_memory_plane_atomic_check(struct drm_plane *plane,
  181. struct drm_atomic_state *state)
  182. {
  183. struct drm_plane_state *plane_state = drm_atomic_get_new_plane_state(state, plane);
  184. struct sharp_memory_device *smd;
  185. struct drm_crtc_state *crtc_state;
  186. smd = container_of(plane, struct sharp_memory_device, plane);
  187. crtc_state = drm_atomic_get_new_crtc_state(state, &smd->crtc);
  188. return drm_atomic_helper_check_plane_state(plane_state, crtc_state,
  189. DRM_PLANE_NO_SCALING,
  190. DRM_PLANE_NO_SCALING,
  191. false, false);
  192. }
  193. static void sharp_memory_plane_atomic_update(struct drm_plane *plane,
  194. struct drm_atomic_state *state)
  195. {
  196. struct drm_plane_state *old_state = drm_atomic_get_old_plane_state(state, plane);
  197. struct drm_plane_state *plane_state = plane->state;
  198. struct drm_shadow_plane_state *shadow_plane_state = to_drm_shadow_plane_state(plane_state);
  199. struct sharp_memory_device *smd;
  200. struct drm_rect rect;
  201. smd = container_of(plane, struct sharp_memory_device, plane);
  202. if (!smd->crtc.state->active)
  203. return;
  204. if (drm_atomic_helper_damage_merged(old_state, plane_state, &rect))
  205. sharp_memory_fb_dirty(plane_state->fb, shadow_plane_state->data,
  206. &rect, &shadow_plane_state->fmtcnv_state);
  207. }
  208. static const struct drm_plane_helper_funcs sharp_memory_plane_helper_funcs = {
  209. .prepare_fb = drm_gem_plane_helper_prepare_fb,
  210. .atomic_check = sharp_memory_plane_atomic_check,
  211. .atomic_update = sharp_memory_plane_atomic_update,
  212. DRM_GEM_SHADOW_PLANE_HELPER_FUNCS,
  213. };
  214. static bool sharp_memory_format_mod_supported(struct drm_plane *plane,
  215. u32 format,
  216. u64 modifier)
  217. {
  218. return modifier == DRM_FORMAT_MOD_LINEAR;
  219. }
  220. static const struct drm_plane_funcs sharp_memory_plane_funcs = {
  221. .update_plane = drm_atomic_helper_update_plane,
  222. .disable_plane = drm_atomic_helper_disable_plane,
  223. .destroy = drm_plane_cleanup,
  224. DRM_GEM_SHADOW_PLANE_FUNCS,
  225. .format_mod_supported = sharp_memory_format_mod_supported,
  226. };
  227. static enum drm_mode_status sharp_memory_crtc_mode_valid(struct drm_crtc *crtc,
  228. const struct drm_display_mode *mode)
  229. {
  230. struct sharp_memory_device *smd = drm_to_sharp_memory_device(crtc->dev);
  231. return drm_crtc_helper_mode_valid_fixed(crtc, mode, smd->mode);
  232. }
  233. static int sharp_memory_crtc_check(struct drm_crtc *crtc,
  234. struct drm_atomic_state *state)
  235. {
  236. struct drm_crtc_state *crtc_state = drm_atomic_get_new_crtc_state(state, crtc);
  237. int ret;
  238. if (!crtc_state->enable)
  239. goto out;
  240. ret = drm_atomic_helper_check_crtc_primary_plane(crtc_state);
  241. if (ret)
  242. return ret;
  243. out:
  244. return drm_atomic_add_affected_planes(state, crtc);
  245. }
  246. static int sharp_memory_sw_vcom_signal_thread(void *data)
  247. {
  248. struct sharp_memory_device *smd = data;
  249. while (!kthread_should_stop()) {
  250. smd->vcom ^= 1; /* Toggle vcom */
  251. sharp_memory_maintain_display(smd);
  252. msleep(1000);
  253. }
  254. return 0;
  255. }
  256. static void sharp_memory_crtc_enable(struct drm_crtc *crtc,
  257. struct drm_atomic_state *state)
  258. {
  259. struct sharp_memory_device *smd = drm_to_sharp_memory_device(crtc->dev);
  260. sharp_memory_clear_display(smd);
  261. if (smd->enable_gpio)
  262. gpiod_set_value(smd->enable_gpio, 1);
  263. }
  264. static void sharp_memory_crtc_disable(struct drm_crtc *crtc,
  265. struct drm_atomic_state *state)
  266. {
  267. struct sharp_memory_device *smd = drm_to_sharp_memory_device(crtc->dev);
  268. sharp_memory_clear_display(smd);
  269. if (smd->enable_gpio)
  270. gpiod_set_value(smd->enable_gpio, 0);
  271. }
  272. static const struct drm_crtc_helper_funcs sharp_memory_crtc_helper_funcs = {
  273. .mode_valid = sharp_memory_crtc_mode_valid,
  274. .atomic_check = sharp_memory_crtc_check,
  275. .atomic_enable = sharp_memory_crtc_enable,
  276. .atomic_disable = sharp_memory_crtc_disable,
  277. };
  278. static const struct drm_crtc_funcs sharp_memory_crtc_funcs = {
  279. .reset = drm_atomic_helper_crtc_reset,
  280. .destroy = drm_crtc_cleanup,
  281. .set_config = drm_atomic_helper_set_config,
  282. .page_flip = drm_atomic_helper_page_flip,
  283. .atomic_duplicate_state = drm_atomic_helper_crtc_duplicate_state,
  284. .atomic_destroy_state = drm_atomic_helper_crtc_destroy_state,
  285. };
  286. static const struct drm_encoder_funcs sharp_memory_encoder_funcs = {
  287. .destroy = drm_encoder_cleanup,
  288. };
  289. static int sharp_memory_connector_get_modes(struct drm_connector *connector)
  290. {
  291. struct sharp_memory_device *smd = drm_to_sharp_memory_device(connector->dev);
  292. return drm_connector_helper_get_modes_fixed(connector, smd->mode);
  293. }
  294. static const struct drm_connector_helper_funcs sharp_memory_connector_hfuncs = {
  295. .get_modes = sharp_memory_connector_get_modes,
  296. };
  297. static const struct drm_connector_funcs sharp_memory_connector_funcs = {
  298. .reset = drm_atomic_helper_connector_reset,
  299. .fill_modes = drm_helper_probe_single_connector_modes,
  300. .destroy = drm_connector_cleanup,
  301. .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
  302. .atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
  303. };
  304. static const struct drm_mode_config_funcs sharp_memory_mode_config_funcs = {
  305. .fb_create = drm_gem_fb_create_with_dirty,
  306. .atomic_check = drm_atomic_helper_check,
  307. .atomic_commit = drm_atomic_helper_commit,
  308. };
  309. static const struct drm_display_mode sharp_memory_ls010b7dh04_mode = {
  310. DRM_SIMPLE_MODE(128, 128, 18, 18),
  311. };
  312. static const struct drm_display_mode sharp_memory_ls011b7dh03_mode = {
  313. DRM_SIMPLE_MODE(160, 68, 25, 10),
  314. };
  315. static const struct drm_display_mode sharp_memory_ls012b7dd01_mode = {
  316. DRM_SIMPLE_MODE(184, 38, 29, 6),
  317. };
  318. static const struct drm_display_mode sharp_memory_ls013b7dh03_mode = {
  319. DRM_SIMPLE_MODE(128, 128, 23, 23),
  320. };
  321. static const struct drm_display_mode sharp_memory_ls013b7dh05_mode = {
  322. DRM_SIMPLE_MODE(144, 168, 20, 24),
  323. };
  324. static const struct drm_display_mode sharp_memory_ls018b7dh02_mode = {
  325. DRM_SIMPLE_MODE(230, 303, 27, 36),
  326. };
  327. static const struct drm_display_mode sharp_memory_ls027b7dh01_mode = {
  328. DRM_SIMPLE_MODE(400, 240, 58, 35),
  329. };
  330. static const struct drm_display_mode sharp_memory_ls032b7dd02_mode = {
  331. DRM_SIMPLE_MODE(336, 536, 42, 68),
  332. };
  333. static const struct drm_display_mode sharp_memory_ls044q7dh01_mode = {
  334. DRM_SIMPLE_MODE(320, 240, 89, 67),
  335. };
  336. static const struct spi_device_id sharp_memory_ids[] = {
  337. {"ls010b7dh04", (kernel_ulong_t)&sharp_memory_ls010b7dh04_mode},
  338. {"ls011b7dh03", (kernel_ulong_t)&sharp_memory_ls011b7dh03_mode},
  339. {"ls012b7dd01", (kernel_ulong_t)&sharp_memory_ls012b7dd01_mode},
  340. {"ls013b7dh03", (kernel_ulong_t)&sharp_memory_ls013b7dh03_mode},
  341. {"ls013b7dh05", (kernel_ulong_t)&sharp_memory_ls013b7dh05_mode},
  342. {"ls018b7dh02", (kernel_ulong_t)&sharp_memory_ls018b7dh02_mode},
  343. {"ls027b7dh01", (kernel_ulong_t)&sharp_memory_ls027b7dh01_mode},
  344. {"ls027b7dh01a", (kernel_ulong_t)&sharp_memory_ls027b7dh01_mode},
  345. {"ls032b7dd02", (kernel_ulong_t)&sharp_memory_ls032b7dd02_mode},
  346. {"ls044q7dh01", (kernel_ulong_t)&sharp_memory_ls044q7dh01_mode},
  347. {},
  348. };
  349. MODULE_DEVICE_TABLE(spi, sharp_memory_ids);
  350. static const struct of_device_id sharp_memory_of_match[] = {
  351. {.compatible = "sharp,ls010b7dh04", &sharp_memory_ls010b7dh04_mode},
  352. {.compatible = "sharp,ls011b7dh03", &sharp_memory_ls011b7dh03_mode},
  353. {.compatible = "sharp,ls012b7dd01", &sharp_memory_ls012b7dd01_mode},
  354. {.compatible = "sharp,ls013b7dh03", &sharp_memory_ls013b7dh03_mode},
  355. {.compatible = "sharp,ls013b7dh05", &sharp_memory_ls013b7dh05_mode},
  356. {.compatible = "sharp,ls018b7dh02", &sharp_memory_ls018b7dh02_mode},
  357. {.compatible = "sharp,ls027b7dh01", &sharp_memory_ls027b7dh01_mode},
  358. {.compatible = "sharp,ls027b7dh01a", &sharp_memory_ls027b7dh01_mode},
  359. {.compatible = "sharp,ls032b7dd02", &sharp_memory_ls032b7dd02_mode},
  360. {.compatible = "sharp,ls044q7dh01", &sharp_memory_ls044q7dh01_mode},
  361. {},
  362. };
  363. MODULE_DEVICE_TABLE(of, sharp_memory_of_match);
  364. static const u32 sharp_memory_formats[] = {
  365. DRM_FORMAT_XRGB8888,
  366. };
  367. static int sharp_memory_pipe_init(struct drm_device *dev,
  368. struct sharp_memory_device *smd,
  369. const u32 *formats, unsigned int format_count,
  370. const u64 *format_modifiers)
  371. {
  372. int ret;
  373. struct drm_encoder *encoder = &smd->encoder;
  374. struct drm_plane *plane = &smd->plane;
  375. struct drm_crtc *crtc = &smd->crtc;
  376. struct drm_connector *connector = &smd->connector;
  377. drm_plane_helper_add(plane, &sharp_memory_plane_helper_funcs);
  378. ret = drm_universal_plane_init(dev, plane, 0,
  379. &sharp_memory_plane_funcs,
  380. formats, format_count,
  381. format_modifiers,
  382. DRM_PLANE_TYPE_PRIMARY, NULL);
  383. if (ret)
  384. return ret;
  385. drm_crtc_helper_add(crtc, &sharp_memory_crtc_helper_funcs);
  386. ret = drm_crtc_init_with_planes(dev, crtc, plane, NULL,
  387. &sharp_memory_crtc_funcs, NULL);
  388. if (ret)
  389. return ret;
  390. encoder->possible_crtcs = drm_crtc_mask(crtc);
  391. ret = drm_encoder_init(dev, encoder, &sharp_memory_encoder_funcs,
  392. DRM_MODE_ENCODER_NONE, NULL);
  393. if (ret)
  394. return ret;
  395. ret = drm_connector_init(&smd->drm, &smd->connector,
  396. &sharp_memory_connector_funcs,
  397. DRM_MODE_CONNECTOR_SPI);
  398. if (ret)
  399. return ret;
  400. drm_connector_helper_add(&smd->connector,
  401. &sharp_memory_connector_hfuncs);
  402. return drm_connector_attach_encoder(connector, encoder);
  403. }
  404. static int sharp_memory_init_pwm_vcom_signal(struct sharp_memory_device *smd)
  405. {
  406. int ret;
  407. struct device *dev = &smd->spi->dev;
  408. struct pwm_state pwm_state;
  409. smd->pwm_vcom_signal = devm_pwm_get(dev, NULL);
  410. if (IS_ERR(smd->pwm_vcom_signal))
  411. return dev_err_probe(dev, PTR_ERR(smd->pwm_vcom_signal),
  412. "Could not get pwm device\n");
  413. pwm_init_state(smd->pwm_vcom_signal, &pwm_state);
  414. pwm_set_relative_duty_cycle(&pwm_state, 1, 10);
  415. pwm_state.enabled = true;
  416. ret = pwm_apply_might_sleep(smd->pwm_vcom_signal, &pwm_state);
  417. if (ret)
  418. return dev_err_probe(dev, -EINVAL, "Could not apply pwm state\n");
  419. return 0;
  420. }
  421. static int sharp_memory_probe(struct spi_device *spi)
  422. {
  423. int ret;
  424. struct device *dev;
  425. struct sharp_memory_device *smd;
  426. struct drm_device *drm;
  427. const char *vcom_mode_str;
  428. dev = &spi->dev;
  429. ret = spi_setup(spi);
  430. if (ret < 0)
  431. return dev_err_probe(dev, ret, "Failed to setup spi device\n");
  432. if (!dev->coherent_dma_mask) {
  433. ret = dma_coerce_mask_and_coherent(dev, DMA_BIT_MASK(32));
  434. if (ret)
  435. return dev_err_probe(dev, ret, "Failed to set dma mask\n");
  436. }
  437. smd = devm_drm_dev_alloc(dev, &sharp_memory_drm_driver,
  438. struct sharp_memory_device, drm);
  439. if (IS_ERR(smd))
  440. return PTR_ERR(smd);
  441. spi_set_drvdata(spi, smd);
  442. smd->spi = spi;
  443. drm = &smd->drm;
  444. ret = drmm_mode_config_init(drm);
  445. if (ret)
  446. return dev_err_probe(dev, ret, "Failed to initialize drm config\n");
  447. smd->enable_gpio = devm_gpiod_get_optional(dev, "enable", GPIOD_OUT_HIGH);
  448. if (!smd->enable_gpio)
  449. dev_warn(dev, "Enable gpio not defined\n");
  450. drm->mode_config.funcs = &sharp_memory_mode_config_funcs;
  451. smd->mode = spi_get_device_match_data(spi);
  452. smd->pitch = (SHARP_ADDR_PERIOD + smd->mode->hdisplay + SHARP_DUMMY_PERIOD) / 8;
  453. smd->tx_buffer_size = (SHARP_MODE_PERIOD +
  454. (SHARP_ADDR_PERIOD + (smd->mode->hdisplay) + SHARP_DUMMY_PERIOD) *
  455. smd->mode->vdisplay) / 8;
  456. smd->tx_buffer = devm_kzalloc(dev, smd->tx_buffer_size, GFP_KERNEL);
  457. if (!smd->tx_buffer)
  458. return -ENOMEM;
  459. mutex_init(&smd->tx_mutex);
  460. /*
  461. * VCOM is a signal that prevents DC bias from being built up in
  462. * the panel resulting in pixels being forever stuck in one state.
  463. *
  464. * This driver supports three different methods to generate this
  465. * signal depending on EXTMODE pin:
  466. *
  467. * software (EXTMODE = L) - This mode uses a kthread to
  468. * periodically send a "maintain display" message to the display,
  469. * toggling the vcom bit on and off with each message
  470. *
  471. * external (EXTMODE = H) - This mode relies on an external
  472. * clock to generate the signal on the EXTCOMM pin
  473. *
  474. * pwm (EXTMODE = H) - This mode uses a pwm device to generate
  475. * the signal on the EXTCOMM pin
  476. *
  477. */
  478. if (device_property_read_string(dev, "sharp,vcom-mode", &vcom_mode_str))
  479. return dev_err_probe(dev, -EINVAL,
  480. "Unable to find sharp,vcom-mode node in device tree\n");
  481. if (!strcmp("software", vcom_mode_str)) {
  482. smd->vcom_mode = SHARP_MEMORY_SOFTWARE_VCOM;
  483. smd->sw_vcom_signal = kthread_run(sharp_memory_sw_vcom_signal_thread,
  484. smd, "sw_vcom_signal");
  485. } else if (!strcmp("external", vcom_mode_str)) {
  486. smd->vcom_mode = SHARP_MEMORY_EXTERNAL_VCOM;
  487. } else if (!strcmp("pwm", vcom_mode_str)) {
  488. smd->vcom_mode = SHARP_MEMORY_PWM_VCOM;
  489. ret = sharp_memory_init_pwm_vcom_signal(smd);
  490. if (ret)
  491. return ret;
  492. } else {
  493. return dev_err_probe(dev, -EINVAL, "Invalid value set for vcom-mode\n");
  494. }
  495. drm->mode_config.min_width = smd->mode->hdisplay;
  496. drm->mode_config.max_width = smd->mode->hdisplay;
  497. drm->mode_config.min_height = smd->mode->vdisplay;
  498. drm->mode_config.max_height = smd->mode->vdisplay;
  499. ret = sharp_memory_pipe_init(drm, smd, sharp_memory_formats,
  500. ARRAY_SIZE(sharp_memory_formats),
  501. NULL);
  502. if (ret)
  503. return dev_err_probe(dev, ret, "Failed to initialize display pipeline.\n");
  504. drm_plane_enable_fb_damage_clips(&smd->plane);
  505. drm_mode_config_reset(drm);
  506. ret = drm_dev_register(drm, 0);
  507. if (ret)
  508. return dev_err_probe(dev, ret, "Failed to register drm device.\n");
  509. drm_client_setup(drm, NULL);
  510. return 0;
  511. }
  512. static void sharp_memory_remove(struct spi_device *spi)
  513. {
  514. struct sharp_memory_device *smd = spi_get_drvdata(spi);
  515. drm_dev_unplug(&smd->drm);
  516. drm_atomic_helper_shutdown(&smd->drm);
  517. switch (smd->vcom_mode) {
  518. case SHARP_MEMORY_SOFTWARE_VCOM:
  519. kthread_stop(smd->sw_vcom_signal);
  520. break;
  521. case SHARP_MEMORY_EXTERNAL_VCOM:
  522. break;
  523. case SHARP_MEMORY_PWM_VCOM:
  524. pwm_disable(smd->pwm_vcom_signal);
  525. break;
  526. }
  527. }
  528. static struct spi_driver sharp_memory_spi_driver = {
  529. .driver = {
  530. .name = "sharp_memory",
  531. .of_match_table = sharp_memory_of_match,
  532. },
  533. .probe = sharp_memory_probe,
  534. .remove = sharp_memory_remove,
  535. .id_table = sharp_memory_ids,
  536. };
  537. module_spi_driver(sharp_memory_spi_driver);
  538. MODULE_AUTHOR("Alex Lanzano <lanzano.alex@gmail.com>");
  539. MODULE_DESCRIPTION("SPI Protocol driver for the sharp_memory display");
  540. MODULE_LICENSE("GPL");