gud_pipe.c 16 KB

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