diff options
Diffstat (limited to 'drivers/gpu/drm/amd/amdgpu/amdgpu_atomfirmware.c')
-rw-r--r-- | drivers/gpu/drm/amd/amdgpu/amdgpu_atomfirmware.c | 112 |
1 files changed, 112 insertions, 0 deletions
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_atomfirmware.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_atomfirmware.c new file mode 100644 index 000000000000..4b9abd68e04f --- /dev/null +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_atomfirmware.c | |||
@@ -0,0 +1,112 @@ | |||
1 | /* | ||
2 | * Copyright 2016 Advanced Micro Devices, Inc. | ||
3 | * | ||
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: | ||
10 | * | ||
11 | * The above copyright notice and this permission notice shall be included in | ||
12 | * all copies or substantial portions of the Software. | ||
13 | * | ||
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. | ||
21 | * | ||
22 | */ | ||
23 | #include <drm/drmP.h> | ||
24 | #include <drm/amdgpu_drm.h> | ||
25 | #include "amdgpu.h" | ||
26 | #include "atomfirmware.h" | ||
27 | #include "amdgpu_atomfirmware.h" | ||
28 | #include "atom.h" | ||
29 | |||
30 | #define get_index_into_master_table(master_table, table_name) (offsetof(struct master_table, table_name) / sizeof(uint16_t)) | ||
31 | |||
32 | bool amdgpu_atomfirmware_gpu_supports_virtualization(struct amdgpu_device *adev) | ||
33 | { | ||
34 | int index = get_index_into_master_table(atom_master_list_of_data_tables_v2_1, | ||
35 | firmwareinfo); | ||
36 | uint16_t data_offset; | ||
37 | |||
38 | if (amdgpu_atom_parse_data_header(adev->mode_info.atom_context, index, NULL, | ||
39 | NULL, NULL, &data_offset)) { | ||
40 | struct atom_firmware_info_v3_1 *firmware_info = | ||
41 | (struct atom_firmware_info_v3_1 *)(adev->mode_info.atom_context->bios + | ||
42 | data_offset); | ||
43 | |||
44 | if (le32_to_cpu(firmware_info->firmware_capability) & | ||
45 | ATOM_FIRMWARE_CAP_GPU_VIRTUALIZATION) | ||
46 | return true; | ||
47 | } | ||
48 | return false; | ||
49 | } | ||
50 | |||
51 | void amdgpu_atomfirmware_scratch_regs_init(struct amdgpu_device *adev) | ||
52 | { | ||
53 | int index = get_index_into_master_table(atom_master_list_of_data_tables_v2_1, | ||
54 | firmwareinfo); | ||
55 | uint16_t data_offset; | ||
56 | |||
57 | if (amdgpu_atom_parse_data_header(adev->mode_info.atom_context, index, NULL, | ||
58 | NULL, NULL, &data_offset)) { | ||
59 | struct atom_firmware_info_v3_1 *firmware_info = | ||
60 | (struct atom_firmware_info_v3_1 *)(adev->mode_info.atom_context->bios + | ||
61 | data_offset); | ||
62 | |||
63 | adev->bios_scratch_reg_offset = | ||
64 | le32_to_cpu(firmware_info->bios_scratch_reg_startaddr); | ||
65 | } | ||
66 | } | ||
67 | |||
68 | void amdgpu_atomfirmware_scratch_regs_save(struct amdgpu_device *adev) | ||
69 | { | ||
70 | int i; | ||
71 | |||
72 | for (i = 0; i < AMDGPU_BIOS_NUM_SCRATCH; i++) | ||
73 | adev->bios_scratch[i] = RREG32(adev->bios_scratch_reg_offset + i); | ||
74 | } | ||
75 | |||
76 | void amdgpu_atomfirmware_scratch_regs_restore(struct amdgpu_device *adev) | ||
77 | { | ||
78 | int i; | ||
79 | |||
80 | for (i = 0; i < AMDGPU_BIOS_NUM_SCRATCH; i++) | ||
81 | WREG32(adev->bios_scratch_reg_offset + i, adev->bios_scratch[i]); | ||
82 | } | ||
83 | |||
84 | int amdgpu_atomfirmware_allocate_fb_scratch(struct amdgpu_device *adev) | ||
85 | { | ||
86 | struct atom_context *ctx = adev->mode_info.atom_context; | ||
87 | int index = get_index_into_master_table(atom_master_list_of_data_tables_v2_1, | ||
88 | vram_usagebyfirmware); | ||
89 | uint16_t data_offset; | ||
90 | int usage_bytes = 0; | ||
91 | |||
92 | if (amdgpu_atom_parse_data_header(ctx, index, NULL, NULL, NULL, &data_offset)) { | ||
93 | struct vram_usagebyfirmware_v2_1 *firmware_usage = | ||
94 | (struct vram_usagebyfirmware_v2_1 *)(ctx->bios + data_offset); | ||
95 | |||
96 | DRM_DEBUG("atom firmware requested %08x %dkb fw %dkb drv\n", | ||
97 | le32_to_cpu(firmware_usage->start_address_in_kb), | ||
98 | le16_to_cpu(firmware_usage->used_by_firmware_in_kb), | ||
99 | le16_to_cpu(firmware_usage->used_by_driver_in_kb)); | ||
100 | |||
101 | usage_bytes = le16_to_cpu(firmware_usage->used_by_driver_in_kb) * 1024; | ||
102 | } | ||
103 | ctx->scratch_size_bytes = 0; | ||
104 | if (usage_bytes == 0) | ||
105 | usage_bytes = 20 * 1024; | ||
106 | /* allocate some scratch memory */ | ||
107 | ctx->scratch = kzalloc(usage_bytes, GFP_KERNEL); | ||
108 | if (!ctx->scratch) | ||
109 | return -ENOMEM; | ||
110 | ctx->scratch_size_bytes = usage_bytes; | ||
111 | return 0; | ||
112 | } | ||