]>
Commit | Line | Data |
---|---|---|
57312eaa SAK |
1 | /* |
2 | * SPDX-License-Identifier: MIT | |
3 | * | |
4 | * Copyright © 2014-2018 Intel Corporation | |
5 | */ | |
6 | ||
7 | #include "intel_huc_fw.h" | |
8 | #include "i915_drv.h" | |
9 | ||
10 | /** | |
11 | * DOC: HuC Firmware | |
12 | * | |
13 | * Motivation: | |
14 | * GEN9 introduces a new dedicated firmware for usage in media HEVC (High | |
15 | * Efficiency Video Coding) operations. Userspace can use the firmware | |
16 | * capabilities by adding HuC specific commands to batch buffers. | |
17 | * | |
18 | * Implementation: | |
19 | * The same firmware loader is used as the GuC. However, the actual | |
20 | * loading to HW is deferred until GEM initialization is done. | |
21 | * | |
22 | * Note that HuC firmware loading must be done before GuC loading. | |
23 | */ | |
24 | ||
25 | #define BXT_HUC_FW_MAJOR 01 | |
a49aa650 AS |
26 | #define BXT_HUC_FW_MINOR 8 |
27 | #define BXT_BLD_NUM 2893 | |
57312eaa SAK |
28 | |
29 | #define SKL_HUC_FW_MAJOR 01 | |
30 | #define SKL_HUC_FW_MINOR 07 | |
31 | #define SKL_BLD_NUM 1398 | |
32 | ||
33 | #define KBL_HUC_FW_MAJOR 02 | |
34 | #define KBL_HUC_FW_MINOR 00 | |
35 | #define KBL_BLD_NUM 1810 | |
36 | ||
37 | #define HUC_FW_PATH(platform, major, minor, bld_num) \ | |
38 | "i915/" __stringify(platform) "_huc_ver" __stringify(major) "_" \ | |
39 | __stringify(minor) "_" __stringify(bld_num) ".bin" | |
40 | ||
41 | #define I915_SKL_HUC_UCODE HUC_FW_PATH(skl, SKL_HUC_FW_MAJOR, \ | |
42 | SKL_HUC_FW_MINOR, SKL_BLD_NUM) | |
43 | MODULE_FIRMWARE(I915_SKL_HUC_UCODE); | |
44 | ||
45 | #define I915_BXT_HUC_UCODE HUC_FW_PATH(bxt, BXT_HUC_FW_MAJOR, \ | |
46 | BXT_HUC_FW_MINOR, BXT_BLD_NUM) | |
47 | MODULE_FIRMWARE(I915_BXT_HUC_UCODE); | |
48 | ||
49 | #define I915_KBL_HUC_UCODE HUC_FW_PATH(kbl, KBL_HUC_FW_MAJOR, \ | |
50 | KBL_HUC_FW_MINOR, KBL_BLD_NUM) | |
51 | MODULE_FIRMWARE(I915_KBL_HUC_UCODE); | |
52 | ||
53 | static void huc_fw_select(struct intel_uc_fw *huc_fw) | |
54 | { | |
55 | struct intel_huc *huc = container_of(huc_fw, struct intel_huc, fw); | |
56 | struct drm_i915_private *dev_priv = huc_to_i915(huc); | |
57 | ||
58 | GEM_BUG_ON(huc_fw->type != INTEL_UC_FW_TYPE_HUC); | |
59 | ||
60 | if (!HAS_HUC(dev_priv)) | |
61 | return; | |
62 | ||
63 | if (i915_modparams.huc_firmware_path) { | |
64 | huc_fw->path = i915_modparams.huc_firmware_path; | |
65 | huc_fw->major_ver_wanted = 0; | |
66 | huc_fw->minor_ver_wanted = 0; | |
67 | } else if (IS_SKYLAKE(dev_priv)) { | |
68 | huc_fw->path = I915_SKL_HUC_UCODE; | |
69 | huc_fw->major_ver_wanted = SKL_HUC_FW_MAJOR; | |
70 | huc_fw->minor_ver_wanted = SKL_HUC_FW_MINOR; | |
71 | } else if (IS_BROXTON(dev_priv)) { | |
72 | huc_fw->path = I915_BXT_HUC_UCODE; | |
73 | huc_fw->major_ver_wanted = BXT_HUC_FW_MAJOR; | |
74 | huc_fw->minor_ver_wanted = BXT_HUC_FW_MINOR; | |
75 | } else if (IS_KABYLAKE(dev_priv) || IS_COFFEELAKE(dev_priv)) { | |
76 | huc_fw->path = I915_KBL_HUC_UCODE; | |
77 | huc_fw->major_ver_wanted = KBL_HUC_FW_MAJOR; | |
78 | huc_fw->minor_ver_wanted = KBL_HUC_FW_MINOR; | |
57312eaa SAK |
79 | } |
80 | } | |
81 | ||
82 | /** | |
83 | * intel_huc_fw_init_early() - initializes HuC firmware struct | |
84 | * @huc: intel_huc struct | |
85 | * | |
86 | * On platforms with HuC selects firmware for uploading | |
87 | */ | |
88 | void intel_huc_fw_init_early(struct intel_huc *huc) | |
89 | { | |
90 | struct intel_uc_fw *huc_fw = &huc->fw; | |
91 | ||
92 | intel_uc_fw_init(huc_fw, INTEL_UC_FW_TYPE_HUC); | |
93 | huc_fw_select(huc_fw); | |
94 | } | |
95 | ||
96 | /** | |
97 | * huc_fw_xfer() - DMA's the firmware | |
98 | * @huc_fw: the firmware descriptor | |
99 | * @vma: the firmware image (bound into the GGTT) | |
100 | * | |
101 | * Transfer the firmware image to RAM for execution by the microcontroller. | |
102 | * | |
103 | * Return: 0 on success, non-zero on failure | |
104 | */ | |
105 | static int huc_fw_xfer(struct intel_uc_fw *huc_fw, struct i915_vma *vma) | |
106 | { | |
107 | struct intel_huc *huc = container_of(huc_fw, struct intel_huc, fw); | |
108 | struct drm_i915_private *dev_priv = huc_to_i915(huc); | |
d2d551c0 | 109 | struct intel_uncore *uncore = &dev_priv->uncore; |
57312eaa SAK |
110 | unsigned long offset = 0; |
111 | u32 size; | |
112 | int ret; | |
113 | ||
114 | GEM_BUG_ON(huc_fw->type != INTEL_UC_FW_TYPE_HUC); | |
115 | ||
d2d551c0 | 116 | intel_uncore_forcewake_get(uncore, FORCEWAKE_ALL); |
57312eaa SAK |
117 | |
118 | /* Set the source address for the uCode */ | |
3c009e3c JL |
119 | offset = intel_guc_ggtt_offset(&dev_priv->guc, vma) + |
120 | huc_fw->header_offset; | |
d2d551c0 DCS |
121 | intel_uncore_write(uncore, DMA_ADDR_0_LOW, |
122 | lower_32_bits(offset)); | |
123 | intel_uncore_write(uncore, DMA_ADDR_0_HIGH, | |
124 | upper_32_bits(offset) & 0xFFFF); | |
57312eaa | 125 | |
d2d551c0 DCS |
126 | /* |
127 | * Hardware doesn't look at destination address for HuC. Set it to 0, | |
57312eaa SAK |
128 | * but still program the correct address space. |
129 | */ | |
d2d551c0 DCS |
130 | intel_uncore_write(uncore, DMA_ADDR_1_LOW, 0); |
131 | intel_uncore_write(uncore, DMA_ADDR_1_HIGH, DMA_ADDRESS_SPACE_WOPCM); | |
57312eaa SAK |
132 | |
133 | size = huc_fw->header_size + huc_fw->ucode_size; | |
d2d551c0 | 134 | intel_uncore_write(uncore, DMA_COPY_SIZE, size); |
57312eaa SAK |
135 | |
136 | /* Start the DMA */ | |
d2d551c0 DCS |
137 | intel_uncore_write(uncore, DMA_CTRL, |
138 | _MASKED_BIT_ENABLE(HUC_UKERNEL | START_DMA)); | |
57312eaa SAK |
139 | |
140 | /* Wait for DMA to finish */ | |
d2d551c0 | 141 | ret = intel_wait_for_register_fw(uncore, DMA_CTRL, START_DMA, 0, 100); |
57312eaa SAK |
142 | |
143 | DRM_DEBUG_DRIVER("HuC DMA transfer wait over with ret %d\n", ret); | |
144 | ||
145 | /* Disable the bits once DMA is over */ | |
d2d551c0 | 146 | intel_uncore_write(uncore, DMA_CTRL, _MASKED_BIT_DISABLE(HUC_UKERNEL)); |
57312eaa | 147 | |
d2d551c0 | 148 | intel_uncore_forcewake_put(uncore, FORCEWAKE_ALL); |
57312eaa SAK |
149 | |
150 | return ret; | |
151 | } | |
152 | ||
153 | /** | |
154 | * intel_huc_fw_upload() - load HuC uCode to device | |
155 | * @huc: intel_huc structure | |
156 | * | |
157 | * Called from intel_uc_init_hw() during driver load, resume from sleep and | |
158 | * after a GPU reset. Note that HuC must be loaded before GuC. | |
159 | * | |
8c650aef MW |
160 | * The firmware image should have already been fetched into memory, so only |
161 | * check that fetch succeeded, and then transfer the image to the h/w. | |
57312eaa SAK |
162 | * |
163 | * Return: non-zero code on error | |
164 | */ | |
165 | int intel_huc_fw_upload(struct intel_huc *huc) | |
166 | { | |
167 | return intel_uc_fw_upload(&huc->fw, huc_fw_xfer); | |
168 | } |