gud_pipe.c 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658
  1. // SPDX-License-Identifier: MIT
  2. /*
  3. * Copyright 2020 Noralf Trønnes
  4. */
  5. #include <linux/lz4.h>
  6. #include <linux/usb.h>
  7. #include <linux/vmalloc.h>
  8. #include <linux/workqueue.h>
  9. #include <drm/drm_atomic.h>
  10. #include <drm/drm_connector.h>
  11. #include <drm/drm_damage_helper.h>
  12. #include <drm/drm_drv.h>
  13. #include <drm/drm_format_helper.h>
  14. #include <drm/drm_fourcc.h>
  15. #include <drm/drm_framebuffer.h>
  16. #include <drm/drm_gem.h>
  17. #include <drm/drm_gem_atomic_helper.h>
  18. #include <drm/drm_gem_framebuffer_helper.h>
  19. #include <drm/drm_print.h>
  20. #include <drm/drm_rect.h>
  21. #include <drm/gud.h>
  22. #include "gud_internal.h"
  23. /*
  24. * Some userspace rendering loops run all displays in the same loop.
  25. * This means that a fast display will have to wait for a slow one.
  26. * Such users might want to enable this module parameter.
  27. */
  28. static bool gud_async_flush;
  29. module_param_named(async_flush, gud_async_flush, bool, 0644);
  30. MODULE_PARM_DESC(async_flush, "Enable asynchronous flushing [default=0]");
  31. /*
  32. * FIXME: The driver is probably broken on Big Endian machines.
  33. * See discussion:
  34. * https://lore.kernel.org/dri-devel/CAKb7UvihLX0hgBOP3VBG7O+atwZcUVCPVuBdfmDMpg0NjXe-cQ@mail.gmail.com/
  35. */
  36. static bool gud_is_big_endian(void)
  37. {
  38. #if defined(__BIG_ENDIAN)
  39. return true;
  40. #else
  41. return false;
  42. #endif
  43. }
  44. static size_t gud_xrgb8888_to_r124(u8 *dst, const struct drm_format_info *format,
  45. void *src, struct drm_framebuffer *fb,
  46. struct drm_rect *rect,
  47. struct drm_format_conv_state *fmtcnv_state)
  48. {
  49. unsigned int block_width = drm_format_info_block_width(format, 0);
  50. unsigned int bits_per_pixel = 8 / block_width;
  51. unsigned int x, y, width, height;
  52. u8 pix, *pix8, *block = dst; /* Assign to silence compiler warning */
  53. struct iosys_map dst_map, vmap;
  54. size_t len;
  55. void *buf;
  56. drm_WARN_ON_ONCE(fb->dev, format->char_per_block[0] != 1);
  57. /* Start on a byte boundary */
  58. rect->x1 = ALIGN_DOWN(rect->x1, block_width);
  59. width = drm_rect_width(rect);
  60. height = drm_rect_height(rect);
  61. len = drm_format_info_min_pitch(format, 0, width) * height;
  62. buf = kmalloc_array(height, width, GFP_KERNEL);
  63. if (!buf)
  64. return 0;
  65. iosys_map_set_vaddr(&dst_map, buf);
  66. iosys_map_set_vaddr(&vmap, src);
  67. drm_fb_xrgb8888_to_gray8(&dst_map, NULL, &vmap, fb, rect, fmtcnv_state);
  68. pix8 = buf;
  69. for (y = 0; y < height; y++) {
  70. for (x = 0; x < width; x++) {
  71. unsigned int pixpos = x % block_width; /* within byte from the left */
  72. unsigned int pixshift = (block_width - pixpos - 1) * bits_per_pixel;
  73. if (!pixpos) {
  74. block = dst++;
  75. *block = 0;
  76. }
  77. pix = (*pix8++) >> (8 - bits_per_pixel);
  78. *block |= pix << pixshift;
  79. }
  80. }
  81. kfree(buf);
  82. return len;
  83. }
  84. static size_t gud_xrgb8888_to_color(u8 *dst, const struct drm_format_info *format,
  85. void *src, struct drm_framebuffer *fb,
  86. struct drm_rect *rect)
  87. {
  88. unsigned int block_width = drm_format_info_block_width(format, 0);
  89. unsigned int bits_per_pixel = 8 / block_width;
  90. u8 r, g, b, pix, *block = dst; /* Assign to silence compiler warning */
  91. unsigned int x, y, width;
  92. __le32 *sbuf32;
  93. u32 pix32;
  94. size_t len;
  95. /* Start on a byte boundary */
  96. rect->x1 = ALIGN_DOWN(rect->x1, block_width);
  97. width = drm_rect_width(rect);
  98. len = drm_format_info_min_pitch(format, 0, width) * drm_rect_height(rect);
  99. for (y = rect->y1; y < rect->y2; y++) {
  100. sbuf32 = src + (y * fb->pitches[0]);
  101. sbuf32 += rect->x1;
  102. for (x = 0; x < width; x++) {
  103. unsigned int pixpos = x % block_width; /* within byte from the left */
  104. unsigned int pixshift = (block_width - pixpos - 1) * bits_per_pixel;
  105. if (!pixpos) {
  106. block = dst++;
  107. *block = 0;
  108. }
  109. pix32 = le32_to_cpu(*sbuf32++);
  110. r = pix32 >> 16;
  111. g = pix32 >> 8;
  112. b = pix32;
  113. switch (format->format) {
  114. case GUD_DRM_FORMAT_XRGB1111:
  115. pix = ((r >> 7) << 2) | ((g >> 7) << 1) | (b >> 7);
  116. break;
  117. default:
  118. drm_WARN_ON_ONCE(fb->dev, 1);
  119. return len;
  120. }
  121. *block |= pix << pixshift;
  122. }
  123. }
  124. return len;
  125. }
  126. static int gud_prep_flush(struct gud_device *gdrm, struct drm_framebuffer *fb,
  127. const struct iosys_map *src, bool cached_reads,
  128. const struct drm_format_info *format, struct drm_rect *rect,
  129. struct gud_set_buffer_req *req,
  130. struct drm_format_conv_state *fmtcnv_state)
  131. {
  132. u8 compression = gdrm->compression;
  133. struct iosys_map dst;
  134. void *vaddr, *buf;
  135. size_t pitch, len;
  136. pitch = drm_format_info_min_pitch(format, 0, drm_rect_width(rect));
  137. len = pitch * drm_rect_height(rect);
  138. if (len > gdrm->bulk_len)
  139. return -E2BIG;
  140. vaddr = src[0].vaddr;
  141. retry:
  142. if (compression)
  143. buf = gdrm->compress_buf;
  144. else
  145. buf = gdrm->bulk_buf;
  146. iosys_map_set_vaddr(&dst, buf);
  147. /*
  148. * Imported buffers are assumed to be write-combined and thus uncached
  149. * with slow reads (at least on ARM).
  150. */
  151. if (format != fb->format) {
  152. if (format->format == GUD_DRM_FORMAT_R1) {
  153. len = gud_xrgb8888_to_r124(buf, format, vaddr, fb, rect, fmtcnv_state);
  154. if (!len)
  155. return -ENOMEM;
  156. } else if (format->format == DRM_FORMAT_R8) {
  157. drm_fb_xrgb8888_to_gray8(&dst, NULL, src, fb, rect, fmtcnv_state);
  158. } else if (format->format == DRM_FORMAT_RGB332) {
  159. drm_fb_xrgb8888_to_rgb332(&dst, NULL, src, fb, rect, fmtcnv_state);
  160. } else if (format->format == DRM_FORMAT_RGB565) {
  161. if (gud_is_big_endian()) {
  162. drm_fb_xrgb8888_to_rgb565be(&dst, NULL, src, fb, rect,
  163. fmtcnv_state);
  164. } else {
  165. drm_fb_xrgb8888_to_rgb565(&dst, NULL, src, fb, rect,
  166. fmtcnv_state);
  167. }
  168. } else if (format->format == DRM_FORMAT_RGB888) {
  169. drm_fb_xrgb8888_to_rgb888(&dst, NULL, src, fb, rect, fmtcnv_state);
  170. } else {
  171. len = gud_xrgb8888_to_color(buf, format, vaddr, fb, rect);
  172. }
  173. } else if (gud_is_big_endian() && format->cpp[0] > 1) {
  174. drm_fb_swab(&dst, NULL, src, fb, rect, cached_reads, fmtcnv_state);
  175. } else if (compression && cached_reads && pitch == fb->pitches[0]) {
  176. /* can compress directly from the framebuffer */
  177. buf = vaddr + rect->y1 * pitch;
  178. } else {
  179. drm_fb_memcpy(&dst, NULL, src, fb, rect);
  180. }
  181. memset(req, 0, sizeof(*req));
  182. req->x = cpu_to_le32(rect->x1);
  183. req->y = cpu_to_le32(rect->y1);
  184. req->width = cpu_to_le32(drm_rect_width(rect));
  185. req->height = cpu_to_le32(drm_rect_height(rect));
  186. req->length = cpu_to_le32(len);
  187. if (compression & GUD_COMPRESSION_LZ4) {
  188. int complen;
  189. complen = LZ4_compress_default(buf, gdrm->bulk_buf, len, len, gdrm->lz4_comp_mem);
  190. if (complen <= 0) {
  191. compression = 0;
  192. goto retry;
  193. }
  194. req->compression = GUD_COMPRESSION_LZ4;
  195. req->compressed_length = cpu_to_le32(complen);
  196. }
  197. return 0;
  198. }
  199. struct gud_usb_bulk_context {
  200. struct timer_list timer;
  201. struct usb_sg_request sgr;
  202. };
  203. static void gud_usb_bulk_timeout(struct timer_list *t)
  204. {
  205. struct gud_usb_bulk_context *ctx = timer_container_of(ctx, t, timer);
  206. usb_sg_cancel(&ctx->sgr);
  207. }
  208. static int gud_usb_bulk(struct gud_device *gdrm, size_t len)
  209. {
  210. struct gud_usb_bulk_context ctx;
  211. int ret;
  212. ret = usb_sg_init(&ctx.sgr, gud_to_usb_device(gdrm), gdrm->bulk_pipe, 0,
  213. gdrm->bulk_sgt.sgl, gdrm->bulk_sgt.nents, len, GFP_KERNEL);
  214. if (ret)
  215. return ret;
  216. timer_setup_on_stack(&ctx.timer, gud_usb_bulk_timeout, 0);
  217. mod_timer(&ctx.timer, jiffies + msecs_to_jiffies(3000));
  218. usb_sg_wait(&ctx.sgr);
  219. if (!timer_delete_sync(&ctx.timer))
  220. ret = -ETIMEDOUT;
  221. else if (ctx.sgr.status < 0)
  222. ret = ctx.sgr.status;
  223. else if (ctx.sgr.bytes != len)
  224. ret = -EIO;
  225. timer_destroy_on_stack(&ctx.timer);
  226. return ret;
  227. }
  228. static int gud_flush_rect(struct gud_device *gdrm, struct drm_framebuffer *fb,
  229. const struct iosys_map *src, bool cached_reads,
  230. const struct drm_format_info *format, struct drm_rect *rect,
  231. struct drm_format_conv_state *fmtcnv_state)
  232. {
  233. struct gud_set_buffer_req req;
  234. size_t len, trlen;
  235. int ret;
  236. drm_dbg(&gdrm->drm, "Flushing [FB:%d] " DRM_RECT_FMT "\n", fb->base.id, DRM_RECT_ARG(rect));
  237. ret = gud_prep_flush(gdrm, fb, src, cached_reads, format, rect, &req, fmtcnv_state);
  238. if (ret)
  239. return ret;
  240. len = le32_to_cpu(req.length);
  241. if (req.compression)
  242. trlen = le32_to_cpu(req.compressed_length);
  243. else
  244. trlen = len;
  245. gdrm->stats_length += len;
  246. /* Did it wrap around? */
  247. if (gdrm->stats_length <= len && gdrm->stats_actual_length) {
  248. gdrm->stats_length = len;
  249. gdrm->stats_actual_length = 0;
  250. }
  251. gdrm->stats_actual_length += trlen;
  252. if (!(gdrm->flags & GUD_DISPLAY_FLAG_FULL_UPDATE) || gdrm->prev_flush_failed) {
  253. ret = gud_usb_set(gdrm, GUD_REQ_SET_BUFFER, 0, &req, sizeof(req));
  254. if (ret)
  255. return ret;
  256. }
  257. ret = gud_usb_bulk(gdrm, trlen);
  258. if (ret)
  259. gdrm->stats_num_errors++;
  260. return ret;
  261. }
  262. void gud_clear_damage(struct gud_device *gdrm)
  263. {
  264. gdrm->damage.x1 = INT_MAX;
  265. gdrm->damage.y1 = INT_MAX;
  266. gdrm->damage.x2 = 0;
  267. gdrm->damage.y2 = 0;
  268. }
  269. static void gud_flush_damage(struct gud_device *gdrm, struct drm_framebuffer *fb,
  270. const struct iosys_map *src, bool cached_reads,
  271. struct drm_rect *damage)
  272. {
  273. struct drm_format_conv_state fmtcnv_state = DRM_FORMAT_CONV_STATE_INIT;
  274. const struct drm_format_info *format;
  275. unsigned int i, lines;
  276. size_t pitch;
  277. int ret;
  278. format = fb->format;
  279. if (format->format == DRM_FORMAT_XRGB8888 && gdrm->xrgb8888_emulation_format)
  280. format = gdrm->xrgb8888_emulation_format;
  281. /* Split update if it's too big */
  282. pitch = drm_format_info_min_pitch(format, 0, drm_rect_width(damage));
  283. lines = drm_rect_height(damage);
  284. if (gdrm->bulk_len < lines * pitch)
  285. lines = gdrm->bulk_len / pitch;
  286. for (i = 0; i < DIV_ROUND_UP(drm_rect_height(damage), lines); i++) {
  287. struct drm_rect rect = *damage;
  288. rect.y1 += i * lines;
  289. rect.y2 = min_t(u32, rect.y1 + lines, damage->y2);
  290. ret = gud_flush_rect(gdrm, fb, src, cached_reads, format, &rect, &fmtcnv_state);
  291. if (ret) {
  292. if (ret != -ENODEV && ret != -ECONNRESET &&
  293. ret != -ESHUTDOWN && ret != -EPROTO)
  294. dev_err_ratelimited(fb->dev->dev,
  295. "Failed to flush framebuffer: error=%d\n", ret);
  296. gdrm->prev_flush_failed = true;
  297. break;
  298. }
  299. }
  300. drm_format_conv_state_release(&fmtcnv_state);
  301. }
  302. void gud_flush_work(struct work_struct *work)
  303. {
  304. struct gud_device *gdrm = container_of(work, struct gud_device, work);
  305. struct iosys_map shadow_map;
  306. struct drm_framebuffer *fb;
  307. struct drm_rect damage;
  308. int idx;
  309. if (!drm_dev_enter(&gdrm->drm, &idx))
  310. return;
  311. mutex_lock(&gdrm->damage_lock);
  312. fb = gdrm->fb;
  313. gdrm->fb = NULL;
  314. iosys_map_set_vaddr(&shadow_map, gdrm->shadow_buf);
  315. damage = gdrm->damage;
  316. gud_clear_damage(gdrm);
  317. mutex_unlock(&gdrm->damage_lock);
  318. if (!fb)
  319. goto out;
  320. gud_flush_damage(gdrm, fb, &shadow_map, true, &damage);
  321. drm_framebuffer_put(fb);
  322. out:
  323. drm_dev_exit(idx);
  324. }
  325. static int gud_fb_queue_damage(struct gud_device *gdrm, struct drm_framebuffer *fb,
  326. const struct iosys_map *src, struct drm_rect *damage)
  327. {
  328. struct drm_framebuffer *old_fb = NULL;
  329. struct iosys_map shadow_map;
  330. mutex_lock(&gdrm->damage_lock);
  331. if (!gdrm->shadow_buf) {
  332. gdrm->shadow_buf = vcalloc(fb->pitches[0], fb->height);
  333. if (!gdrm->shadow_buf) {
  334. mutex_unlock(&gdrm->damage_lock);
  335. return -ENOMEM;
  336. }
  337. }
  338. iosys_map_set_vaddr(&shadow_map, gdrm->shadow_buf);
  339. iosys_map_incr(&shadow_map, drm_fb_clip_offset(fb->pitches[0], fb->format, damage));
  340. drm_fb_memcpy(&shadow_map, fb->pitches, src, fb, damage);
  341. if (fb != gdrm->fb) {
  342. old_fb = gdrm->fb;
  343. drm_framebuffer_get(fb);
  344. gdrm->fb = fb;
  345. }
  346. gdrm->damage.x1 = min(gdrm->damage.x1, damage->x1);
  347. gdrm->damage.y1 = min(gdrm->damage.y1, damage->y1);
  348. gdrm->damage.x2 = max(gdrm->damage.x2, damage->x2);
  349. gdrm->damage.y2 = max(gdrm->damage.y2, damage->y2);
  350. mutex_unlock(&gdrm->damage_lock);
  351. queue_work(system_long_wq, &gdrm->work);
  352. if (old_fb)
  353. drm_framebuffer_put(old_fb);
  354. return 0;
  355. }
  356. static void gud_fb_handle_damage(struct gud_device *gdrm, struct drm_framebuffer *fb,
  357. const struct iosys_map *src, struct drm_rect *damage)
  358. {
  359. int ret;
  360. if (gdrm->flags & GUD_DISPLAY_FLAG_FULL_UPDATE)
  361. drm_rect_init(damage, 0, 0, fb->width, fb->height);
  362. if (gud_async_flush) {
  363. ret = gud_fb_queue_damage(gdrm, fb, src, damage);
  364. if (ret != -ENOMEM)
  365. return;
  366. }
  367. /* Imported buffers are assumed to be WriteCombined with uncached reads */
  368. gud_flush_damage(gdrm, fb, src, !fb->obj[0]->import_attach, damage);
  369. }
  370. int gud_plane_atomic_check(struct drm_plane *plane,
  371. struct drm_atomic_state *state)
  372. {
  373. struct gud_device *gdrm = to_gud_device(plane->dev);
  374. struct drm_plane_state *old_plane_state = drm_atomic_get_old_plane_state(state, plane);
  375. struct drm_plane_state *new_plane_state = drm_atomic_get_new_plane_state(state, plane);
  376. struct drm_crtc *crtc = new_plane_state->crtc;
  377. struct drm_crtc_state *crtc_state = NULL;
  378. const struct drm_display_mode *mode;
  379. struct drm_framebuffer *old_fb = old_plane_state->fb;
  380. struct drm_connector_state *connector_state = NULL;
  381. struct drm_framebuffer *fb = new_plane_state->fb;
  382. const struct drm_format_info *format;
  383. struct drm_connector *connector;
  384. unsigned int i, num_properties;
  385. struct gud_state_req *req;
  386. int idx, ret;
  387. size_t len;
  388. if (crtc)
  389. crtc_state = drm_atomic_get_new_crtc_state(state, crtc);
  390. ret = drm_atomic_helper_check_plane_state(new_plane_state, crtc_state,
  391. DRM_PLANE_NO_SCALING,
  392. DRM_PLANE_NO_SCALING,
  393. false, false);
  394. if (ret)
  395. return ret;
  396. if (!new_plane_state->visible)
  397. return 0;
  398. if (old_plane_state->rotation != new_plane_state->rotation)
  399. crtc_state->mode_changed = true;
  400. mode = &crtc_state->mode;
  401. format = fb->format;
  402. if (old_fb && old_fb->format != format)
  403. crtc_state->mode_changed = true;
  404. if (!crtc_state->mode_changed && !crtc_state->connectors_changed)
  405. return 0;
  406. /* Only one connector is supported */
  407. if (hweight32(crtc_state->connector_mask) != 1)
  408. return -EINVAL;
  409. if (format->format == DRM_FORMAT_XRGB8888 && gdrm->xrgb8888_emulation_format)
  410. format = gdrm->xrgb8888_emulation_format;
  411. for_each_new_connector_in_state(state, connector, connector_state, i) {
  412. if (connector_state->crtc)
  413. break;
  414. }
  415. /*
  416. * DRM_IOCTL_MODE_OBJ_SETPROPERTY on the rotation property will not have
  417. * the connector included in the state.
  418. */
  419. if (!connector_state) {
  420. struct drm_connector_list_iter conn_iter;
  421. drm_connector_list_iter_begin(plane->dev, &conn_iter);
  422. drm_for_each_connector_iter(connector, &conn_iter) {
  423. if (connector->state->crtc) {
  424. connector_state = connector->state;
  425. break;
  426. }
  427. }
  428. drm_connector_list_iter_end(&conn_iter);
  429. }
  430. if (drm_WARN_ON_ONCE(plane->dev, !connector_state))
  431. return -ENOENT;
  432. len = struct_size(req, properties,
  433. size_add(GUD_PROPERTIES_MAX_NUM, GUD_CONNECTOR_PROPERTIES_MAX_NUM));
  434. req = kzalloc(len, GFP_KERNEL);
  435. if (!req)
  436. return -ENOMEM;
  437. gud_from_display_mode(&req->mode, mode);
  438. req->format = gud_from_fourcc(format->format);
  439. if (drm_WARN_ON_ONCE(plane->dev, !req->format)) {
  440. ret = -EINVAL;
  441. goto out;
  442. }
  443. req->connector = drm_connector_index(connector_state->connector);
  444. ret = gud_connector_fill_properties(connector_state, req->properties);
  445. if (ret < 0)
  446. goto out;
  447. num_properties = ret;
  448. for (i = 0; i < gdrm->num_properties; i++) {
  449. u16 prop = gdrm->properties[i];
  450. u64 val;
  451. switch (prop) {
  452. case GUD_PROPERTY_ROTATION:
  453. /* DRM UAPI matches the protocol so use value directly */
  454. val = new_plane_state->rotation;
  455. break;
  456. default:
  457. drm_WARN_ON_ONCE(plane->dev, 1);
  458. ret = -EINVAL;
  459. goto out;
  460. }
  461. req->properties[num_properties + i].prop = cpu_to_le16(prop);
  462. req->properties[num_properties + i].val = cpu_to_le64(val);
  463. num_properties++;
  464. }
  465. if (drm_dev_enter(fb->dev, &idx)) {
  466. len = struct_size(req, properties, num_properties);
  467. ret = gud_usb_set(gdrm, GUD_REQ_SET_STATE_CHECK, 0, req, len);
  468. drm_dev_exit(idx);
  469. } else {
  470. ret = -ENODEV;
  471. }
  472. out:
  473. kfree(req);
  474. return ret;
  475. }
  476. void gud_crtc_atomic_enable(struct drm_crtc *crtc,
  477. struct drm_atomic_state *state)
  478. {
  479. struct drm_device *drm = crtc->dev;
  480. struct gud_device *gdrm = to_gud_device(drm);
  481. int idx;
  482. if (!drm_dev_enter(drm, &idx))
  483. return;
  484. gud_usb_set_u8(gdrm, GUD_REQ_SET_CONTROLLER_ENABLE, 1);
  485. gud_usb_set(gdrm, GUD_REQ_SET_STATE_COMMIT, 0, NULL, 0);
  486. gud_usb_set_u8(gdrm, GUD_REQ_SET_DISPLAY_ENABLE, 1);
  487. drm_dev_exit(idx);
  488. }
  489. void gud_crtc_atomic_disable(struct drm_crtc *crtc,
  490. struct drm_atomic_state *state)
  491. {
  492. struct drm_device *drm = crtc->dev;
  493. struct gud_device *gdrm = to_gud_device(drm);
  494. int idx;
  495. if (!drm_dev_enter(drm, &idx))
  496. return;
  497. gud_usb_set_u8(gdrm, GUD_REQ_SET_DISPLAY_ENABLE, 0);
  498. gud_usb_set_u8(gdrm, GUD_REQ_SET_CONTROLLER_ENABLE, 0);
  499. drm_dev_exit(idx);
  500. }
  501. void gud_plane_atomic_update(struct drm_plane *plane,
  502. struct drm_atomic_state *atomic_state)
  503. {
  504. struct drm_device *drm = plane->dev;
  505. struct gud_device *gdrm = to_gud_device(drm);
  506. struct drm_plane_state *old_state = drm_atomic_get_old_plane_state(atomic_state, plane);
  507. struct drm_plane_state *new_state = drm_atomic_get_new_plane_state(atomic_state, plane);
  508. struct drm_shadow_plane_state *shadow_plane_state = to_drm_shadow_plane_state(new_state);
  509. struct drm_framebuffer *fb = new_state->fb;
  510. struct drm_crtc *crtc = new_state->crtc;
  511. struct drm_rect damage;
  512. struct drm_atomic_helper_damage_iter iter;
  513. int ret, idx;
  514. if (!crtc || crtc->state->mode_changed || !crtc->state->enable) {
  515. cancel_work_sync(&gdrm->work);
  516. mutex_lock(&gdrm->damage_lock);
  517. if (gdrm->fb) {
  518. drm_framebuffer_put(gdrm->fb);
  519. gdrm->fb = NULL;
  520. }
  521. gud_clear_damage(gdrm);
  522. vfree(gdrm->shadow_buf);
  523. gdrm->shadow_buf = NULL;
  524. mutex_unlock(&gdrm->damage_lock);
  525. }
  526. if (!crtc || !drm_dev_enter(drm, &idx))
  527. return;
  528. ret = drm_gem_fb_begin_cpu_access(fb, DMA_FROM_DEVICE);
  529. if (ret)
  530. goto out;
  531. drm_atomic_helper_damage_iter_init(&iter, old_state, new_state);
  532. drm_atomic_for_each_plane_damage(&iter, &damage)
  533. gud_fb_handle_damage(gdrm, fb, &shadow_plane_state->data[0], &damage);
  534. drm_gem_fb_end_cpu_access(fb, DMA_FROM_DEVICE);
  535. out:
  536. drm_dev_exit(idx);
  537. }