.. | .. |
---|
24 | 24 | #include "gf100.h" |
---|
25 | 25 | #include "ram.h" |
---|
26 | 26 | |
---|
| 27 | +#include <core/firmware.h> |
---|
27 | 28 | #include <core/memory.h> |
---|
| 29 | +#include <nvfw/fw.h> |
---|
| 30 | +#include <nvfw/hs.h> |
---|
| 31 | +#include <engine/nvdec.h> |
---|
| 32 | + |
---|
| 33 | +int |
---|
| 34 | +gp102_fb_vpr_scrub(struct nvkm_fb *fb) |
---|
| 35 | +{ |
---|
| 36 | + struct nvkm_subdev *subdev = &fb->subdev; |
---|
| 37 | + struct nvkm_device *device = subdev->device; |
---|
| 38 | + struct nvkm_falcon *falcon = &device->nvdec[0]->falcon; |
---|
| 39 | + struct nvkm_blob *blob = &fb->vpr_scrubber; |
---|
| 40 | + const struct nvfw_bin_hdr *hsbin_hdr; |
---|
| 41 | + const struct nvfw_hs_header *fw_hdr; |
---|
| 42 | + const struct nvfw_hs_load_header *lhdr; |
---|
| 43 | + void *scrub_data; |
---|
| 44 | + u32 patch_loc, patch_sig; |
---|
| 45 | + int ret; |
---|
| 46 | + |
---|
| 47 | + nvkm_falcon_get(falcon, subdev); |
---|
| 48 | + |
---|
| 49 | + hsbin_hdr = nvfw_bin_hdr(subdev, blob->data); |
---|
| 50 | + fw_hdr = nvfw_hs_header(subdev, blob->data + hsbin_hdr->header_offset); |
---|
| 51 | + lhdr = nvfw_hs_load_header(subdev, blob->data + fw_hdr->hdr_offset); |
---|
| 52 | + scrub_data = blob->data + hsbin_hdr->data_offset; |
---|
| 53 | + |
---|
| 54 | + patch_loc = *(u32 *)(blob->data + fw_hdr->patch_loc); |
---|
| 55 | + patch_sig = *(u32 *)(blob->data + fw_hdr->patch_sig); |
---|
| 56 | + if (falcon->debug) { |
---|
| 57 | + memcpy(scrub_data + patch_loc, |
---|
| 58 | + blob->data + fw_hdr->sig_dbg_offset + patch_sig, |
---|
| 59 | + fw_hdr->sig_dbg_size); |
---|
| 60 | + } else { |
---|
| 61 | + memcpy(scrub_data + patch_loc, |
---|
| 62 | + blob->data + fw_hdr->sig_prod_offset + patch_sig, |
---|
| 63 | + fw_hdr->sig_prod_size); |
---|
| 64 | + } |
---|
| 65 | + |
---|
| 66 | + nvkm_falcon_reset(falcon); |
---|
| 67 | + nvkm_falcon_bind_context(falcon, NULL); |
---|
| 68 | + |
---|
| 69 | + nvkm_falcon_load_imem(falcon, scrub_data, lhdr->non_sec_code_off, |
---|
| 70 | + lhdr->non_sec_code_size, |
---|
| 71 | + lhdr->non_sec_code_off >> 8, 0, false); |
---|
| 72 | + nvkm_falcon_load_imem(falcon, scrub_data + lhdr->apps[0], |
---|
| 73 | + ALIGN(lhdr->apps[0], 0x100), |
---|
| 74 | + lhdr->apps[1], |
---|
| 75 | + lhdr->apps[0] >> 8, 0, true); |
---|
| 76 | + nvkm_falcon_load_dmem(falcon, scrub_data + lhdr->data_dma_base, 0, |
---|
| 77 | + lhdr->data_size, 0); |
---|
| 78 | + |
---|
| 79 | + nvkm_falcon_set_start_addr(falcon, 0x0); |
---|
| 80 | + nvkm_falcon_start(falcon); |
---|
| 81 | + |
---|
| 82 | + ret = nvkm_falcon_wait_for_halt(falcon, 500); |
---|
| 83 | + if (ret < 0) { |
---|
| 84 | + ret = -ETIMEDOUT; |
---|
| 85 | + goto end; |
---|
| 86 | + } |
---|
| 87 | + |
---|
| 88 | + /* put nvdec in clean state - without reset it will remain in HS mode */ |
---|
| 89 | + nvkm_falcon_reset(falcon); |
---|
| 90 | +end: |
---|
| 91 | + nvkm_falcon_put(falcon, subdev); |
---|
| 92 | + return ret; |
---|
| 93 | +} |
---|
| 94 | + |
---|
| 95 | +bool |
---|
| 96 | +gp102_fb_vpr_scrub_required(struct nvkm_fb *fb) |
---|
| 97 | +{ |
---|
| 98 | + struct nvkm_device *device = fb->subdev.device; |
---|
| 99 | + nvkm_wr32(device, 0x100cd0, 0x2); |
---|
| 100 | + return (nvkm_rd32(device, 0x100cd0) & 0x00000010) != 0; |
---|
| 101 | +} |
---|
28 | 102 | |
---|
29 | 103 | static const struct nvkm_fb_func |
---|
30 | 104 | gp102_fb = { |
---|
.. | .. |
---|
33 | 107 | .init = gp100_fb_init, |
---|
34 | 108 | .init_remapper = gp100_fb_init_remapper, |
---|
35 | 109 | .init_page = gm200_fb_init_page, |
---|
| 110 | + .vpr.scrub_required = gp102_fb_vpr_scrub_required, |
---|
| 111 | + .vpr.scrub = gp102_fb_vpr_scrub, |
---|
36 | 112 | .ram_new = gp100_ram_new, |
---|
37 | 113 | }; |
---|
38 | 114 | |
---|
39 | 115 | int |
---|
| 116 | +gp102_fb_new_(const struct nvkm_fb_func *func, struct nvkm_device *device, |
---|
| 117 | + int index, struct nvkm_fb **pfb) |
---|
| 118 | +{ |
---|
| 119 | + int ret = gf100_fb_new_(func, device, index, pfb); |
---|
| 120 | + if (ret) |
---|
| 121 | + return ret; |
---|
| 122 | + |
---|
| 123 | + nvkm_firmware_load_blob(&(*pfb)->subdev, "nvdec/scrubber", "", 0, |
---|
| 124 | + &(*pfb)->vpr_scrubber); |
---|
| 125 | + return 0; |
---|
| 126 | +} |
---|
| 127 | + |
---|
| 128 | +int |
---|
40 | 129 | gp102_fb_new(struct nvkm_device *device, int index, struct nvkm_fb **pfb) |
---|
41 | 130 | { |
---|
42 | | - return gf100_fb_new_(&gp102_fb, device, index, pfb); |
---|
| 131 | + return gp102_fb_new_(&gp102_fb, device, index, pfb); |
---|
43 | 132 | } |
---|
| 133 | + |
---|
| 134 | +MODULE_FIRMWARE("nvidia/gp102/nvdec/scrubber.bin"); |
---|
| 135 | +MODULE_FIRMWARE("nvidia/gp104/nvdec/scrubber.bin"); |
---|
| 136 | +MODULE_FIRMWARE("nvidia/gp106/nvdec/scrubber.bin"); |
---|
| 137 | +MODULE_FIRMWARE("nvidia/gp107/nvdec/scrubber.bin"); |
---|
| 138 | +MODULE_FIRMWARE("nvidia/gp108/nvdec/scrubber.bin"); |
---|