Home | History | Annotate | Download | only in amdgpu
      1 /*
      2  * Copyright  2016 Red Hat.
      3  * Copyright  2016 Bas Nieuwenhuizen
      4  * based on amdgpu winsys.
      5  * Copyright  2011 Marek Olk <maraeo (at) 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 
     59 static 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 
     89 static const char *
     90 get_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 
    115 static bool
    116 do_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;
    330 fail:
    331 	return false;
    332 }
    333 
    334 static 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 
    340 static 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 
    349 struct radeon_winsys *
    350 radv_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 
    381 winsys_fail:
    382 	free(ws);
    383 fail:
    384 	amdgpu_device_deinitialize(dev);
    385 	return NULL;
    386 }
    387