1 /*
2  * Copyright ©  2014 Intel Corporation
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a
5  * copy of this software and associated documentation files (the
6  * "Software"), to deal in the Software without restriction, including
7  * without limitation the rights to use, copy, modify, merge, publish,
8  * distribute, sub license, and/or sell copies of the Software, and to
9  * permit persons to whom the Software is furnished to do so, subject to
10  * the following conditions:
11  *
12  * The above copyright notice and this permission notice (including the
13  * next paragraph) shall be included in all copies or substantial portions
14  * of the Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
17  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
19  * IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
20  * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
21  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
22  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23  *
24  * Authors:
25  *    Xiang Haihao <haihao.xiang@intel.com>
26  *    Midhunchandra Kodiyath <midhunchandra.kodiyath@intel.com>
27  *
28  */
29 
30 #include "media_drv_driver.h"
31 #include "media_drv_batchbuffer.h"
32 #include "media_drv_gpe_utils.h"
33 #include "media_drv_util.h"
34 #include "media_drv_hwcmds.h"
35 
36 //#define DEBUG
37 VOID
media_batchbuffer_advance(MEDIA_BATCH_BUFFER * batch)38 media_batchbuffer_advance (MEDIA_BATCH_BUFFER * batch)
39 {
40 
41   MEDIA_DRV_ASSERT (batch->emit_total ==
42 		    (batch->cmd_ptr - batch->emit_start));
43 }
44 
45 static VOID
media_batchbuffer_reset(MEDIA_BATCH_BUFFER * batch,INT buffer_size)46 media_batchbuffer_reset (MEDIA_BATCH_BUFFER * batch, INT buffer_size)
47 {
48   struct media_driver_data *drv_data = batch->drv_data;
49   INT batch_size = buffer_size;
50 
51   MEDIA_DRV_ASSERT (batch->flag == I915_EXEC_RENDER ||
52 		    batch->flag == I915_EXEC_BLT ||
53 		    batch->flag == I915_EXEC_BSD ||
54 		    batch->flag == I915_EXEC_VEBOX);
55 
56   dri_bo_unreference (batch->buffer);
57   batch->buffer = dri_bo_alloc (drv_data->bufmgr,
58 				"batch buffer", batch_size, 0x1000);
59   MEDIA_DRV_ASSERT (batch->buffer);
60   dri_bo_map (batch->buffer, 1);
61   MEDIA_DRV_ASSERT (batch->buffer->virtual);
62   batch->map = batch->buffer->virtual;
63   batch->size = batch_size;
64   batch->cmd_ptr = batch->map;
65   batch->atomic = 0;
66 }
67 VOID
media_batchbuffer_submit(MEDIA_BATCH_BUFFER * batch)68 media_batchbuffer_submit (MEDIA_BATCH_BUFFER * batch)
69 {
70   UINT used = batch->cmd_ptr - batch->map;
71   if (used == 0)
72     {
73       return;
74     }
75   if ((used & 4) == 0)
76     {
77       *(UINT *) batch->cmd_ptr = 0;
78       batch->cmd_ptr += 4;
79     }
80 
81   *(UINT *) batch->cmd_ptr = MI_BATCH_BUFFER_END;
82   batch->cmd_ptr += 4;
83   dri_bo_unmap (batch->buffer);
84   used = batch->cmd_ptr - batch->map;
85   drm_intel_bo_mrb_exec (batch->buffer, used, 0, 0, 0, batch->flag);
86   media_batchbuffer_free (batch);
87 }
88 
89 VOID
media_batchbuffer_flush(MEDIA_BATCH_BUFFER * batch)90 media_batchbuffer_flush (MEDIA_BATCH_BUFFER * batch)
91 {
92   UINT used = batch->cmd_ptr - batch->map;
93   if (used == 0)
94     {
95       return;
96     }
97   if ((used & 4) == 0)
98     {
99       *(UINT *) batch->cmd_ptr = 0;
100       batch->cmd_ptr += 4;
101     }
102 
103   *(UINT *) batch->cmd_ptr = MI_BATCH_BUFFER_END;
104   batch->cmd_ptr += 4;
105   dri_bo_unmap (batch->buffer);
106   used = batch->cmd_ptr - batch->map;
107   drm_intel_bo_mrb_exec (batch->buffer, used, 0, 0, 0, batch->flag);
108   media_batchbuffer_reset (batch, batch->size);
109 }
110 
111 VOID
media_batchbuffer_begin(MEDIA_BATCH_BUFFER * batch,INT total)112 media_batchbuffer_begin (MEDIA_BATCH_BUFFER * batch, INT total)
113 {
114   batch->emit_total = total * 4;
115   batch->emit_start = batch->cmd_ptr;
116 }
117 
118 static UINT
media_batchbuffer_check_space(MEDIA_BATCH_BUFFER * batch)119 media_batchbuffer_check_space (MEDIA_BATCH_BUFFER * batch)
120 {
121   return (batch->size - BATCH_RESERVED) - (batch->cmd_ptr - batch->map);
122 }
123 
124 VOID
media_batchbuffer_check_flag(MEDIA_BATCH_BUFFER * batch,INT flag)125 media_batchbuffer_check_flag (MEDIA_BATCH_BUFFER * batch, INT flag)
126 {
127   if (flag != I915_EXEC_RENDER &&
128       flag != I915_EXEC_BLT &&
129       flag != I915_EXEC_BSD && flag != I915_EXEC_VEBOX)
130     return;
131 
132   if (batch->flag == flag)
133     return;
134 
135   media_batchbuffer_flush (batch);
136   batch->flag = flag;
137 }
138 
139 VOID
media_batchbuffer_require_space(MEDIA_BATCH_BUFFER * batch,UINT size)140 media_batchbuffer_require_space (MEDIA_BATCH_BUFFER * batch, UINT size)
141 {
142   MEDIA_DRV_ASSERT (size < batch->size - 8);
143   if (media_batchbuffer_check_space (batch) < size)
144     {
145       media_batchbuffer_flush (batch);
146     }
147 }
148 
149 VOID
media_batchbuffer_emit_dword(MEDIA_BATCH_BUFFER * batch,UINT cmd)150 media_batchbuffer_emit_dword (MEDIA_BATCH_BUFFER * batch, UINT cmd)
151 {
152   MEDIA_DRV_ASSERT (media_batchbuffer_check_space (batch) >= 4);
153   *(UINT *) batch->cmd_ptr = cmd;
154   batch->cmd_ptr += 4;
155 }
156 
157 VOID
media_batchbuffer_emit_reloc(MEDIA_BATCH_BUFFER * batch,dri_bo * bo,UINT read_domains,UINT write_domains,UINT delta)158 media_batchbuffer_emit_reloc (MEDIA_BATCH_BUFFER * batch, dri_bo * bo,
159 			      UINT read_domains, UINT write_domains,
160 			      UINT delta)
161 {
162   assert (batch->cmd_ptr - batch->map < batch->size);
163   dri_bo_emit_reloc (batch->buffer,/* I915_GEM_DOMAIN_RENDER*/ read_domains, write_domains,delta, batch->cmd_ptr - batch->map, bo);
164   media_batchbuffer_emit_dword (batch, bo->offset + delta);
165 }
166 
167 MEDIA_BATCH_BUFFER *
media_batchbuffer_new(struct media_driver_data * drv_data,INT flag,INT buffer_size)168 media_batchbuffer_new (struct media_driver_data * drv_data, INT flag,
169 		       INT buffer_size)
170 {
171   MEDIA_BATCH_BUFFER *batch = media_drv_alloc_memory (sizeof (*batch));
172   MEDIA_DRV_ASSERT (flag == I915_EXEC_RENDER);
173 
174   if (!buffer_size || buffer_size < BATCH_SIZE)
175     {
176       buffer_size = BATCH_SIZE;
177     }
178   /* the buffer size can't exceed 4M */
179   if (buffer_size > MAX_BATCH_SIZE)
180     {
181       buffer_size = MAX_BATCH_SIZE;
182     }
183   batch->drv_data = drv_data;
184   batch->flag = flag;
185 
186   media_batchbuffer_reset (batch, buffer_size);
187 
188   return batch;
189 }
190 
191 VOID
media_batchbuffer_free(MEDIA_BATCH_BUFFER * batch)192 media_batchbuffer_free (MEDIA_BATCH_BUFFER * batch)
193 {
194   if (batch->map)
195     {
196       dri_bo_unmap (batch->buffer);
197       batch->map = NULL;
198     }
199 
200   dri_bo_unreference (batch->buffer);
201   media_drv_free_memory (batch);
202 }
203 
204 BOOL
media_allocate_resource(MEDIA_RESOURCE * res,dri_bufmgr * bufmgr,const BYTE * name,UINT size,UINT align)205 media_allocate_resource (MEDIA_RESOURCE * res, dri_bufmgr * bufmgr,
206 			 const BYTE * name, UINT size, UINT align)
207 {
208   res->bo = dri_bo_alloc (bufmgr,(const CHAR *) name, size, align);
209   res->bo_size = size;
210   return SUCCESS;
211 }
212 
213 BOOL
media_allocate_resource_ext(MEDIA_RESOURCE * res,dri_bufmgr * bufmgr,MEDIA_ALLOC_PARAMS * params,UINT align)214 media_allocate_resource_ext (MEDIA_RESOURCE * res, dri_bufmgr * bufmgr,
215 			     MEDIA_ALLOC_PARAMS * params, UINT align)
216 {
217   res->bo = dri_bo_alloc (bufmgr,(const CHAR *) params->buf_name, params->bo_size, align);
218   res->bo_size = params->bo_size;
219   res->width = params->width;
220   res->height = params->height;
221   res->tiling = params->tiling;
222 
223   return SUCCESS;
224 }
225 
226 VOID *
media_map_buffer_obj(dri_bo * bo)227 media_map_buffer_obj (dri_bo * bo)
228 {
229   dri_bo_map (bo, 1);
230   MEDIA_DRV_ASSERT (bo->virtual);
231   return bo->virtual;
232 }
233 
234 BOOL
media_unmap_buffer_obj(dri_bo * bo)235 media_unmap_buffer_obj (dri_bo * bo)
236 {
237   dri_bo_unmap (bo);
238   return SUCCESS;
239 }
240 
241 void
media_batchbuffer_emit_mi_flush(MEDIA_BATCH_BUFFER * batch)242 media_batchbuffer_emit_mi_flush (MEDIA_BATCH_BUFFER * batch)
243 {
244   struct media_driver_data *drv_data = batch->drv_data;
245 
246   if (IS_GEN75(drv_data->device_id) ||
247       IS_CHERRYVIEW(drv_data->device_id) ||
248       IS_GEN8(drv_data->device_id)) {
249       if (batch->flag == I915_EXEC_RENDER) {
250           if (IS_GEN8(drv_data->device_id) ||
251               IS_CHERRYVIEW(drv_data->device_id)) {
252               BEGIN_BATCH(batch, 6);
253               OUT_BATCH(batch, CMD_PIPE_CONTROL | (6 - 2));
254 
255               OUT_BATCH(batch,
256                         CMD_PIPE_CONTROL_CS_STALL |
257                         CMD_PIPE_CONTROL_WC_FLUSH |
258                         CMD_PIPE_CONTROL_TC_FLUSH |
259                         CMD_PIPE_CONTROL_DC_FLUSH |
260                         CMD_PIPE_CONTROL_NOWRITE);
261               OUT_BATCH(batch, 0); /* write address */
262               OUT_BATCH(batch, 0);
263               OUT_BATCH(batch, 0); /* write data */
264               OUT_BATCH(batch, 0);
265               ADVANCE_BATCH(batch);
266           } else {
267               BEGIN_BATCH(batch, 4);
268               OUT_BATCH(batch, CMD_PIPE_CONTROL | (4 - 2));
269 
270               OUT_BATCH(batch,
271                         CMD_PIPE_CONTROL_WC_FLUSH |
272                         CMD_PIPE_CONTROL_TC_FLUSH |
273                         CMD_PIPE_CONTROL_DC_FLUSH |
274                         CMD_PIPE_CONTROL_NOWRITE);
275               OUT_BATCH(batch, 0); /* write address */
276               OUT_BATCH(batch, 0); /* write data */
277               ADVANCE_BATCH(batch);
278           }
279 
280       } else {
281           if (batch->flag == I915_EXEC_BLT) {
282               __BEGIN_BATCH(batch, 4, I915_EXEC_BLT);
283               OUT_BATCH(batch, MI_FLUSH_DW);
284               OUT_BATCH(batch, 0);
285               OUT_BATCH(batch, 0);
286               OUT_BATCH(batch, 0);
287               ADVANCE_BATCH(batch);
288           } else if (batch->flag == I915_EXEC_BSD) {
289               __BEGIN_BATCH(batch, 4, I915_EXEC_BSD);
290               OUT_BATCH(batch, MI_FLUSH_DW | MI_FLUSH_DW_VIDEO_PIPELINE_CACHE_INVALIDATE);
291               OUT_BATCH(batch, 0);
292               OUT_BATCH(batch, 0);
293               OUT_BATCH(batch, 0);
294               ADVANCE_BATCH(batch);
295           }
296       }
297   }
298 }
299 
300 static void
media_batchbuffer_start_atomic_helper(MEDIA_BATCH_BUFFER * batch,int flag,unsigned int size)301 media_batchbuffer_start_atomic_helper(MEDIA_BATCH_BUFFER *batch,
302                                       int flag,
303                                       unsigned int size)
304 {
305     media_batchbuffer_check_flag(batch, flag);
306     media_batchbuffer_require_space(batch, size);
307     batch->atomic = 1;
308 }
309 
310 void
media_batchbuffer_start_atomic(MEDIA_BATCH_BUFFER * batch,unsigned int size)311 media_batchbuffer_start_atomic(MEDIA_BATCH_BUFFER *batch, unsigned int size)
312 {
313     media_batchbuffer_start_atomic_helper(batch, I915_EXEC_RENDER, size);
314 }
315 
316 void
media_batchbuffer_start_atomic_blt(MEDIA_BATCH_BUFFER * batch,unsigned int size)317 media_batchbuffer_start_atomic_blt(MEDIA_BATCH_BUFFER *batch, unsigned int size)
318 {
319     media_batchbuffer_start_atomic_helper(batch, I915_EXEC_BLT, size);
320 }
321 
322 void
media_batchbuffer_start_atomic_bcs(MEDIA_BATCH_BUFFER * batch,unsigned int size)323 media_batchbuffer_start_atomic_bcs(MEDIA_BATCH_BUFFER *batch, unsigned int size)
324 {
325     media_batchbuffer_start_atomic_helper(batch, I915_EXEC_BSD, size);
326 }
327 
328 void
media_batchbuffer_start_atomic_veb(MEDIA_BATCH_BUFFER * batch,unsigned int size)329 media_batchbuffer_start_atomic_veb(MEDIA_BATCH_BUFFER *batch, unsigned int size)
330 {
331     media_batchbuffer_start_atomic_helper(batch, I915_EXEC_VEBOX, size);
332 }
333 
334 void
media_batchbuffer_end_atomic(MEDIA_BATCH_BUFFER * batch)335 media_batchbuffer_end_atomic(MEDIA_BATCH_BUFFER *batch)
336 {
337     batch->atomic = 0;
338 }
339