vmwgfx_stdu.c 53 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879
  1. // SPDX-License-Identifier: GPL-2.0 OR MIT
  2. /******************************************************************************
  3. *
  4. * COPYRIGHT (C) 2014-2022 VMware, Inc., Palo Alto, CA., USA
  5. *
  6. * Permission is hereby granted, free of charge, to any person obtaining a
  7. * copy of this software and associated documentation files (the
  8. * "Software"), to deal in the Software without restriction, including
  9. * without limitation the rights to use, copy, modify, merge, publish,
  10. * distribute, sub license, and/or sell copies of the Software, and to
  11. * permit persons to whom the Software is furnished to do so, subject to
  12. * the following conditions:
  13. *
  14. * The above copyright notice and this permission notice (including the
  15. * next paragraph) shall be included in all copies or substantial portions
  16. * of the Software.
  17. *
  18. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  19. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  20. * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
  21. * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
  22. * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
  23. * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
  24. * USE OR OTHER DEALINGS IN THE SOFTWARE.
  25. *
  26. ******************************************************************************/
  27. #include <drm/drm_atomic.h>
  28. #include <drm/drm_atomic_helper.h>
  29. #include <drm/drm_damage_helper.h>
  30. #include <drm/drm_fourcc.h>
  31. #include "vmwgfx_kms.h"
  32. #include "vmw_surface_cache.h"
  33. #define vmw_crtc_to_stdu(x) \
  34. container_of(x, struct vmw_screen_target_display_unit, base.crtc)
  35. #define vmw_encoder_to_stdu(x) \
  36. container_of(x, struct vmw_screen_target_display_unit, base.encoder)
  37. #define vmw_connector_to_stdu(x) \
  38. container_of(x, struct vmw_screen_target_display_unit, base.connector)
  39. enum stdu_content_type {
  40. SAME_AS_DISPLAY = 0,
  41. SEPARATE_SURFACE,
  42. SEPARATE_BO
  43. };
  44. /**
  45. * struct vmw_stdu_dirty - closure structure for the update functions
  46. *
  47. * @base: The base type we derive from. Used by vmw_kms_helper_dirty().
  48. * @transfer: Transfer direction for DMA command.
  49. * @left: Left side of bounding box.
  50. * @right: Right side of bounding box.
  51. * @top: Top side of bounding box.
  52. * @bottom: Bottom side of bounding box.
  53. * @fb_left: Left side of the framebuffer/content bounding box
  54. * @fb_top: Top of the framebuffer/content bounding box
  55. * @pitch: framebuffer pitch (stride)
  56. * @buf: buffer object when DMA-ing between buffer and screen targets.
  57. * @sid: Surface ID when copying between surface and screen targets.
  58. */
  59. struct vmw_stdu_dirty {
  60. struct vmw_kms_dirty base;
  61. SVGA3dTransferType transfer;
  62. s32 left, right, top, bottom;
  63. s32 fb_left, fb_top;
  64. u32 pitch;
  65. union {
  66. struct vmw_buffer_object *buf;
  67. u32 sid;
  68. };
  69. };
  70. /*
  71. * SVGA commands that are used by this code. Please see the device headers
  72. * for explanation.
  73. */
  74. struct vmw_stdu_update {
  75. SVGA3dCmdHeader header;
  76. SVGA3dCmdUpdateGBScreenTarget body;
  77. };
  78. struct vmw_stdu_dma {
  79. SVGA3dCmdHeader header;
  80. SVGA3dCmdSurfaceDMA body;
  81. };
  82. struct vmw_stdu_surface_copy {
  83. SVGA3dCmdHeader header;
  84. SVGA3dCmdSurfaceCopy body;
  85. };
  86. struct vmw_stdu_update_gb_image {
  87. SVGA3dCmdHeader header;
  88. SVGA3dCmdUpdateGBImage body;
  89. };
  90. /**
  91. * struct vmw_screen_target_display_unit
  92. *
  93. * @base: VMW specific DU structure
  94. * @display_srf: surface to be displayed. The dimension of this will always
  95. * match the display mode. If the display mode matches
  96. * content_vfbs dimensions, then this is a pointer into the
  97. * corresponding field in content_vfbs. If not, then this
  98. * is a separate buffer to which content_vfbs will blit to.
  99. * @content_fb_type: content_fb type
  100. * @display_width: display width
  101. * @display_height: display height
  102. * @defined: true if the current display unit has been initialized
  103. * @cpp: Bytes per pixel
  104. */
  105. struct vmw_screen_target_display_unit {
  106. struct vmw_display_unit base;
  107. struct vmw_surface *display_srf;
  108. enum stdu_content_type content_fb_type;
  109. s32 display_width, display_height;
  110. bool defined;
  111. /* For CPU Blit */
  112. unsigned int cpp;
  113. };
  114. static void vmw_stdu_destroy(struct vmw_screen_target_display_unit *stdu);
  115. /******************************************************************************
  116. * Screen Target Display Unit CRTC Functions
  117. *****************************************************************************/
  118. static bool vmw_stdu_use_cpu_blit(const struct vmw_private *vmw)
  119. {
  120. return !(vmw->capabilities & SVGA_CAP_3D) || vmw->vram_size < (32 * 1024 * 1024);
  121. }
  122. /**
  123. * vmw_stdu_crtc_destroy - cleans up the STDU
  124. *
  125. * @crtc: used to get a reference to the containing STDU
  126. */
  127. static void vmw_stdu_crtc_destroy(struct drm_crtc *crtc)
  128. {
  129. vmw_stdu_destroy(vmw_crtc_to_stdu(crtc));
  130. }
  131. /**
  132. * vmw_stdu_define_st - Defines a Screen Target
  133. *
  134. * @dev_priv: VMW DRM device
  135. * @stdu: display unit to create a Screen Target for
  136. * @mode: The mode to set.
  137. * @crtc_x: X coordinate of screen target relative to framebuffer origin.
  138. * @crtc_y: Y coordinate of screen target relative to framebuffer origin.
  139. *
  140. * Creates a STDU that we can used later. This function is called whenever the
  141. * framebuffer size changes.
  142. *
  143. * RETURNs:
  144. * 0 on success, error code on failure
  145. */
  146. static int vmw_stdu_define_st(struct vmw_private *dev_priv,
  147. struct vmw_screen_target_display_unit *stdu,
  148. struct drm_display_mode *mode,
  149. int crtc_x, int crtc_y)
  150. {
  151. struct {
  152. SVGA3dCmdHeader header;
  153. SVGA3dCmdDefineGBScreenTarget body;
  154. } *cmd;
  155. cmd = VMW_CMD_RESERVE(dev_priv, sizeof(*cmd));
  156. if (unlikely(cmd == NULL))
  157. return -ENOMEM;
  158. cmd->header.id = SVGA_3D_CMD_DEFINE_GB_SCREENTARGET;
  159. cmd->header.size = sizeof(cmd->body);
  160. cmd->body.stid = stdu->base.unit;
  161. cmd->body.width = mode->hdisplay;
  162. cmd->body.height = mode->vdisplay;
  163. cmd->body.flags = (0 == cmd->body.stid) ? SVGA_STFLAG_PRIMARY : 0;
  164. cmd->body.dpi = 0;
  165. cmd->body.xRoot = crtc_x;
  166. cmd->body.yRoot = crtc_y;
  167. stdu->base.set_gui_x = cmd->body.xRoot;
  168. stdu->base.set_gui_y = cmd->body.yRoot;
  169. vmw_cmd_commit(dev_priv, sizeof(*cmd));
  170. stdu->defined = true;
  171. stdu->display_width = mode->hdisplay;
  172. stdu->display_height = mode->vdisplay;
  173. return 0;
  174. }
  175. /**
  176. * vmw_stdu_bind_st - Binds a surface to a Screen Target
  177. *
  178. * @dev_priv: VMW DRM device
  179. * @stdu: display unit affected
  180. * @res: Buffer to bind to the screen target. Set to NULL to blank screen.
  181. *
  182. * Binding a surface to a Screen Target the same as flipping
  183. */
  184. static int vmw_stdu_bind_st(struct vmw_private *dev_priv,
  185. struct vmw_screen_target_display_unit *stdu,
  186. const struct vmw_resource *res)
  187. {
  188. SVGA3dSurfaceImageId image;
  189. struct {
  190. SVGA3dCmdHeader header;
  191. SVGA3dCmdBindGBScreenTarget body;
  192. } *cmd;
  193. if (!stdu->defined) {
  194. DRM_ERROR("No screen target defined\n");
  195. return -EINVAL;
  196. }
  197. /* Set up image using information in vfb */
  198. memset(&image, 0, sizeof(image));
  199. image.sid = res ? res->id : SVGA3D_INVALID_ID;
  200. cmd = VMW_CMD_RESERVE(dev_priv, sizeof(*cmd));
  201. if (unlikely(cmd == NULL))
  202. return -ENOMEM;
  203. cmd->header.id = SVGA_3D_CMD_BIND_GB_SCREENTARGET;
  204. cmd->header.size = sizeof(cmd->body);
  205. cmd->body.stid = stdu->base.unit;
  206. cmd->body.image = image;
  207. vmw_cmd_commit(dev_priv, sizeof(*cmd));
  208. return 0;
  209. }
  210. /**
  211. * vmw_stdu_populate_update - populate an UPDATE_GB_SCREENTARGET command with a
  212. * bounding box.
  213. *
  214. * @cmd: Pointer to command stream.
  215. * @unit: Screen target unit.
  216. * @left: Left side of bounding box.
  217. * @right: Right side of bounding box.
  218. * @top: Top side of bounding box.
  219. * @bottom: Bottom side of bounding box.
  220. */
  221. static void vmw_stdu_populate_update(void *cmd, int unit,
  222. s32 left, s32 right, s32 top, s32 bottom)
  223. {
  224. struct vmw_stdu_update *update = cmd;
  225. update->header.id = SVGA_3D_CMD_UPDATE_GB_SCREENTARGET;
  226. update->header.size = sizeof(update->body);
  227. update->body.stid = unit;
  228. update->body.rect.x = left;
  229. update->body.rect.y = top;
  230. update->body.rect.w = right - left;
  231. update->body.rect.h = bottom - top;
  232. }
  233. /**
  234. * vmw_stdu_update_st - Full update of a Screen Target
  235. *
  236. * @dev_priv: VMW DRM device
  237. * @stdu: display unit affected
  238. *
  239. * This function needs to be called whenever the content of a screen
  240. * target has changed completely. Typically as a result of a backing
  241. * surface change.
  242. *
  243. * RETURNS:
  244. * 0 on success, error code on failure
  245. */
  246. static int vmw_stdu_update_st(struct vmw_private *dev_priv,
  247. struct vmw_screen_target_display_unit *stdu)
  248. {
  249. struct vmw_stdu_update *cmd;
  250. if (!stdu->defined) {
  251. DRM_ERROR("No screen target defined");
  252. return -EINVAL;
  253. }
  254. cmd = VMW_CMD_RESERVE(dev_priv, sizeof(*cmd));
  255. if (unlikely(cmd == NULL))
  256. return -ENOMEM;
  257. vmw_stdu_populate_update(cmd, stdu->base.unit,
  258. 0, stdu->display_width,
  259. 0, stdu->display_height);
  260. vmw_cmd_commit(dev_priv, sizeof(*cmd));
  261. return 0;
  262. }
  263. /**
  264. * vmw_stdu_destroy_st - Destroy a Screen Target
  265. *
  266. * @dev_priv: VMW DRM device
  267. * @stdu: display unit to destroy
  268. */
  269. static int vmw_stdu_destroy_st(struct vmw_private *dev_priv,
  270. struct vmw_screen_target_display_unit *stdu)
  271. {
  272. int ret;
  273. struct {
  274. SVGA3dCmdHeader header;
  275. SVGA3dCmdDestroyGBScreenTarget body;
  276. } *cmd;
  277. /* Nothing to do if not successfully defined */
  278. if (unlikely(!stdu->defined))
  279. return 0;
  280. cmd = VMW_CMD_RESERVE(dev_priv, sizeof(*cmd));
  281. if (unlikely(cmd == NULL))
  282. return -ENOMEM;
  283. cmd->header.id = SVGA_3D_CMD_DESTROY_GB_SCREENTARGET;
  284. cmd->header.size = sizeof(cmd->body);
  285. cmd->body.stid = stdu->base.unit;
  286. vmw_cmd_commit(dev_priv, sizeof(*cmd));
  287. /* Force sync */
  288. ret = vmw_fallback_wait(dev_priv, false, true, 0, false, 3*HZ);
  289. if (unlikely(ret != 0))
  290. DRM_ERROR("Failed to sync with HW");
  291. stdu->defined = false;
  292. stdu->display_width = 0;
  293. stdu->display_height = 0;
  294. return ret;
  295. }
  296. /**
  297. * vmw_stdu_crtc_mode_set_nofb - Updates screen target size
  298. *
  299. * @crtc: CRTC associated with the screen target
  300. *
  301. * This function defines/destroys a screen target
  302. *
  303. */
  304. static void vmw_stdu_crtc_mode_set_nofb(struct drm_crtc *crtc)
  305. {
  306. struct vmw_private *dev_priv;
  307. struct vmw_screen_target_display_unit *stdu;
  308. struct drm_connector_state *conn_state;
  309. struct vmw_connector_state *vmw_conn_state;
  310. int x, y, ret;
  311. stdu = vmw_crtc_to_stdu(crtc);
  312. dev_priv = vmw_priv(crtc->dev);
  313. conn_state = stdu->base.connector.state;
  314. vmw_conn_state = vmw_connector_state_to_vcs(conn_state);
  315. if (stdu->defined) {
  316. ret = vmw_stdu_bind_st(dev_priv, stdu, NULL);
  317. if (ret)
  318. DRM_ERROR("Failed to blank CRTC\n");
  319. (void) vmw_stdu_update_st(dev_priv, stdu);
  320. ret = vmw_stdu_destroy_st(dev_priv, stdu);
  321. if (ret)
  322. DRM_ERROR("Failed to destroy Screen Target\n");
  323. stdu->content_fb_type = SAME_AS_DISPLAY;
  324. }
  325. if (!crtc->state->enable)
  326. return;
  327. x = vmw_conn_state->gui_x;
  328. y = vmw_conn_state->gui_y;
  329. vmw_svga_enable(dev_priv);
  330. ret = vmw_stdu_define_st(dev_priv, stdu, &crtc->mode, x, y);
  331. if (ret)
  332. DRM_ERROR("Failed to define Screen Target of size %dx%d\n",
  333. crtc->x, crtc->y);
  334. }
  335. static void vmw_stdu_crtc_helper_prepare(struct drm_crtc *crtc)
  336. {
  337. }
  338. static void vmw_stdu_crtc_atomic_enable(struct drm_crtc *crtc,
  339. struct drm_atomic_state *state)
  340. {
  341. }
  342. static void vmw_stdu_crtc_atomic_disable(struct drm_crtc *crtc,
  343. struct drm_atomic_state *state)
  344. {
  345. struct vmw_private *dev_priv;
  346. struct vmw_screen_target_display_unit *stdu;
  347. int ret;
  348. if (!crtc) {
  349. DRM_ERROR("CRTC is NULL\n");
  350. return;
  351. }
  352. stdu = vmw_crtc_to_stdu(crtc);
  353. dev_priv = vmw_priv(crtc->dev);
  354. if (stdu->defined) {
  355. ret = vmw_stdu_bind_st(dev_priv, stdu, NULL);
  356. if (ret)
  357. DRM_ERROR("Failed to blank CRTC\n");
  358. (void) vmw_stdu_update_st(dev_priv, stdu);
  359. ret = vmw_stdu_destroy_st(dev_priv, stdu);
  360. if (ret)
  361. DRM_ERROR("Failed to destroy Screen Target\n");
  362. stdu->content_fb_type = SAME_AS_DISPLAY;
  363. }
  364. }
  365. /**
  366. * vmw_stdu_bo_clip - Callback to encode a suface DMA command cliprect
  367. *
  368. * @dirty: The closure structure.
  369. *
  370. * Encodes a surface DMA command cliprect and updates the bounding box
  371. * for the DMA.
  372. */
  373. static void vmw_stdu_bo_clip(struct vmw_kms_dirty *dirty)
  374. {
  375. struct vmw_stdu_dirty *ddirty =
  376. container_of(dirty, struct vmw_stdu_dirty, base);
  377. struct vmw_stdu_dma *cmd = dirty->cmd;
  378. struct SVGA3dCopyBox *blit = (struct SVGA3dCopyBox *) &cmd[1];
  379. blit += dirty->num_hits;
  380. blit->srcx = dirty->fb_x;
  381. blit->srcy = dirty->fb_y;
  382. blit->x = dirty->unit_x1;
  383. blit->y = dirty->unit_y1;
  384. blit->d = 1;
  385. blit->w = dirty->unit_x2 - dirty->unit_x1;
  386. blit->h = dirty->unit_y2 - dirty->unit_y1;
  387. dirty->num_hits++;
  388. if (ddirty->transfer != SVGA3D_WRITE_HOST_VRAM)
  389. return;
  390. /* Destination bounding box */
  391. ddirty->left = min_t(s32, ddirty->left, dirty->unit_x1);
  392. ddirty->top = min_t(s32, ddirty->top, dirty->unit_y1);
  393. ddirty->right = max_t(s32, ddirty->right, dirty->unit_x2);
  394. ddirty->bottom = max_t(s32, ddirty->bottom, dirty->unit_y2);
  395. }
  396. /**
  397. * vmw_stdu_bo_fifo_commit - Callback to fill in and submit a DMA command.
  398. *
  399. * @dirty: The closure structure.
  400. *
  401. * Fills in the missing fields in a DMA command, and optionally encodes
  402. * a screen target update command, depending on transfer direction.
  403. */
  404. static void vmw_stdu_bo_fifo_commit(struct vmw_kms_dirty *dirty)
  405. {
  406. struct vmw_stdu_dirty *ddirty =
  407. container_of(dirty, struct vmw_stdu_dirty, base);
  408. struct vmw_screen_target_display_unit *stdu =
  409. container_of(dirty->unit, typeof(*stdu), base);
  410. struct vmw_stdu_dma *cmd = dirty->cmd;
  411. struct SVGA3dCopyBox *blit = (struct SVGA3dCopyBox *) &cmd[1];
  412. SVGA3dCmdSurfaceDMASuffix *suffix =
  413. (SVGA3dCmdSurfaceDMASuffix *) &blit[dirty->num_hits];
  414. size_t blit_size = sizeof(*blit) * dirty->num_hits + sizeof(*suffix);
  415. if (!dirty->num_hits) {
  416. vmw_cmd_commit(dirty->dev_priv, 0);
  417. return;
  418. }
  419. cmd->header.id = SVGA_3D_CMD_SURFACE_DMA;
  420. cmd->header.size = sizeof(cmd->body) + blit_size;
  421. vmw_bo_get_guest_ptr(&ddirty->buf->base, &cmd->body.guest.ptr);
  422. cmd->body.guest.pitch = ddirty->pitch;
  423. cmd->body.host.sid = stdu->display_srf->res.id;
  424. cmd->body.host.face = 0;
  425. cmd->body.host.mipmap = 0;
  426. cmd->body.transfer = ddirty->transfer;
  427. suffix->suffixSize = sizeof(*suffix);
  428. suffix->maximumOffset = ddirty->buf->base.base.size;
  429. if (ddirty->transfer == SVGA3D_WRITE_HOST_VRAM) {
  430. blit_size += sizeof(struct vmw_stdu_update);
  431. vmw_stdu_populate_update(&suffix[1], stdu->base.unit,
  432. ddirty->left, ddirty->right,
  433. ddirty->top, ddirty->bottom);
  434. }
  435. vmw_cmd_commit(dirty->dev_priv, sizeof(*cmd) + blit_size);
  436. stdu->display_srf->res.res_dirty = true;
  437. ddirty->left = ddirty->top = S32_MAX;
  438. ddirty->right = ddirty->bottom = S32_MIN;
  439. }
  440. /**
  441. * vmw_stdu_bo_cpu_clip - Callback to encode a CPU blit
  442. *
  443. * @dirty: The closure structure.
  444. *
  445. * This function calculates the bounding box for all the incoming clips.
  446. */
  447. static void vmw_stdu_bo_cpu_clip(struct vmw_kms_dirty *dirty)
  448. {
  449. struct vmw_stdu_dirty *ddirty =
  450. container_of(dirty, struct vmw_stdu_dirty, base);
  451. dirty->num_hits = 1;
  452. /* Calculate destination bounding box */
  453. ddirty->left = min_t(s32, ddirty->left, dirty->unit_x1);
  454. ddirty->top = min_t(s32, ddirty->top, dirty->unit_y1);
  455. ddirty->right = max_t(s32, ddirty->right, dirty->unit_x2);
  456. ddirty->bottom = max_t(s32, ddirty->bottom, dirty->unit_y2);
  457. /*
  458. * Calculate content bounding box. We only need the top-left
  459. * coordinate because width and height will be the same as the
  460. * destination bounding box above
  461. */
  462. ddirty->fb_left = min_t(s32, ddirty->fb_left, dirty->fb_x);
  463. ddirty->fb_top = min_t(s32, ddirty->fb_top, dirty->fb_y);
  464. }
  465. /**
  466. * vmw_stdu_bo_cpu_commit - Callback to do a CPU blit from buffer object
  467. *
  468. * @dirty: The closure structure.
  469. *
  470. * For the special case when we cannot create a proxy surface in a
  471. * 2D VM, we have to do a CPU blit ourselves.
  472. */
  473. static void vmw_stdu_bo_cpu_commit(struct vmw_kms_dirty *dirty)
  474. {
  475. struct vmw_stdu_dirty *ddirty =
  476. container_of(dirty, struct vmw_stdu_dirty, base);
  477. struct vmw_screen_target_display_unit *stdu =
  478. container_of(dirty->unit, typeof(*stdu), base);
  479. s32 width, height;
  480. s32 src_pitch, dst_pitch;
  481. struct ttm_buffer_object *src_bo, *dst_bo;
  482. u32 src_offset, dst_offset;
  483. struct vmw_diff_cpy diff = VMW_CPU_BLIT_DIFF_INITIALIZER(stdu->cpp);
  484. if (!dirty->num_hits)
  485. return;
  486. width = ddirty->right - ddirty->left;
  487. height = ddirty->bottom - ddirty->top;
  488. if (width == 0 || height == 0)
  489. return;
  490. /* Assume we are blitting from Guest (bo) to Host (display_srf) */
  491. dst_pitch = stdu->display_srf->metadata.base_size.width * stdu->cpp;
  492. dst_bo = &stdu->display_srf->res.backup->base;
  493. dst_offset = ddirty->top * dst_pitch + ddirty->left * stdu->cpp;
  494. src_pitch = ddirty->pitch;
  495. src_bo = &ddirty->buf->base;
  496. src_offset = ddirty->fb_top * src_pitch + ddirty->fb_left * stdu->cpp;
  497. /* Swap src and dst if the assumption was wrong. */
  498. if (ddirty->transfer != SVGA3D_WRITE_HOST_VRAM) {
  499. swap(dst_pitch, src_pitch);
  500. swap(dst_bo, src_bo);
  501. swap(src_offset, dst_offset);
  502. }
  503. (void) vmw_bo_cpu_blit(dst_bo, dst_offset, dst_pitch,
  504. src_bo, src_offset, src_pitch,
  505. width * stdu->cpp, height, &diff);
  506. if (ddirty->transfer == SVGA3D_WRITE_HOST_VRAM &&
  507. drm_rect_visible(&diff.rect)) {
  508. struct vmw_private *dev_priv;
  509. struct vmw_stdu_update *cmd;
  510. struct drm_clip_rect region;
  511. int ret;
  512. /* We are updating the actual surface, not a proxy */
  513. region.x1 = diff.rect.x1;
  514. region.x2 = diff.rect.x2;
  515. region.y1 = diff.rect.y1;
  516. region.y2 = diff.rect.y2;
  517. ret = vmw_kms_update_proxy(&stdu->display_srf->res, &region,
  518. 1, 1);
  519. if (ret)
  520. goto out_cleanup;
  521. dev_priv = vmw_priv(stdu->base.crtc.dev);
  522. cmd = VMW_CMD_RESERVE(dev_priv, sizeof(*cmd));
  523. if (!cmd)
  524. goto out_cleanup;
  525. vmw_stdu_populate_update(cmd, stdu->base.unit,
  526. region.x1, region.x2,
  527. region.y1, region.y2);
  528. vmw_cmd_commit(dev_priv, sizeof(*cmd));
  529. }
  530. out_cleanup:
  531. ddirty->left = ddirty->top = ddirty->fb_left = ddirty->fb_top = S32_MAX;
  532. ddirty->right = ddirty->bottom = S32_MIN;
  533. }
  534. /**
  535. * vmw_kms_stdu_dma - Perform a DMA transfer between a buffer-object backed
  536. * framebuffer and the screen target system.
  537. *
  538. * @dev_priv: Pointer to the device private structure.
  539. * @file_priv: Pointer to a struct drm-file identifying the caller. May be
  540. * set to NULL, but then @user_fence_rep must also be set to NULL.
  541. * @vfb: Pointer to the buffer-object backed framebuffer.
  542. * @user_fence_rep: User-space provided structure for fence information.
  543. * @clips: Array of clip rects. Either @clips or @vclips must be NULL.
  544. * @vclips: Alternate array of clip rects. Either @clips or @vclips must
  545. * be NULL.
  546. * @num_clips: Number of clip rects in @clips or @vclips.
  547. * @increment: Increment to use when looping over @clips or @vclips.
  548. * @to_surface: Whether to DMA to the screen target system as opposed to
  549. * from the screen target system.
  550. * @interruptible: Whether to perform waits interruptible if possible.
  551. * @crtc: If crtc is passed, perform stdu dma on that crtc only.
  552. *
  553. * If DMA-ing till the screen target system, the function will also notify
  554. * the screen target system that a bounding box of the cliprects has been
  555. * updated.
  556. * Returns 0 on success, negative error code on failure. -ERESTARTSYS if
  557. * interrupted.
  558. */
  559. int vmw_kms_stdu_dma(struct vmw_private *dev_priv,
  560. struct drm_file *file_priv,
  561. struct vmw_framebuffer *vfb,
  562. struct drm_vmw_fence_rep __user *user_fence_rep,
  563. struct drm_clip_rect *clips,
  564. struct drm_vmw_rect *vclips,
  565. uint32_t num_clips,
  566. int increment,
  567. bool to_surface,
  568. bool interruptible,
  569. struct drm_crtc *crtc)
  570. {
  571. struct vmw_buffer_object *buf =
  572. container_of(vfb, struct vmw_framebuffer_bo, base)->buffer;
  573. struct vmw_stdu_dirty ddirty;
  574. int ret;
  575. bool cpu_blit = vmw_stdu_use_cpu_blit(dev_priv);
  576. DECLARE_VAL_CONTEXT(val_ctx, NULL, 0);
  577. /*
  578. * VMs without 3D support don't have the surface DMA command and
  579. * we'll be using a CPU blit, and the framebuffer should be moved out
  580. * of VRAM.
  581. */
  582. ret = vmw_validation_add_bo(&val_ctx, buf, false, cpu_blit);
  583. if (ret)
  584. return ret;
  585. ret = vmw_validation_prepare(&val_ctx, NULL, interruptible);
  586. if (ret)
  587. goto out_unref;
  588. ddirty.transfer = (to_surface) ? SVGA3D_WRITE_HOST_VRAM :
  589. SVGA3D_READ_HOST_VRAM;
  590. ddirty.left = ddirty.top = S32_MAX;
  591. ddirty.right = ddirty.bottom = S32_MIN;
  592. ddirty.fb_left = ddirty.fb_top = S32_MAX;
  593. ddirty.pitch = vfb->base.pitches[0];
  594. ddirty.buf = buf;
  595. ddirty.base.fifo_commit = vmw_stdu_bo_fifo_commit;
  596. ddirty.base.clip = vmw_stdu_bo_clip;
  597. ddirty.base.fifo_reserve_size = sizeof(struct vmw_stdu_dma) +
  598. num_clips * sizeof(SVGA3dCopyBox) +
  599. sizeof(SVGA3dCmdSurfaceDMASuffix);
  600. if (to_surface)
  601. ddirty.base.fifo_reserve_size += sizeof(struct vmw_stdu_update);
  602. if (cpu_blit) {
  603. ddirty.base.fifo_commit = vmw_stdu_bo_cpu_commit;
  604. ddirty.base.clip = vmw_stdu_bo_cpu_clip;
  605. ddirty.base.fifo_reserve_size = 0;
  606. }
  607. ddirty.base.crtc = crtc;
  608. ret = vmw_kms_helper_dirty(dev_priv, vfb, clips, vclips,
  609. 0, 0, num_clips, increment, &ddirty.base);
  610. vmw_kms_helper_validation_finish(dev_priv, file_priv, &val_ctx, NULL,
  611. user_fence_rep);
  612. return ret;
  613. out_unref:
  614. vmw_validation_unref_lists(&val_ctx);
  615. return ret;
  616. }
  617. /**
  618. * vmw_kms_stdu_surface_clip - Callback to encode a surface copy command cliprect
  619. *
  620. * @dirty: The closure structure.
  621. *
  622. * Encodes a surface copy command cliprect and updates the bounding box
  623. * for the copy.
  624. */
  625. static void vmw_kms_stdu_surface_clip(struct vmw_kms_dirty *dirty)
  626. {
  627. struct vmw_stdu_dirty *sdirty =
  628. container_of(dirty, struct vmw_stdu_dirty, base);
  629. struct vmw_stdu_surface_copy *cmd = dirty->cmd;
  630. struct vmw_screen_target_display_unit *stdu =
  631. container_of(dirty->unit, typeof(*stdu), base);
  632. if (sdirty->sid != stdu->display_srf->res.id) {
  633. struct SVGA3dCopyBox *blit = (struct SVGA3dCopyBox *) &cmd[1];
  634. blit += dirty->num_hits;
  635. blit->srcx = dirty->fb_x;
  636. blit->srcy = dirty->fb_y;
  637. blit->x = dirty->unit_x1;
  638. blit->y = dirty->unit_y1;
  639. blit->d = 1;
  640. blit->w = dirty->unit_x2 - dirty->unit_x1;
  641. blit->h = dirty->unit_y2 - dirty->unit_y1;
  642. }
  643. dirty->num_hits++;
  644. /* Destination bounding box */
  645. sdirty->left = min_t(s32, sdirty->left, dirty->unit_x1);
  646. sdirty->top = min_t(s32, sdirty->top, dirty->unit_y1);
  647. sdirty->right = max_t(s32, sdirty->right, dirty->unit_x2);
  648. sdirty->bottom = max_t(s32, sdirty->bottom, dirty->unit_y2);
  649. }
  650. /**
  651. * vmw_kms_stdu_surface_fifo_commit - Callback to fill in and submit a surface
  652. * copy command.
  653. *
  654. * @dirty: The closure structure.
  655. *
  656. * Fills in the missing fields in a surface copy command, and encodes a screen
  657. * target update command.
  658. */
  659. static void vmw_kms_stdu_surface_fifo_commit(struct vmw_kms_dirty *dirty)
  660. {
  661. struct vmw_stdu_dirty *sdirty =
  662. container_of(dirty, struct vmw_stdu_dirty, base);
  663. struct vmw_screen_target_display_unit *stdu =
  664. container_of(dirty->unit, typeof(*stdu), base);
  665. struct vmw_stdu_surface_copy *cmd = dirty->cmd;
  666. struct vmw_stdu_update *update;
  667. size_t blit_size = sizeof(SVGA3dCopyBox) * dirty->num_hits;
  668. size_t commit_size;
  669. if (!dirty->num_hits) {
  670. vmw_cmd_commit(dirty->dev_priv, 0);
  671. return;
  672. }
  673. if (sdirty->sid != stdu->display_srf->res.id) {
  674. struct SVGA3dCopyBox *blit = (struct SVGA3dCopyBox *) &cmd[1];
  675. cmd->header.id = SVGA_3D_CMD_SURFACE_COPY;
  676. cmd->header.size = sizeof(cmd->body) + blit_size;
  677. cmd->body.src.sid = sdirty->sid;
  678. cmd->body.dest.sid = stdu->display_srf->res.id;
  679. update = (struct vmw_stdu_update *) &blit[dirty->num_hits];
  680. commit_size = sizeof(*cmd) + blit_size + sizeof(*update);
  681. stdu->display_srf->res.res_dirty = true;
  682. } else {
  683. update = dirty->cmd;
  684. commit_size = sizeof(*update);
  685. }
  686. vmw_stdu_populate_update(update, stdu->base.unit, sdirty->left,
  687. sdirty->right, sdirty->top, sdirty->bottom);
  688. vmw_cmd_commit(dirty->dev_priv, commit_size);
  689. sdirty->left = sdirty->top = S32_MAX;
  690. sdirty->right = sdirty->bottom = S32_MIN;
  691. }
  692. /**
  693. * vmw_kms_stdu_surface_dirty - Dirty part of a surface backed framebuffer
  694. *
  695. * @dev_priv: Pointer to the device private structure.
  696. * @framebuffer: Pointer to the surface-buffer backed framebuffer.
  697. * @clips: Array of clip rects. Either @clips or @vclips must be NULL.
  698. * @vclips: Alternate array of clip rects. Either @clips or @vclips must
  699. * be NULL.
  700. * @srf: Pointer to surface to blit from. If NULL, the surface attached
  701. * to @framebuffer will be used.
  702. * @dest_x: X coordinate offset to align @srf with framebuffer coordinates.
  703. * @dest_y: Y coordinate offset to align @srf with framebuffer coordinates.
  704. * @num_clips: Number of clip rects in @clips.
  705. * @inc: Increment to use when looping over @clips.
  706. * @out_fence: If non-NULL, will return a ref-counted pointer to a
  707. * struct vmw_fence_obj. The returned fence pointer may be NULL in which
  708. * case the device has already synchronized.
  709. * @crtc: If crtc is passed, perform surface dirty on that crtc only.
  710. *
  711. * Returns 0 on success, negative error code on failure. -ERESTARTSYS if
  712. * interrupted.
  713. */
  714. int vmw_kms_stdu_surface_dirty(struct vmw_private *dev_priv,
  715. struct vmw_framebuffer *framebuffer,
  716. struct drm_clip_rect *clips,
  717. struct drm_vmw_rect *vclips,
  718. struct vmw_resource *srf,
  719. s32 dest_x,
  720. s32 dest_y,
  721. unsigned num_clips, int inc,
  722. struct vmw_fence_obj **out_fence,
  723. struct drm_crtc *crtc)
  724. {
  725. struct vmw_framebuffer_surface *vfbs =
  726. container_of(framebuffer, typeof(*vfbs), base);
  727. struct vmw_stdu_dirty sdirty;
  728. DECLARE_VAL_CONTEXT(val_ctx, NULL, 0);
  729. int ret;
  730. if (!srf)
  731. srf = &vfbs->surface->res;
  732. ret = vmw_validation_add_resource(&val_ctx, srf, 0, VMW_RES_DIRTY_NONE,
  733. NULL, NULL);
  734. if (ret)
  735. return ret;
  736. ret = vmw_validation_prepare(&val_ctx, &dev_priv->cmdbuf_mutex, true);
  737. if (ret)
  738. goto out_unref;
  739. if (vfbs->is_bo_proxy) {
  740. ret = vmw_kms_update_proxy(srf, clips, num_clips, inc);
  741. if (ret)
  742. goto out_finish;
  743. }
  744. sdirty.base.fifo_commit = vmw_kms_stdu_surface_fifo_commit;
  745. sdirty.base.clip = vmw_kms_stdu_surface_clip;
  746. sdirty.base.fifo_reserve_size = sizeof(struct vmw_stdu_surface_copy) +
  747. sizeof(SVGA3dCopyBox) * num_clips +
  748. sizeof(struct vmw_stdu_update);
  749. sdirty.base.crtc = crtc;
  750. sdirty.sid = srf->id;
  751. sdirty.left = sdirty.top = S32_MAX;
  752. sdirty.right = sdirty.bottom = S32_MIN;
  753. ret = vmw_kms_helper_dirty(dev_priv, framebuffer, clips, vclips,
  754. dest_x, dest_y, num_clips, inc,
  755. &sdirty.base);
  756. out_finish:
  757. vmw_kms_helper_validation_finish(dev_priv, NULL, &val_ctx, out_fence,
  758. NULL);
  759. return ret;
  760. out_unref:
  761. vmw_validation_unref_lists(&val_ctx);
  762. return ret;
  763. }
  764. /*
  765. * Screen Target CRTC dispatch table
  766. */
  767. static const struct drm_crtc_funcs vmw_stdu_crtc_funcs = {
  768. .gamma_set = vmw_du_crtc_gamma_set,
  769. .destroy = vmw_stdu_crtc_destroy,
  770. .reset = vmw_du_crtc_reset,
  771. .atomic_duplicate_state = vmw_du_crtc_duplicate_state,
  772. .atomic_destroy_state = vmw_du_crtc_destroy_state,
  773. .set_config = drm_atomic_helper_set_config,
  774. .page_flip = drm_atomic_helper_page_flip,
  775. };
  776. /******************************************************************************
  777. * Screen Target Display Unit Encoder Functions
  778. *****************************************************************************/
  779. /**
  780. * vmw_stdu_encoder_destroy - cleans up the STDU
  781. *
  782. * @encoder: used the get the containing STDU
  783. *
  784. * vmwgfx cleans up crtc/encoder/connector all at the same time so technically
  785. * this can be a no-op. Nevertheless, it doesn't hurt of have this in case
  786. * the common KMS code changes and somehow vmw_stdu_crtc_destroy() doesn't
  787. * get called.
  788. */
  789. static void vmw_stdu_encoder_destroy(struct drm_encoder *encoder)
  790. {
  791. vmw_stdu_destroy(vmw_encoder_to_stdu(encoder));
  792. }
  793. static const struct drm_encoder_funcs vmw_stdu_encoder_funcs = {
  794. .destroy = vmw_stdu_encoder_destroy,
  795. };
  796. /******************************************************************************
  797. * Screen Target Display Unit Connector Functions
  798. *****************************************************************************/
  799. /**
  800. * vmw_stdu_connector_destroy - cleans up the STDU
  801. *
  802. * @connector: used to get the containing STDU
  803. *
  804. * vmwgfx cleans up crtc/encoder/connector all at the same time so technically
  805. * this can be a no-op. Nevertheless, it doesn't hurt of have this in case
  806. * the common KMS code changes and somehow vmw_stdu_crtc_destroy() doesn't
  807. * get called.
  808. */
  809. static void vmw_stdu_connector_destroy(struct drm_connector *connector)
  810. {
  811. vmw_stdu_destroy(vmw_connector_to_stdu(connector));
  812. }
  813. static const struct drm_connector_funcs vmw_stdu_connector_funcs = {
  814. .dpms = vmw_du_connector_dpms,
  815. .detect = vmw_du_connector_detect,
  816. .fill_modes = vmw_du_connector_fill_modes,
  817. .destroy = vmw_stdu_connector_destroy,
  818. .reset = vmw_du_connector_reset,
  819. .atomic_duplicate_state = vmw_du_connector_duplicate_state,
  820. .atomic_destroy_state = vmw_du_connector_destroy_state,
  821. };
  822. static const struct
  823. drm_connector_helper_funcs vmw_stdu_connector_helper_funcs = {
  824. };
  825. /******************************************************************************
  826. * Screen Target Display Plane Functions
  827. *****************************************************************************/
  828. /**
  829. * vmw_stdu_primary_plane_cleanup_fb - Unpins the display surface
  830. *
  831. * @plane: display plane
  832. * @old_state: Contains the FB to clean up
  833. *
  834. * Unpins the display surface
  835. *
  836. * Returns 0 on success
  837. */
  838. static void
  839. vmw_stdu_primary_plane_cleanup_fb(struct drm_plane *plane,
  840. struct drm_plane_state *old_state)
  841. {
  842. struct vmw_plane_state *vps = vmw_plane_state_to_vps(old_state);
  843. if (vps->surf)
  844. WARN_ON(!vps->pinned);
  845. vmw_du_plane_cleanup_fb(plane, old_state);
  846. vps->content_fb_type = SAME_AS_DISPLAY;
  847. vps->cpp = 0;
  848. }
  849. /**
  850. * vmw_stdu_primary_plane_prepare_fb - Readies the display surface
  851. *
  852. * @plane: display plane
  853. * @new_state: info on the new plane state, including the FB
  854. *
  855. * This function allocates a new display surface if the content is
  856. * backed by a buffer object. The display surface is pinned here, and it'll
  857. * be unpinned in .cleanup_fb()
  858. *
  859. * Returns 0 on success
  860. */
  861. static int
  862. vmw_stdu_primary_plane_prepare_fb(struct drm_plane *plane,
  863. struct drm_plane_state *new_state)
  864. {
  865. struct vmw_private *dev_priv = vmw_priv(plane->dev);
  866. struct drm_framebuffer *new_fb = new_state->fb;
  867. struct vmw_framebuffer *vfb;
  868. struct vmw_plane_state *vps = vmw_plane_state_to_vps(new_state);
  869. enum stdu_content_type new_content_type;
  870. struct vmw_framebuffer_surface *new_vfbs;
  871. uint32_t hdisplay = new_state->crtc_w, vdisplay = new_state->crtc_h;
  872. int ret;
  873. /* No FB to prepare */
  874. if (!new_fb) {
  875. if (vps->surf) {
  876. WARN_ON(vps->pinned != 0);
  877. vmw_surface_unreference(&vps->surf);
  878. }
  879. return 0;
  880. }
  881. vfb = vmw_framebuffer_to_vfb(new_fb);
  882. new_vfbs = (vfb->bo) ? NULL : vmw_framebuffer_to_vfbs(new_fb);
  883. if (new_vfbs &&
  884. new_vfbs->surface->metadata.base_size.width == hdisplay &&
  885. new_vfbs->surface->metadata.base_size.height == vdisplay)
  886. new_content_type = SAME_AS_DISPLAY;
  887. else if (vfb->bo)
  888. new_content_type = SEPARATE_BO;
  889. else
  890. new_content_type = SEPARATE_SURFACE;
  891. if (new_content_type != SAME_AS_DISPLAY) {
  892. struct vmw_surface_metadata metadata = {0};
  893. /*
  894. * If content buffer is a buffer object, then we have to
  895. * construct surface info
  896. */
  897. if (new_content_type == SEPARATE_BO) {
  898. switch (new_fb->format->cpp[0]*8) {
  899. case 32:
  900. metadata.format = SVGA3D_X8R8G8B8;
  901. break;
  902. case 16:
  903. metadata.format = SVGA3D_R5G6B5;
  904. break;
  905. case 8:
  906. metadata.format = SVGA3D_P8;
  907. break;
  908. default:
  909. DRM_ERROR("Invalid format\n");
  910. return -EINVAL;
  911. }
  912. metadata.mip_levels[0] = 1;
  913. metadata.num_sizes = 1;
  914. metadata.scanout = true;
  915. } else {
  916. metadata = new_vfbs->surface->metadata;
  917. }
  918. metadata.base_size.width = hdisplay;
  919. metadata.base_size.height = vdisplay;
  920. metadata.base_size.depth = 1;
  921. if (vps->surf) {
  922. struct drm_vmw_size cur_base_size =
  923. vps->surf->metadata.base_size;
  924. if (cur_base_size.width != metadata.base_size.width ||
  925. cur_base_size.height != metadata.base_size.height ||
  926. vps->surf->metadata.format != metadata.format) {
  927. WARN_ON(vps->pinned != 0);
  928. vmw_surface_unreference(&vps->surf);
  929. }
  930. }
  931. if (!vps->surf) {
  932. ret = vmw_gb_surface_define(dev_priv, &metadata,
  933. &vps->surf);
  934. if (ret != 0) {
  935. DRM_ERROR("Couldn't allocate STDU surface.\n");
  936. return ret;
  937. }
  938. }
  939. } else {
  940. /*
  941. * prepare_fb and clean_fb should only take care of pinning
  942. * and unpinning. References are tracked by state objects.
  943. * The only time we add a reference in prepare_fb is if the
  944. * state object doesn't have a reference to begin with
  945. */
  946. if (vps->surf) {
  947. WARN_ON(vps->pinned != 0);
  948. vmw_surface_unreference(&vps->surf);
  949. }
  950. vps->surf = vmw_surface_reference(new_vfbs->surface);
  951. }
  952. if (vps->surf) {
  953. /* Pin new surface before flipping */
  954. ret = vmw_resource_pin(&vps->surf->res, false);
  955. if (ret)
  956. goto out_srf_unref;
  957. vps->pinned++;
  958. }
  959. vps->content_fb_type = new_content_type;
  960. /*
  961. * This should only happen if the buffer object is too large to create a
  962. * proxy surface for.
  963. * If we are a 2D VM with a buffer object then we have to use CPU blit
  964. * so cache these mappings
  965. */
  966. if (vps->content_fb_type == SEPARATE_BO &&
  967. vmw_stdu_use_cpu_blit(dev_priv))
  968. vps->cpp = new_fb->pitches[0] / new_fb->width;
  969. return 0;
  970. out_srf_unref:
  971. vmw_surface_unreference(&vps->surf);
  972. return ret;
  973. }
  974. static uint32_t vmw_stdu_bo_fifo_size(struct vmw_du_update_plane *update,
  975. uint32_t num_hits)
  976. {
  977. return sizeof(struct vmw_stdu_dma) + sizeof(SVGA3dCopyBox) * num_hits +
  978. sizeof(SVGA3dCmdSurfaceDMASuffix) +
  979. sizeof(struct vmw_stdu_update);
  980. }
  981. static uint32_t vmw_stdu_bo_fifo_size_cpu(struct vmw_du_update_plane *update,
  982. uint32_t num_hits)
  983. {
  984. return sizeof(struct vmw_stdu_update_gb_image) +
  985. sizeof(struct vmw_stdu_update);
  986. }
  987. static uint32_t vmw_stdu_bo_populate_dma(struct vmw_du_update_plane *update,
  988. void *cmd, uint32_t num_hits)
  989. {
  990. struct vmw_screen_target_display_unit *stdu;
  991. struct vmw_framebuffer_bo *vfbbo;
  992. struct vmw_stdu_dma *cmd_dma = cmd;
  993. stdu = container_of(update->du, typeof(*stdu), base);
  994. vfbbo = container_of(update->vfb, typeof(*vfbbo), base);
  995. cmd_dma->header.id = SVGA_3D_CMD_SURFACE_DMA;
  996. cmd_dma->header.size = sizeof(cmd_dma->body) +
  997. sizeof(struct SVGA3dCopyBox) * num_hits +
  998. sizeof(SVGA3dCmdSurfaceDMASuffix);
  999. vmw_bo_get_guest_ptr(&vfbbo->buffer->base, &cmd_dma->body.guest.ptr);
  1000. cmd_dma->body.guest.pitch = update->vfb->base.pitches[0];
  1001. cmd_dma->body.host.sid = stdu->display_srf->res.id;
  1002. cmd_dma->body.host.face = 0;
  1003. cmd_dma->body.host.mipmap = 0;
  1004. cmd_dma->body.transfer = SVGA3D_WRITE_HOST_VRAM;
  1005. return sizeof(*cmd_dma);
  1006. }
  1007. static uint32_t vmw_stdu_bo_populate_clip(struct vmw_du_update_plane *update,
  1008. void *cmd, struct drm_rect *clip,
  1009. uint32_t fb_x, uint32_t fb_y)
  1010. {
  1011. struct SVGA3dCopyBox *box = cmd;
  1012. box->srcx = fb_x;
  1013. box->srcy = fb_y;
  1014. box->srcz = 0;
  1015. box->x = clip->x1;
  1016. box->y = clip->y1;
  1017. box->z = 0;
  1018. box->w = drm_rect_width(clip);
  1019. box->h = drm_rect_height(clip);
  1020. box->d = 1;
  1021. return sizeof(*box);
  1022. }
  1023. static uint32_t vmw_stdu_bo_populate_update(struct vmw_du_update_plane *update,
  1024. void *cmd, struct drm_rect *bb)
  1025. {
  1026. struct vmw_screen_target_display_unit *stdu;
  1027. struct vmw_framebuffer_bo *vfbbo;
  1028. SVGA3dCmdSurfaceDMASuffix *suffix = cmd;
  1029. stdu = container_of(update->du, typeof(*stdu), base);
  1030. vfbbo = container_of(update->vfb, typeof(*vfbbo), base);
  1031. suffix->suffixSize = sizeof(*suffix);
  1032. suffix->maximumOffset = vfbbo->buffer->base.base.size;
  1033. vmw_stdu_populate_update(&suffix[1], stdu->base.unit, bb->x1, bb->x2,
  1034. bb->y1, bb->y2);
  1035. return sizeof(*suffix) + sizeof(struct vmw_stdu_update);
  1036. }
  1037. static uint32_t vmw_stdu_bo_pre_clip_cpu(struct vmw_du_update_plane *update,
  1038. void *cmd, uint32_t num_hits)
  1039. {
  1040. struct vmw_du_update_plane_buffer *bo_update =
  1041. container_of(update, typeof(*bo_update), base);
  1042. bo_update->fb_left = INT_MAX;
  1043. bo_update->fb_top = INT_MAX;
  1044. return 0;
  1045. }
  1046. static uint32_t vmw_stdu_bo_clip_cpu(struct vmw_du_update_plane *update,
  1047. void *cmd, struct drm_rect *clip,
  1048. uint32_t fb_x, uint32_t fb_y)
  1049. {
  1050. struct vmw_du_update_plane_buffer *bo_update =
  1051. container_of(update, typeof(*bo_update), base);
  1052. bo_update->fb_left = min_t(int, bo_update->fb_left, fb_x);
  1053. bo_update->fb_top = min_t(int, bo_update->fb_top, fb_y);
  1054. return 0;
  1055. }
  1056. static uint32_t
  1057. vmw_stdu_bo_populate_update_cpu(struct vmw_du_update_plane *update, void *cmd,
  1058. struct drm_rect *bb)
  1059. {
  1060. struct vmw_du_update_plane_buffer *bo_update;
  1061. struct vmw_screen_target_display_unit *stdu;
  1062. struct vmw_framebuffer_bo *vfbbo;
  1063. struct vmw_diff_cpy diff = VMW_CPU_BLIT_DIFF_INITIALIZER(0);
  1064. struct vmw_stdu_update_gb_image *cmd_img = cmd;
  1065. struct vmw_stdu_update *cmd_update;
  1066. struct ttm_buffer_object *src_bo, *dst_bo;
  1067. u32 src_offset, dst_offset;
  1068. s32 src_pitch, dst_pitch;
  1069. s32 width, height;
  1070. bo_update = container_of(update, typeof(*bo_update), base);
  1071. stdu = container_of(update->du, typeof(*stdu), base);
  1072. vfbbo = container_of(update->vfb, typeof(*vfbbo), base);
  1073. width = bb->x2 - bb->x1;
  1074. height = bb->y2 - bb->y1;
  1075. diff.cpp = stdu->cpp;
  1076. dst_bo = &stdu->display_srf->res.backup->base;
  1077. dst_pitch = stdu->display_srf->metadata.base_size.width * stdu->cpp;
  1078. dst_offset = bb->y1 * dst_pitch + bb->x1 * stdu->cpp;
  1079. src_bo = &vfbbo->buffer->base;
  1080. src_pitch = update->vfb->base.pitches[0];
  1081. src_offset = bo_update->fb_top * src_pitch + bo_update->fb_left *
  1082. stdu->cpp;
  1083. (void) vmw_bo_cpu_blit(dst_bo, dst_offset, dst_pitch, src_bo,
  1084. src_offset, src_pitch, width * stdu->cpp, height,
  1085. &diff);
  1086. if (drm_rect_visible(&diff.rect)) {
  1087. SVGA3dBox *box = &cmd_img->body.box;
  1088. cmd_img->header.id = SVGA_3D_CMD_UPDATE_GB_IMAGE;
  1089. cmd_img->header.size = sizeof(cmd_img->body);
  1090. cmd_img->body.image.sid = stdu->display_srf->res.id;
  1091. cmd_img->body.image.face = 0;
  1092. cmd_img->body.image.mipmap = 0;
  1093. box->x = diff.rect.x1;
  1094. box->y = diff.rect.y1;
  1095. box->z = 0;
  1096. box->w = drm_rect_width(&diff.rect);
  1097. box->h = drm_rect_height(&diff.rect);
  1098. box->d = 1;
  1099. cmd_update = (struct vmw_stdu_update *)&cmd_img[1];
  1100. vmw_stdu_populate_update(cmd_update, stdu->base.unit,
  1101. diff.rect.x1, diff.rect.x2,
  1102. diff.rect.y1, diff.rect.y2);
  1103. return sizeof(*cmd_img) + sizeof(*cmd_update);
  1104. }
  1105. return 0;
  1106. }
  1107. /**
  1108. * vmw_stdu_plane_update_bo - Update display unit for bo backed fb.
  1109. * @dev_priv: device private.
  1110. * @plane: plane state.
  1111. * @old_state: old plane state.
  1112. * @vfb: framebuffer which is blitted to display unit.
  1113. * @out_fence: If non-NULL, will return a ref-counted pointer to vmw_fence_obj.
  1114. * The returned fence pointer may be NULL in which case the device
  1115. * has already synchronized.
  1116. *
  1117. * Return: 0 on success or a negative error code on failure.
  1118. */
  1119. static int vmw_stdu_plane_update_bo(struct vmw_private *dev_priv,
  1120. struct drm_plane *plane,
  1121. struct drm_plane_state *old_state,
  1122. struct vmw_framebuffer *vfb,
  1123. struct vmw_fence_obj **out_fence)
  1124. {
  1125. struct vmw_du_update_plane_buffer bo_update;
  1126. memset(&bo_update, 0, sizeof(struct vmw_du_update_plane_buffer));
  1127. bo_update.base.plane = plane;
  1128. bo_update.base.old_state = old_state;
  1129. bo_update.base.dev_priv = dev_priv;
  1130. bo_update.base.du = vmw_crtc_to_du(plane->state->crtc);
  1131. bo_update.base.vfb = vfb;
  1132. bo_update.base.out_fence = out_fence;
  1133. bo_update.base.mutex = NULL;
  1134. bo_update.base.cpu_blit = vmw_stdu_use_cpu_blit(dev_priv);
  1135. bo_update.base.intr = false;
  1136. /*
  1137. * VM without 3D support don't have surface DMA command and framebuffer
  1138. * should be moved out of VRAM.
  1139. */
  1140. if (bo_update.base.cpu_blit) {
  1141. bo_update.base.calc_fifo_size = vmw_stdu_bo_fifo_size_cpu;
  1142. bo_update.base.pre_clip = vmw_stdu_bo_pre_clip_cpu;
  1143. bo_update.base.clip = vmw_stdu_bo_clip_cpu;
  1144. bo_update.base.post_clip = vmw_stdu_bo_populate_update_cpu;
  1145. } else {
  1146. bo_update.base.calc_fifo_size = vmw_stdu_bo_fifo_size;
  1147. bo_update.base.pre_clip = vmw_stdu_bo_populate_dma;
  1148. bo_update.base.clip = vmw_stdu_bo_populate_clip;
  1149. bo_update.base.post_clip = vmw_stdu_bo_populate_update;
  1150. }
  1151. return vmw_du_helper_plane_update(&bo_update.base);
  1152. }
  1153. static uint32_t
  1154. vmw_stdu_surface_fifo_size_same_display(struct vmw_du_update_plane *update,
  1155. uint32_t num_hits)
  1156. {
  1157. struct vmw_framebuffer_surface *vfbs;
  1158. uint32_t size = 0;
  1159. vfbs = container_of(update->vfb, typeof(*vfbs), base);
  1160. if (vfbs->is_bo_proxy)
  1161. size += sizeof(struct vmw_stdu_update_gb_image) * num_hits;
  1162. size += sizeof(struct vmw_stdu_update);
  1163. return size;
  1164. }
  1165. static uint32_t vmw_stdu_surface_fifo_size(struct vmw_du_update_plane *update,
  1166. uint32_t num_hits)
  1167. {
  1168. struct vmw_framebuffer_surface *vfbs;
  1169. uint32_t size = 0;
  1170. vfbs = container_of(update->vfb, typeof(*vfbs), base);
  1171. if (vfbs->is_bo_proxy)
  1172. size += sizeof(struct vmw_stdu_update_gb_image) * num_hits;
  1173. size += sizeof(struct vmw_stdu_surface_copy) + sizeof(SVGA3dCopyBox) *
  1174. num_hits + sizeof(struct vmw_stdu_update);
  1175. return size;
  1176. }
  1177. static uint32_t
  1178. vmw_stdu_surface_update_proxy(struct vmw_du_update_plane *update, void *cmd)
  1179. {
  1180. struct vmw_framebuffer_surface *vfbs;
  1181. struct drm_plane_state *state = update->plane->state;
  1182. struct drm_plane_state *old_state = update->old_state;
  1183. struct vmw_stdu_update_gb_image *cmd_update = cmd;
  1184. struct drm_atomic_helper_damage_iter iter;
  1185. struct drm_rect clip;
  1186. uint32_t copy_size = 0;
  1187. vfbs = container_of(update->vfb, typeof(*vfbs), base);
  1188. /*
  1189. * proxy surface is special where a buffer object type fb is wrapped
  1190. * in a surface and need an update gb image command to sync with device.
  1191. */
  1192. drm_atomic_helper_damage_iter_init(&iter, old_state, state);
  1193. drm_atomic_for_each_plane_damage(&iter, &clip) {
  1194. SVGA3dBox *box = &cmd_update->body.box;
  1195. cmd_update->header.id = SVGA_3D_CMD_UPDATE_GB_IMAGE;
  1196. cmd_update->header.size = sizeof(cmd_update->body);
  1197. cmd_update->body.image.sid = vfbs->surface->res.id;
  1198. cmd_update->body.image.face = 0;
  1199. cmd_update->body.image.mipmap = 0;
  1200. box->x = clip.x1;
  1201. box->y = clip.y1;
  1202. box->z = 0;
  1203. box->w = drm_rect_width(&clip);
  1204. box->h = drm_rect_height(&clip);
  1205. box->d = 1;
  1206. copy_size += sizeof(*cmd_update);
  1207. cmd_update++;
  1208. }
  1209. return copy_size;
  1210. }
  1211. static uint32_t
  1212. vmw_stdu_surface_populate_copy(struct vmw_du_update_plane *update, void *cmd,
  1213. uint32_t num_hits)
  1214. {
  1215. struct vmw_screen_target_display_unit *stdu;
  1216. struct vmw_framebuffer_surface *vfbs;
  1217. struct vmw_stdu_surface_copy *cmd_copy = cmd;
  1218. stdu = container_of(update->du, typeof(*stdu), base);
  1219. vfbs = container_of(update->vfb, typeof(*vfbs), base);
  1220. cmd_copy->header.id = SVGA_3D_CMD_SURFACE_COPY;
  1221. cmd_copy->header.size = sizeof(cmd_copy->body) + sizeof(SVGA3dCopyBox) *
  1222. num_hits;
  1223. cmd_copy->body.src.sid = vfbs->surface->res.id;
  1224. cmd_copy->body.dest.sid = stdu->display_srf->res.id;
  1225. return sizeof(*cmd_copy);
  1226. }
  1227. static uint32_t
  1228. vmw_stdu_surface_populate_clip(struct vmw_du_update_plane *update, void *cmd,
  1229. struct drm_rect *clip, uint32_t fb_x,
  1230. uint32_t fb_y)
  1231. {
  1232. struct SVGA3dCopyBox *box = cmd;
  1233. box->srcx = fb_x;
  1234. box->srcy = fb_y;
  1235. box->srcz = 0;
  1236. box->x = clip->x1;
  1237. box->y = clip->y1;
  1238. box->z = 0;
  1239. box->w = drm_rect_width(clip);
  1240. box->h = drm_rect_height(clip);
  1241. box->d = 1;
  1242. return sizeof(*box);
  1243. }
  1244. static uint32_t
  1245. vmw_stdu_surface_populate_update(struct vmw_du_update_plane *update, void *cmd,
  1246. struct drm_rect *bb)
  1247. {
  1248. vmw_stdu_populate_update(cmd, update->du->unit, bb->x1, bb->x2, bb->y1,
  1249. bb->y2);
  1250. return sizeof(struct vmw_stdu_update);
  1251. }
  1252. /**
  1253. * vmw_stdu_plane_update_surface - Update display unit for surface backed fb
  1254. * @dev_priv: Device private
  1255. * @plane: Plane state
  1256. * @old_state: Old plane state
  1257. * @vfb: Framebuffer which is blitted to display unit
  1258. * @out_fence: If non-NULL, will return a ref-counted pointer to vmw_fence_obj.
  1259. * The returned fence pointer may be NULL in which case the device
  1260. * has already synchronized.
  1261. *
  1262. * Return: 0 on success or a negative error code on failure.
  1263. */
  1264. static int vmw_stdu_plane_update_surface(struct vmw_private *dev_priv,
  1265. struct drm_plane *plane,
  1266. struct drm_plane_state *old_state,
  1267. struct vmw_framebuffer *vfb,
  1268. struct vmw_fence_obj **out_fence)
  1269. {
  1270. struct vmw_du_update_plane srf_update;
  1271. struct vmw_screen_target_display_unit *stdu;
  1272. struct vmw_framebuffer_surface *vfbs;
  1273. stdu = vmw_crtc_to_stdu(plane->state->crtc);
  1274. vfbs = container_of(vfb, typeof(*vfbs), base);
  1275. memset(&srf_update, 0, sizeof(struct vmw_du_update_plane));
  1276. srf_update.plane = plane;
  1277. srf_update.old_state = old_state;
  1278. srf_update.dev_priv = dev_priv;
  1279. srf_update.du = vmw_crtc_to_du(plane->state->crtc);
  1280. srf_update.vfb = vfb;
  1281. srf_update.out_fence = out_fence;
  1282. srf_update.mutex = &dev_priv->cmdbuf_mutex;
  1283. srf_update.cpu_blit = false;
  1284. srf_update.intr = true;
  1285. if (vfbs->is_bo_proxy)
  1286. srf_update.post_prepare = vmw_stdu_surface_update_proxy;
  1287. if (vfbs->surface->res.id != stdu->display_srf->res.id) {
  1288. srf_update.calc_fifo_size = vmw_stdu_surface_fifo_size;
  1289. srf_update.pre_clip = vmw_stdu_surface_populate_copy;
  1290. srf_update.clip = vmw_stdu_surface_populate_clip;
  1291. } else {
  1292. srf_update.calc_fifo_size =
  1293. vmw_stdu_surface_fifo_size_same_display;
  1294. }
  1295. srf_update.post_clip = vmw_stdu_surface_populate_update;
  1296. return vmw_du_helper_plane_update(&srf_update);
  1297. }
  1298. /**
  1299. * vmw_stdu_primary_plane_atomic_update - formally switches STDU to new plane
  1300. * @plane: display plane
  1301. * @state: Only used to get crtc info
  1302. *
  1303. * Formally update stdu->display_srf to the new plane, and bind the new
  1304. * plane STDU. This function is called during the commit phase when
  1305. * all the preparation have been done and all the configurations have
  1306. * been checked.
  1307. */
  1308. static void
  1309. vmw_stdu_primary_plane_atomic_update(struct drm_plane *plane,
  1310. struct drm_atomic_state *state)
  1311. {
  1312. struct drm_plane_state *old_state = drm_atomic_get_old_plane_state(state, plane);
  1313. struct drm_plane_state *new_state = drm_atomic_get_new_plane_state(state, plane);
  1314. struct vmw_plane_state *vps = vmw_plane_state_to_vps(new_state);
  1315. struct drm_crtc *crtc = new_state->crtc;
  1316. struct vmw_screen_target_display_unit *stdu;
  1317. struct vmw_fence_obj *fence = NULL;
  1318. struct vmw_private *dev_priv;
  1319. int ret;
  1320. /* If case of device error, maintain consistent atomic state */
  1321. if (crtc && new_state->fb) {
  1322. struct vmw_framebuffer *vfb =
  1323. vmw_framebuffer_to_vfb(new_state->fb);
  1324. stdu = vmw_crtc_to_stdu(crtc);
  1325. dev_priv = vmw_priv(crtc->dev);
  1326. stdu->display_srf = vps->surf;
  1327. stdu->content_fb_type = vps->content_fb_type;
  1328. stdu->cpp = vps->cpp;
  1329. ret = vmw_stdu_bind_st(dev_priv, stdu, &stdu->display_srf->res);
  1330. if (ret)
  1331. DRM_ERROR("Failed to bind surface to STDU.\n");
  1332. if (vfb->bo)
  1333. ret = vmw_stdu_plane_update_bo(dev_priv, plane,
  1334. old_state, vfb, &fence);
  1335. else
  1336. ret = vmw_stdu_plane_update_surface(dev_priv, plane,
  1337. old_state, vfb,
  1338. &fence);
  1339. if (ret)
  1340. DRM_ERROR("Failed to update STDU.\n");
  1341. } else {
  1342. crtc = old_state->crtc;
  1343. stdu = vmw_crtc_to_stdu(crtc);
  1344. dev_priv = vmw_priv(crtc->dev);
  1345. /* Blank STDU when fb and crtc are NULL */
  1346. if (!stdu->defined)
  1347. return;
  1348. ret = vmw_stdu_bind_st(dev_priv, stdu, NULL);
  1349. if (ret)
  1350. DRM_ERROR("Failed to blank STDU\n");
  1351. ret = vmw_stdu_update_st(dev_priv, stdu);
  1352. if (ret)
  1353. DRM_ERROR("Failed to update STDU.\n");
  1354. return;
  1355. }
  1356. if (fence)
  1357. vmw_fence_obj_unreference(&fence);
  1358. }
  1359. static const struct drm_plane_funcs vmw_stdu_plane_funcs = {
  1360. .update_plane = drm_atomic_helper_update_plane,
  1361. .disable_plane = drm_atomic_helper_disable_plane,
  1362. .destroy = vmw_du_primary_plane_destroy,
  1363. .reset = vmw_du_plane_reset,
  1364. .atomic_duplicate_state = vmw_du_plane_duplicate_state,
  1365. .atomic_destroy_state = vmw_du_plane_destroy_state,
  1366. };
  1367. static const struct drm_plane_funcs vmw_stdu_cursor_funcs = {
  1368. .update_plane = drm_atomic_helper_update_plane,
  1369. .disable_plane = drm_atomic_helper_disable_plane,
  1370. .destroy = vmw_du_cursor_plane_destroy,
  1371. .reset = vmw_du_plane_reset,
  1372. .atomic_duplicate_state = vmw_du_plane_duplicate_state,
  1373. .atomic_destroy_state = vmw_du_plane_destroy_state,
  1374. };
  1375. /*
  1376. * Atomic Helpers
  1377. */
  1378. static const struct
  1379. drm_plane_helper_funcs vmw_stdu_cursor_plane_helper_funcs = {
  1380. .atomic_check = vmw_du_cursor_plane_atomic_check,
  1381. .atomic_update = vmw_du_cursor_plane_atomic_update,
  1382. .prepare_fb = vmw_du_cursor_plane_prepare_fb,
  1383. .cleanup_fb = vmw_du_cursor_plane_cleanup_fb,
  1384. };
  1385. static const struct
  1386. drm_plane_helper_funcs vmw_stdu_primary_plane_helper_funcs = {
  1387. .atomic_check = vmw_du_primary_plane_atomic_check,
  1388. .atomic_update = vmw_stdu_primary_plane_atomic_update,
  1389. .prepare_fb = vmw_stdu_primary_plane_prepare_fb,
  1390. .cleanup_fb = vmw_stdu_primary_plane_cleanup_fb,
  1391. };
  1392. static const struct drm_crtc_helper_funcs vmw_stdu_crtc_helper_funcs = {
  1393. .prepare = vmw_stdu_crtc_helper_prepare,
  1394. .mode_set_nofb = vmw_stdu_crtc_mode_set_nofb,
  1395. .atomic_check = vmw_du_crtc_atomic_check,
  1396. .atomic_begin = vmw_du_crtc_atomic_begin,
  1397. .atomic_flush = vmw_du_crtc_atomic_flush,
  1398. .atomic_enable = vmw_stdu_crtc_atomic_enable,
  1399. .atomic_disable = vmw_stdu_crtc_atomic_disable,
  1400. };
  1401. /**
  1402. * vmw_stdu_init - Sets up a Screen Target Display Unit
  1403. *
  1404. * @dev_priv: VMW DRM device
  1405. * @unit: unit number range from 0 to VMWGFX_NUM_DISPLAY_UNITS
  1406. *
  1407. * This function is called once per CRTC, and allocates one Screen Target
  1408. * display unit to represent that CRTC. Since the SVGA device does not separate
  1409. * out encoder and connector, they are represented as part of the STDU as well.
  1410. */
  1411. static int vmw_stdu_init(struct vmw_private *dev_priv, unsigned unit)
  1412. {
  1413. struct vmw_screen_target_display_unit *stdu;
  1414. struct drm_device *dev = &dev_priv->drm;
  1415. struct drm_connector *connector;
  1416. struct drm_encoder *encoder;
  1417. struct drm_plane *primary;
  1418. struct vmw_cursor_plane *cursor;
  1419. struct drm_crtc *crtc;
  1420. int ret;
  1421. stdu = kzalloc(sizeof(*stdu), GFP_KERNEL);
  1422. if (!stdu)
  1423. return -ENOMEM;
  1424. stdu->base.unit = unit;
  1425. crtc = &stdu->base.crtc;
  1426. encoder = &stdu->base.encoder;
  1427. connector = &stdu->base.connector;
  1428. primary = &stdu->base.primary;
  1429. cursor = &stdu->base.cursor;
  1430. stdu->base.pref_active = (unit == 0);
  1431. stdu->base.pref_width = dev_priv->initial_width;
  1432. stdu->base.pref_height = dev_priv->initial_height;
  1433. stdu->base.is_implicit = false;
  1434. /* Initialize primary plane */
  1435. ret = drm_universal_plane_init(dev, primary,
  1436. 0, &vmw_stdu_plane_funcs,
  1437. vmw_primary_plane_formats,
  1438. ARRAY_SIZE(vmw_primary_plane_formats),
  1439. NULL, DRM_PLANE_TYPE_PRIMARY, NULL);
  1440. if (ret) {
  1441. DRM_ERROR("Failed to initialize primary plane");
  1442. goto err_free;
  1443. }
  1444. drm_plane_helper_add(primary, &vmw_stdu_primary_plane_helper_funcs);
  1445. drm_plane_enable_fb_damage_clips(primary);
  1446. /* Initialize cursor plane */
  1447. ret = drm_universal_plane_init(dev, &cursor->base,
  1448. 0, &vmw_stdu_cursor_funcs,
  1449. vmw_cursor_plane_formats,
  1450. ARRAY_SIZE(vmw_cursor_plane_formats),
  1451. NULL, DRM_PLANE_TYPE_CURSOR, NULL);
  1452. if (ret) {
  1453. DRM_ERROR("Failed to initialize cursor plane");
  1454. drm_plane_cleanup(&stdu->base.primary);
  1455. goto err_free;
  1456. }
  1457. drm_plane_helper_add(&cursor->base, &vmw_stdu_cursor_plane_helper_funcs);
  1458. ret = drm_connector_init(dev, connector, &vmw_stdu_connector_funcs,
  1459. DRM_MODE_CONNECTOR_VIRTUAL);
  1460. if (ret) {
  1461. DRM_ERROR("Failed to initialize connector\n");
  1462. goto err_free;
  1463. }
  1464. drm_connector_helper_add(connector, &vmw_stdu_connector_helper_funcs);
  1465. connector->status = vmw_du_connector_detect(connector, false);
  1466. ret = drm_encoder_init(dev, encoder, &vmw_stdu_encoder_funcs,
  1467. DRM_MODE_ENCODER_VIRTUAL, NULL);
  1468. if (ret) {
  1469. DRM_ERROR("Failed to initialize encoder\n");
  1470. goto err_free_connector;
  1471. }
  1472. (void) drm_connector_attach_encoder(connector, encoder);
  1473. encoder->possible_crtcs = (1 << unit);
  1474. encoder->possible_clones = 0;
  1475. ret = drm_connector_register(connector);
  1476. if (ret) {
  1477. DRM_ERROR("Failed to register connector\n");
  1478. goto err_free_encoder;
  1479. }
  1480. ret = drm_crtc_init_with_planes(dev, crtc, primary,
  1481. &cursor->base,
  1482. &vmw_stdu_crtc_funcs, NULL);
  1483. if (ret) {
  1484. DRM_ERROR("Failed to initialize CRTC\n");
  1485. goto err_free_unregister;
  1486. }
  1487. drm_crtc_helper_add(crtc, &vmw_stdu_crtc_helper_funcs);
  1488. drm_mode_crtc_set_gamma_size(crtc, 256);
  1489. drm_object_attach_property(&connector->base,
  1490. dev_priv->hotplug_mode_update_property, 1);
  1491. drm_object_attach_property(&connector->base,
  1492. dev->mode_config.suggested_x_property, 0);
  1493. drm_object_attach_property(&connector->base,
  1494. dev->mode_config.suggested_y_property, 0);
  1495. return 0;
  1496. err_free_unregister:
  1497. drm_connector_unregister(connector);
  1498. err_free_encoder:
  1499. drm_encoder_cleanup(encoder);
  1500. err_free_connector:
  1501. drm_connector_cleanup(connector);
  1502. err_free:
  1503. kfree(stdu);
  1504. return ret;
  1505. }
  1506. /**
  1507. * vmw_stdu_destroy - Cleans up a vmw_screen_target_display_unit
  1508. *
  1509. * @stdu: Screen Target Display Unit to be destroyed
  1510. *
  1511. * Clean up after vmw_stdu_init
  1512. */
  1513. static void vmw_stdu_destroy(struct vmw_screen_target_display_unit *stdu)
  1514. {
  1515. vmw_du_cleanup(&stdu->base);
  1516. kfree(stdu);
  1517. }
  1518. /******************************************************************************
  1519. * Screen Target Display KMS Functions
  1520. *
  1521. * These functions are called by the common KMS code in vmwgfx_kms.c
  1522. *****************************************************************************/
  1523. /**
  1524. * vmw_kms_stdu_init_display - Initializes a Screen Target based display
  1525. *
  1526. * @dev_priv: VMW DRM device
  1527. *
  1528. * This function initialize a Screen Target based display device. It checks
  1529. * the capability bits to make sure the underlying hardware can support
  1530. * screen targets, and then creates the maximum number of CRTCs, a.k.a Display
  1531. * Units, as supported by the display hardware.
  1532. *
  1533. * RETURNS:
  1534. * 0 on success, error code otherwise
  1535. */
  1536. int vmw_kms_stdu_init_display(struct vmw_private *dev_priv)
  1537. {
  1538. struct drm_device *dev = &dev_priv->drm;
  1539. int i, ret;
  1540. /* Do nothing if there's no support for MOBs */
  1541. if (!dev_priv->has_mob)
  1542. return -ENOSYS;
  1543. if (!(dev_priv->capabilities & SVGA_CAP_GBOBJECTS))
  1544. return -ENOSYS;
  1545. dev_priv->active_display_unit = vmw_du_screen_target;
  1546. for (i = 0; i < VMWGFX_NUM_DISPLAY_UNITS; ++i) {
  1547. ret = vmw_stdu_init(dev_priv, i);
  1548. if (unlikely(ret != 0)) {
  1549. drm_err(&dev_priv->drm,
  1550. "Failed to initialize STDU %d", i);
  1551. return ret;
  1552. }
  1553. }
  1554. drm_mode_config_reset(dev);
  1555. return 0;
  1556. }