2 * Copyright 2016 Advanced Micro Devices, Inc.
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 * OTHER DEALINGS IN THE SOFTWARE.
24 #include <drm/amdgpu_drm.h>
26 #include "atomfirmware.h"
27 #include "amdgpu_atomfirmware.h"
31 #define get_index_into_master_table(master_table, table_name) (offsetof(struct master_table, table_name) / sizeof(uint16_t))
33 bool amdgpu_atomfirmware_gpu_supports_virtualization(struct amdgpu_device
*adev
)
35 int index
= get_index_into_master_table(atom_master_list_of_data_tables_v2_1
,
39 if (amdgpu_atom_parse_data_header(adev
->mode_info
.atom_context
, index
, NULL
,
40 NULL
, NULL
, &data_offset
)) {
41 struct atom_firmware_info_v3_1
*firmware_info
=
42 (struct atom_firmware_info_v3_1
*)(adev
->mode_info
.atom_context
->bios
+
45 if (le32_to_cpu(firmware_info
->firmware_capability
) &
46 ATOM_FIRMWARE_CAP_GPU_VIRTUALIZATION
)
52 void amdgpu_atomfirmware_scratch_regs_init(struct amdgpu_device
*adev
)
54 int index
= get_index_into_master_table(atom_master_list_of_data_tables_v2_1
,
58 if (amdgpu_atom_parse_data_header(adev
->mode_info
.atom_context
, index
, NULL
,
59 NULL
, NULL
, &data_offset
)) {
60 struct atom_firmware_info_v3_1
*firmware_info
=
61 (struct atom_firmware_info_v3_1
*)(adev
->mode_info
.atom_context
->bios
+
64 adev
->bios_scratch_reg_offset
=
65 le32_to_cpu(firmware_info
->bios_scratch_reg_startaddr
);
69 int amdgpu_atomfirmware_allocate_fb_scratch(struct amdgpu_device
*adev
)
71 struct atom_context
*ctx
= adev
->mode_info
.atom_context
;
72 int index
= get_index_into_master_table(atom_master_list_of_data_tables_v2_1
,
73 vram_usagebyfirmware
);
74 struct vram_usagebyfirmware_v2_1
* firmware_usage
;
75 uint32_t start_addr
, size
;
79 if (amdgpu_atom_parse_data_header(ctx
, index
, NULL
, NULL
, NULL
, &data_offset
)) {
80 firmware_usage
= (struct vram_usagebyfirmware_v2_1
*)(ctx
->bios
+ data_offset
);
81 DRM_DEBUG("atom firmware requested %08x %dkb fw %dkb drv\n",
82 le32_to_cpu(firmware_usage
->start_address_in_kb
),
83 le16_to_cpu(firmware_usage
->used_by_firmware_in_kb
),
84 le16_to_cpu(firmware_usage
->used_by_driver_in_kb
));
86 start_addr
= le32_to_cpu(firmware_usage
->start_address_in_kb
);
87 size
= le16_to_cpu(firmware_usage
->used_by_firmware_in_kb
);
89 if ((uint32_t)(start_addr
& ATOM_VRAM_OPERATION_FLAGS_MASK
) ==
90 (uint32_t)(ATOM_VRAM_BLOCK_SRIOV_MSG_SHARE_RESERVATION
<<
91 ATOM_VRAM_OPERATION_FLAGS_SHIFT
)) {
92 /* Firmware request VRAM reservation for SR-IOV */
93 adev
->fw_vram_usage
.start_offset
= (start_addr
&
94 (~ATOM_VRAM_OPERATION_FLAGS_MASK
)) << 10;
95 adev
->fw_vram_usage
.size
= size
<< 10;
96 /* Use the default scratch size */
99 usage_bytes
= le16_to_cpu(firmware_usage
->used_by_driver_in_kb
) << 10;
102 ctx
->scratch_size_bytes
= 0;
103 if (usage_bytes
== 0)
104 usage_bytes
= 20 * 1024;
105 /* allocate some scratch memory */
106 ctx
->scratch
= kzalloc(usage_bytes
, GFP_KERNEL
);
109 ctx
->scratch_size_bytes
= usage_bytes
;
114 struct atom_integrated_system_info_v1_11 v11
;
118 struct atom_umc_info_v3_1 v31
;
121 * Return vram width from integrated system info table, if available,
124 int amdgpu_atomfirmware_get_vram_width(struct amdgpu_device
*adev
)
126 struct amdgpu_mode_info
*mode_info
= &adev
->mode_info
;
127 int index
= get_index_into_master_table(atom_master_list_of_data_tables_v2_1
,
128 integratedsysteminfo
);
129 u16 data_offset
, size
;
130 union igp_info
*igp_info
;
133 /* get any igp specific overrides */
134 if (amdgpu_atom_parse_data_header(mode_info
->atom_context
, index
, &size
,
135 &frev
, &crev
, &data_offset
)) {
136 igp_info
= (union igp_info
*)
137 (mode_info
->atom_context
->bios
+ data_offset
);
140 return igp_info
->v11
.umachannelnumber
* 64;
149 static int convert_atom_mem_type_to_vram_type (struct amdgpu_device
*adev
,
154 if (adev
->flags
& AMD_IS_APU
) {
155 switch (atom_mem_type
) {
158 vram_type
= AMDGPU_VRAM_TYPE_DDR2
;
162 vram_type
= AMDGPU_VRAM_TYPE_DDR3
;
166 vram_type
= AMDGPU_VRAM_TYPE_DDR4
;
169 vram_type
= AMDGPU_VRAM_TYPE_UNKNOWN
;
173 switch (atom_mem_type
) {
174 case ATOM_DGPU_VRAM_TYPE_GDDR5
:
175 vram_type
= AMDGPU_VRAM_TYPE_GDDR5
;
177 case ATOM_DGPU_VRAM_TYPE_HBM
:
178 vram_type
= AMDGPU_VRAM_TYPE_HBM
;
181 vram_type
= AMDGPU_VRAM_TYPE_UNKNOWN
;
189 * Return vram type from either integrated system info table
190 * or umc info table, if available, or 0 (TYPE_UNKNOWN) if not
192 int amdgpu_atomfirmware_get_vram_type(struct amdgpu_device
*adev
)
194 struct amdgpu_mode_info
*mode_info
= &adev
->mode_info
;
196 u16 data_offset
, size
;
197 union igp_info
*igp_info
;
198 union umc_info
*umc_info
;
202 if (adev
->flags
& AMD_IS_APU
)
203 index
= get_index_into_master_table(atom_master_list_of_data_tables_v2_1
,
204 integratedsysteminfo
);
206 index
= get_index_into_master_table(atom_master_list_of_data_tables_v2_1
,
208 if (amdgpu_atom_parse_data_header(mode_info
->atom_context
,
210 &frev
, &crev
, &data_offset
)) {
211 if (adev
->flags
& AMD_IS_APU
) {
212 igp_info
= (union igp_info
*)
213 (mode_info
->atom_context
->bios
+ data_offset
);
216 mem_type
= igp_info
->v11
.memorytype
;
217 return convert_atom_mem_type_to_vram_type(adev
, mem_type
);
222 umc_info
= (union umc_info
*)
223 (mode_info
->atom_context
->bios
+ data_offset
);
226 mem_type
= umc_info
->v31
.vram_type
;
227 return convert_atom_mem_type_to_vram_type(adev
, mem_type
);
237 union firmware_info
{
238 struct atom_firmware_info_v3_1 v31
;
242 struct atom_smu_info_v3_1 v31
;
245 int amdgpu_atomfirmware_get_clock_info(struct amdgpu_device
*adev
)
247 struct amdgpu_mode_info
*mode_info
= &adev
->mode_info
;
248 struct amdgpu_pll
*spll
= &adev
->clock
.spll
;
249 struct amdgpu_pll
*mpll
= &adev
->clock
.mpll
;
251 uint16_t data_offset
;
252 int ret
= -EINVAL
, index
;
254 index
= get_index_into_master_table(atom_master_list_of_data_tables_v2_1
,
256 if (amdgpu_atom_parse_data_header(mode_info
->atom_context
, index
, NULL
,
257 &frev
, &crev
, &data_offset
)) {
258 union firmware_info
*firmware_info
=
259 (union firmware_info
*)(mode_info
->atom_context
->bios
+
262 adev
->clock
.default_sclk
=
263 le32_to_cpu(firmware_info
->v31
.bootup_sclk_in10khz
);
264 adev
->clock
.default_mclk
=
265 le32_to_cpu(firmware_info
->v31
.bootup_mclk_in10khz
);
267 adev
->pm
.current_sclk
= adev
->clock
.default_sclk
;
268 adev
->pm
.current_mclk
= adev
->clock
.default_mclk
;
270 /* not technically a clock, but... */
271 adev
->mode_info
.firmware_flags
=
272 le32_to_cpu(firmware_info
->v31
.firmware_capability
);
277 index
= get_index_into_master_table(atom_master_list_of_data_tables_v2_1
,
279 if (amdgpu_atom_parse_data_header(mode_info
->atom_context
, index
, NULL
,
280 &frev
, &crev
, &data_offset
)) {
281 union smu_info
*smu_info
=
282 (union smu_info
*)(mode_info
->atom_context
->bios
+
286 spll
->reference_freq
= le32_to_cpu(smu_info
->v31
.core_refclk_10khz
);
288 spll
->reference_div
= 0;
289 spll
->min_post_div
= 1;
290 spll
->max_post_div
= 1;
291 spll
->min_ref_div
= 2;
292 spll
->max_ref_div
= 0xff;
293 spll
->min_feedback_div
= 4;
294 spll
->max_feedback_div
= 0xff;
300 index
= get_index_into_master_table(atom_master_list_of_data_tables_v2_1
,
302 if (amdgpu_atom_parse_data_header(mode_info
->atom_context
, index
, NULL
,
303 &frev
, &crev
, &data_offset
)) {
304 union umc_info
*umc_info
=
305 (union umc_info
*)(mode_info
->atom_context
->bios
+
309 mpll
->reference_freq
= le32_to_cpu(umc_info
->v31
.mem_refclk_10khz
);
311 mpll
->reference_div
= 0;
312 mpll
->min_post_div
= 1;
313 mpll
->max_post_div
= 1;
314 mpll
->min_ref_div
= 2;
315 mpll
->max_ref_div
= 0xff;
316 mpll
->min_feedback_div
= 4;
317 mpll
->max_feedback_div
= 0xff;
327 struct atom_gfx_info_v2_4 v24
;
330 int amdgpu_atomfirmware_get_gfx_info(struct amdgpu_device
*adev
)
332 struct amdgpu_mode_info
*mode_info
= &adev
->mode_info
;
335 uint16_t data_offset
;
337 index
= get_index_into_master_table(atom_master_list_of_data_tables_v2_1
,
339 if (amdgpu_atom_parse_data_header(mode_info
->atom_context
, index
, NULL
,
340 &frev
, &crev
, &data_offset
)) {
341 union gfx_info
*gfx_info
= (union gfx_info
*)
342 (mode_info
->atom_context
->bios
+ data_offset
);
345 adev
->gfx
.config
.max_shader_engines
= gfx_info
->v24
.gc_num_se
;
346 adev
->gfx
.config
.max_cu_per_sh
= gfx_info
->v24
.gc_num_cu_per_sh
;
347 adev
->gfx
.config
.max_sh_per_se
= gfx_info
->v24
.gc_num_sh_per_se
;
348 adev
->gfx
.config
.max_backends_per_se
= gfx_info
->v24
.gc_num_rb_per_se
;
349 adev
->gfx
.config
.max_texture_channel_caches
= gfx_info
->v24
.gc_num_tccs
;
350 adev
->gfx
.config
.max_gprs
= le16_to_cpu(gfx_info
->v24
.gc_num_gprs
);
351 adev
->gfx
.config
.max_gs_threads
= gfx_info
->v24
.gc_num_max_gs_thds
;
352 adev
->gfx
.config
.gs_vgt_table_depth
= gfx_info
->v24
.gc_gs_table_depth
;
353 adev
->gfx
.config
.gs_prim_buffer_depth
=
354 le16_to_cpu(gfx_info
->v24
.gc_gsprim_buff_depth
);
355 adev
->gfx
.config
.double_offchip_lds_buf
=
356 gfx_info
->v24
.gc_double_offchip_lds_buffer
;
357 adev
->gfx
.cu_info
.wave_front_size
= le16_to_cpu(gfx_info
->v24
.gc_wave_size
);
358 adev
->gfx
.cu_info
.max_waves_per_simd
= le16_to_cpu(gfx_info
->v24
.gc_max_waves_per_simd
);
359 adev
->gfx
.cu_info
.max_scratch_slots_per_cu
= gfx_info
->v24
.gc_max_scratch_slots_per_cu
;
360 adev
->gfx
.cu_info
.lds_size
= le16_to_cpu(gfx_info
->v24
.gc_lds_size
);