1/*
2 * Copyright © 2016 Red Hat.
3 * Copyright © 2016 Bas Nieuwenhuizen
4 * based on amdgpu winsys.
5 * Copyright © 2011 Marek Olšák <maraeo@gmail.com>
6 * Copyright © 2015 Advanced Micro Devices, Inc.
7 *
8 * Permission is hereby granted, free of charge, to any person obtaining a
9 * copy of this software and associated documentation files (the "Software"),
10 * to deal in the Software without restriction, including without limitation
11 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
12 * and/or sell copies of the Software, and to permit persons to whom the
13 * Software is furnished to do so, subject to the following conditions:
14 *
15 * The above copyright notice and this permission notice (including the next
16 * paragraph) shall be included in all copies or substantial portions of the
17 * Software.
18 *
19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
22 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
24 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
25 * IN THE SOFTWARE.
26 */
27#include "radv_amdgpu_winsys.h"
28#include "radv_amdgpu_winsys_public.h"
29#include "radv_amdgpu_surface.h"
30#include "amdgpu_id.h"
31#include "xf86drm.h"
32#include <stdio.h>
33#include <stdlib.h>
34#include <string.h>
35#include <amdgpu_drm.h>
36#include <assert.h>
37#include "radv_amdgpu_cs.h"
38#include "radv_amdgpu_bo.h"
39#include "radv_amdgpu_surface.h"
40
41#define CIK_TILE_MODE_COLOR_2D			14
42
43#define CIK__GB_TILE_MODE__PIPE_CONFIG(x)        (((x) >> 6) & 0x1f)
44#define     CIK__PIPE_CONFIG__ADDR_SURF_P2               0
45#define     CIK__PIPE_CONFIG__ADDR_SURF_P4_8x16          4
46#define     CIK__PIPE_CONFIG__ADDR_SURF_P4_16x16         5
47#define     CIK__PIPE_CONFIG__ADDR_SURF_P4_16x32         6
48#define     CIK__PIPE_CONFIG__ADDR_SURF_P4_32x32         7
49#define     CIK__PIPE_CONFIG__ADDR_SURF_P8_16x16_8x16    8
50#define     CIK__PIPE_CONFIG__ADDR_SURF_P8_16x32_8x16    9
51#define     CIK__PIPE_CONFIG__ADDR_SURF_P8_32x32_8x16    10
52#define     CIK__PIPE_CONFIG__ADDR_SURF_P8_16x32_16x16   11
53#define     CIK__PIPE_CONFIG__ADDR_SURF_P8_32x32_16x16   12
54#define     CIK__PIPE_CONFIG__ADDR_SURF_P8_32x32_16x32   13
55#define     CIK__PIPE_CONFIG__ADDR_SURF_P8_32x64_32x32   14
56#define     CIK__PIPE_CONFIG__ADDR_SURF_P16_32X32_8X16   16
57#define     CIK__PIPE_CONFIG__ADDR_SURF_P16_32X32_16X16  17
58
59static unsigned radv_cik_get_num_tile_pipes(struct amdgpu_gpu_info *info)
60{
61	unsigned mode2d = info->gb_tile_mode[CIK_TILE_MODE_COLOR_2D];
62
63	switch (CIK__GB_TILE_MODE__PIPE_CONFIG(mode2d)) {
64	case CIK__PIPE_CONFIG__ADDR_SURF_P2:
65		return 2;
66	case CIK__PIPE_CONFIG__ADDR_SURF_P4_8x16:
67	case CIK__PIPE_CONFIG__ADDR_SURF_P4_16x16:
68	case CIK__PIPE_CONFIG__ADDR_SURF_P4_16x32:
69	case CIK__PIPE_CONFIG__ADDR_SURF_P4_32x32:
70		return 4;
71	case CIK__PIPE_CONFIG__ADDR_SURF_P8_16x16_8x16:
72	case CIK__PIPE_CONFIG__ADDR_SURF_P8_16x32_8x16:
73	case CIK__PIPE_CONFIG__ADDR_SURF_P8_32x32_8x16:
74	case CIK__PIPE_CONFIG__ADDR_SURF_P8_16x32_16x16:
75	case CIK__PIPE_CONFIG__ADDR_SURF_P8_32x32_16x16:
76	case CIK__PIPE_CONFIG__ADDR_SURF_P8_32x32_16x32:
77	case CIK__PIPE_CONFIG__ADDR_SURF_P8_32x64_32x32:
78		return 8;
79	case CIK__PIPE_CONFIG__ADDR_SURF_P16_32X32_8X16:
80	case CIK__PIPE_CONFIG__ADDR_SURF_P16_32X32_16X16:
81		return 16;
82	default:
83		fprintf(stderr, "Invalid CIK pipe configuration, assuming P2\n");
84		assert(!"this should never occur");
85		return 2;
86	}
87}
88
89static const char *
90get_chip_name(enum radeon_family family)
91{
92	switch (family) {
93	case CHIP_TAHITI: return "AMD RADV TAHITI";
94	case CHIP_PITCAIRN: return "AMD RADV PITCAIRN";
95	case CHIP_VERDE: return "AMD RADV CAPE VERDE";
96	case CHIP_OLAND: return "AMD RADV OLAND";
97	case CHIP_HAINAN: return "AMD RADV HAINAN";
98	case CHIP_BONAIRE: return "AMD RADV BONAIRE";
99	case CHIP_KAVERI: return "AMD RADV KAVERI";
100	case CHIP_KABINI: return "AMD RADV KABINI";
101	case CHIP_HAWAII: return "AMD RADV HAWAII";
102	case CHIP_MULLINS: return "AMD RADV MULLINS";
103	case CHIP_TONGA: return "AMD RADV TONGA";
104	case CHIP_ICELAND: return "AMD RADV ICELAND";
105	case CHIP_CARRIZO: return "AMD RADV CARRIZO";
106	case CHIP_FIJI: return "AMD RADV FIJI";
107	case CHIP_POLARIS10: return "AMD RADV POLARIS10";
108	case CHIP_POLARIS11: return "AMD RADV POLARIS11";
109	case CHIP_STONEY: return "AMD RADV STONEY";
110	default: return "AMD RADV unknown";
111	}
112}
113
114
115static bool
116do_winsys_init(struct radv_amdgpu_winsys *ws, int fd)
117{
118	struct amdgpu_buffer_size_alignments alignment_info = {};
119	struct amdgpu_heap_info vram, visible_vram, gtt;
120	struct drm_amdgpu_info_hw_ip dma = {};
121	struct drm_amdgpu_info_hw_ip compute = {};
122	drmDevicePtr devinfo;
123	int r;
124	int i, j;
125	/* Get PCI info. */
126	r = drmGetDevice(fd, &devinfo);
127	if (r) {
128		fprintf(stderr, "amdgpu: drmGetDevice failed.\n");
129		goto fail;
130	}
131	ws->info.pci_domain = devinfo->businfo.pci->domain;
132	ws->info.pci_bus = devinfo->businfo.pci->bus;
133	ws->info.pci_dev = devinfo->businfo.pci->dev;
134	ws->info.pci_func = devinfo->businfo.pci->func;
135	drmFreeDevice(&devinfo);
136
137	/* Query hardware and driver information. */
138	r = amdgpu_query_gpu_info(ws->dev, &ws->amdinfo);
139	if (r) {
140		fprintf(stderr, "amdgpu: amdgpu_query_gpu_info failed.\n");
141		goto fail;
142	}
143
144	r = amdgpu_query_buffer_size_alignment(ws->dev, &alignment_info);
145	if (r) {
146		fprintf(stderr, "amdgpu: amdgpu_query_buffer_size_alignment failed.\n");
147		goto fail;
148	}
149
150	r = amdgpu_query_heap_info(ws->dev, AMDGPU_GEM_DOMAIN_VRAM, 0, &vram);
151	if (r) {
152		fprintf(stderr, "amdgpu: amdgpu_query_heap_info(vram) failed.\n");
153		goto fail;
154	}
155
156	r = amdgpu_query_heap_info(ws->dev, AMDGPU_GEM_DOMAIN_VRAM,
157	                           AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED, &visible_vram);
158	if (r) {
159		fprintf(stderr, "amdgpu: amdgpu_query_heap_info(visible_vram) failed.\n");
160		goto fail;
161	}
162
163	r = amdgpu_query_heap_info(ws->dev, AMDGPU_GEM_DOMAIN_GTT, 0, &gtt);
164	if (r) {
165		fprintf(stderr, "amdgpu: amdgpu_query_heap_info(gtt) failed.\n");
166		goto fail;
167	}
168
169	r = amdgpu_query_hw_ip_info(ws->dev, AMDGPU_HW_IP_DMA, 0, &dma);
170	if (r) {
171		fprintf(stderr, "amdgpu: amdgpu_query_hw_ip_info(dma) failed.\n");
172		goto fail;
173	}
174
175	r = amdgpu_query_hw_ip_info(ws->dev, AMDGPU_HW_IP_COMPUTE, 0, &compute);
176	if (r) {
177		fprintf(stderr, "amdgpu: amdgpu_query_hw_ip_info(compute) failed.\n");
178		goto fail;
179	}
180	ws->info.pci_id = ws->amdinfo.asic_id; /* TODO: is this correct? */
181	ws->info.vce_harvest_config = ws->amdinfo.vce_harvest_config;
182
183	switch (ws->info.pci_id) {
184#define CHIPSET(pci_id, name, cfamily) case pci_id: ws->info.family = CHIP_##cfamily; break;
185#include "pci_ids/radeonsi_pci_ids.h"
186#undef CHIPSET
187	default:
188		fprintf(stderr, "amdgpu: Invalid PCI ID.\n");
189		goto fail;
190	}
191
192	if (ws->info.family >= CHIP_TONGA)
193		ws->info.chip_class = VI;
194	else if (ws->info.family >= CHIP_BONAIRE)
195		ws->info.chip_class = CIK;
196	else if (ws->info.family >= CHIP_TAHITI)
197		ws->info.chip_class = SI;
198	else {
199		fprintf(stderr, "amdgpu: Unknown family.\n");
200		goto fail;
201	}
202
203	/* family and rev_id are for addrlib */
204	switch (ws->info.family) {
205	case CHIP_TAHITI:
206		ws->family = FAMILY_SI;
207		ws->rev_id = SI_TAHITI_P_A0;
208		break;
209	case CHIP_PITCAIRN:
210		ws->family = FAMILY_SI;
211		ws->rev_id = SI_PITCAIRN_PM_A0;
212	  break;
213	case CHIP_VERDE:
214		ws->family = FAMILY_SI;
215		ws->rev_id = SI_CAPEVERDE_M_A0;
216		break;
217	case CHIP_OLAND:
218		ws->family = FAMILY_SI;
219		ws->rev_id = SI_OLAND_M_A0;
220		break;
221	case CHIP_HAINAN:
222		ws->family = FAMILY_SI;
223		ws->rev_id = SI_HAINAN_V_A0;
224		break;
225	case CHIP_BONAIRE:
226		ws->family = FAMILY_CI;
227		ws->rev_id = CI_BONAIRE_M_A0;
228		break;
229	case CHIP_KAVERI:
230		ws->family = FAMILY_KV;
231		ws->rev_id = KV_SPECTRE_A0;
232		break;
233	case CHIP_KABINI:
234		ws->family = FAMILY_KV;
235		ws->rev_id = KB_KALINDI_A0;
236		break;
237	case CHIP_HAWAII:
238		ws->family = FAMILY_CI;
239		ws->rev_id = CI_HAWAII_P_A0;
240		break;
241	case CHIP_MULLINS:
242		ws->family = FAMILY_KV;
243		ws->rev_id = ML_GODAVARI_A0;
244		break;
245	case CHIP_TONGA:
246		ws->family = FAMILY_VI;
247		ws->rev_id = VI_TONGA_P_A0;
248		break;
249	case CHIP_ICELAND:
250		ws->family = FAMILY_VI;
251		ws->rev_id = VI_ICELAND_M_A0;
252		break;
253	case CHIP_CARRIZO:
254		ws->family = FAMILY_CZ;
255		ws->rev_id = CARRIZO_A0;
256		break;
257	case CHIP_STONEY:
258		ws->family = FAMILY_CZ;
259		ws->rev_id = STONEY_A0;
260		break;
261	case CHIP_FIJI:
262		ws->family = FAMILY_VI;
263		ws->rev_id = VI_FIJI_P_A0;
264		break;
265	case CHIP_POLARIS10:
266		ws->family = FAMILY_VI;
267		ws->rev_id = VI_POLARIS10_P_A0;
268		break;
269	case CHIP_POLARIS11:
270		ws->family = FAMILY_VI;
271		ws->rev_id = VI_POLARIS11_M_A0;
272		break;
273	default:
274		fprintf(stderr, "amdgpu: Unknown family.\n");
275		goto fail;
276	}
277
278	ws->addrlib = radv_amdgpu_addr_create(&ws->amdinfo, ws->family, ws->rev_id, ws->info.chip_class);
279	if (!ws->addrlib) {
280		fprintf(stderr, "amdgpu: Cannot create addrlib.\n");
281		goto fail;
282	}
283
284	assert(util_is_power_of_two(dma.available_rings + 1));
285	assert(util_is_power_of_two(compute.available_rings + 1));
286
287	/* Set hardware information. */
288	ws->info.name = get_chip_name(ws->info.family);
289	ws->info.gart_size = gtt.heap_size;
290	ws->info.vram_size = vram.heap_size;
291	ws->info.visible_vram_size = visible_vram.heap_size;
292	/* convert the shader clock from KHz to MHz */
293	ws->info.max_shader_clock = ws->amdinfo.max_engine_clk / 1000;
294	ws->info.max_se = ws->amdinfo.num_shader_engines;
295	ws->info.max_sh_per_se = ws->amdinfo.num_shader_arrays_per_engine;
296	ws->info.has_uvd = 0;
297	ws->info.vce_fw_version = 0;
298	ws->info.has_userptr = TRUE;
299	ws->info.num_render_backends = ws->amdinfo.rb_pipes;
300	ws->info.clock_crystal_freq = ws->amdinfo.gpu_counter_freq;
301	ws->info.num_tile_pipes = radv_cik_get_num_tile_pipes(&ws->amdinfo);
302	ws->info.pipe_interleave_bytes = 256 << ((ws->amdinfo.gb_addr_cfg >> 4) & 0x7);
303	ws->info.has_virtual_memory = TRUE;
304	ws->info.sdma_rings = MIN2(util_bitcount(dma.available_rings),
305	                           MAX_RINGS_PER_TYPE);
306	ws->info.compute_rings = MIN2(util_bitcount(compute.available_rings),
307	                              MAX_RINGS_PER_TYPE);
308
309	/* Get the number of good compute units. */
310	ws->info.num_good_compute_units = 0;
311	for (i = 0; i < ws->info.max_se; i++)
312		for (j = 0; j < ws->info.max_sh_per_se; j++)
313			ws->info.num_good_compute_units +=
314				util_bitcount(ws->amdinfo.cu_bitmap[i][j]);
315
316	memcpy(ws->info.si_tile_mode_array, ws->amdinfo.gb_tile_mode,
317	       sizeof(ws->amdinfo.gb_tile_mode));
318	ws->info.enabled_rb_mask = ws->amdinfo.enabled_rb_pipes_mask;
319
320	memcpy(ws->info.cik_macrotile_mode_array, ws->amdinfo.gb_macro_tile_mode,
321	       sizeof(ws->amdinfo.gb_macro_tile_mode));
322
323	ws->info.gart_page_size = alignment_info.size_remote;
324
325	if (ws->info.chip_class == SI)
326		ws->info.gfx_ib_pad_with_type2 = TRUE;
327
328	ws->use_ib_bos = ws->family >= FAMILY_CI;
329	return true;
330fail:
331	return false;
332}
333
334static void radv_amdgpu_winsys_query_info(struct radeon_winsys *rws,
335                                     struct radeon_info *info)
336{
337	*info = ((struct radv_amdgpu_winsys *)rws)->info;
338}
339
340static void radv_amdgpu_winsys_destroy(struct radeon_winsys *rws)
341{
342	struct radv_amdgpu_winsys *ws = (struct radv_amdgpu_winsys*)rws;
343
344	AddrDestroy(ws->addrlib);
345	amdgpu_device_deinitialize(ws->dev);
346	FREE(rws);
347}
348
349struct radeon_winsys *
350radv_amdgpu_winsys_create(int fd)
351{
352	uint32_t drm_major, drm_minor, r;
353	amdgpu_device_handle dev;
354	struct radv_amdgpu_winsys *ws;
355
356	r = amdgpu_device_initialize(fd, &drm_major, &drm_minor, &dev);
357	if (r)
358		return NULL;
359
360	ws = calloc(1, sizeof(struct radv_amdgpu_winsys));
361	if (!ws)
362		goto fail;
363
364	ws->dev = dev;
365	ws->info.drm_major = drm_major;
366	ws->info.drm_minor = drm_minor;
367	if (!do_winsys_init(ws, fd))
368		goto winsys_fail;
369
370	ws->debug_all_bos = getenv("RADV_DEBUG_ALL_BOS") ? true : false;
371	LIST_INITHEAD(&ws->global_bo_list);
372	pthread_mutex_init(&ws->global_bo_list_lock, NULL);
373	ws->base.query_info = radv_amdgpu_winsys_query_info;
374	ws->base.destroy = radv_amdgpu_winsys_destroy;
375	radv_amdgpu_bo_init_functions(ws);
376	radv_amdgpu_cs_init_functions(ws);
377	radv_amdgpu_surface_init_functions(ws);
378
379	return &ws->base;
380
381winsys_fail:
382	free(ws);
383fail:
384	amdgpu_device_deinitialize(dev);
385	return NULL;
386}
387