vmwgfx_stdu.c 54 KB

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