| .. | .. |
|---|
| 22 | 22 | #include <core/device.h> |
|---|
| 23 | 23 | #include <core/firmware.h> |
|---|
| 24 | 24 | |
|---|
| 25 | +int |
|---|
| 26 | +nvkm_firmware_load_name(const struct nvkm_subdev *subdev, const char *base, |
|---|
| 27 | + const char *name, int ver, const struct firmware **pfw) |
|---|
| 28 | +{ |
|---|
| 29 | + char path[64]; |
|---|
| 30 | + int ret; |
|---|
| 31 | + |
|---|
| 32 | + snprintf(path, sizeof(path), "%s%s", base, name); |
|---|
| 33 | + ret = nvkm_firmware_get(subdev, path, ver, pfw); |
|---|
| 34 | + if (ret < 0) |
|---|
| 35 | + return ret; |
|---|
| 36 | + |
|---|
| 37 | + return 0; |
|---|
| 38 | +} |
|---|
| 39 | + |
|---|
| 40 | +int |
|---|
| 41 | +nvkm_firmware_load_blob(const struct nvkm_subdev *subdev, const char *base, |
|---|
| 42 | + const char *name, int ver, struct nvkm_blob *blob) |
|---|
| 43 | +{ |
|---|
| 44 | + const struct firmware *fw; |
|---|
| 45 | + int ret; |
|---|
| 46 | + |
|---|
| 47 | + ret = nvkm_firmware_load_name(subdev, base, name, ver, &fw); |
|---|
| 48 | + if (ret == 0) { |
|---|
| 49 | + blob->data = kmemdup(fw->data, fw->size, GFP_KERNEL); |
|---|
| 50 | + blob->size = fw->size; |
|---|
| 51 | + nvkm_firmware_put(fw); |
|---|
| 52 | + if (!blob->data) |
|---|
| 53 | + return -ENOMEM; |
|---|
| 54 | + } |
|---|
| 55 | + |
|---|
| 56 | + return ret; |
|---|
| 57 | +} |
|---|
| 58 | + |
|---|
| 25 | 59 | /** |
|---|
| 26 | 60 | * nvkm_firmware_get - load firmware from the official nvidia/chip/ directory |
|---|
| 27 | | - * @device device that will use that firmware |
|---|
| 61 | + * @subdev subdevice that will use that firmware |
|---|
| 28 | 62 | * @fwname name of firmware file to load |
|---|
| 29 | 63 | * @fw firmware structure to load to |
|---|
| 30 | 64 | * |
|---|
| .. | .. |
|---|
| 32 | 66 | * Firmware files released by NVIDIA will always follow this format. |
|---|
| 33 | 67 | */ |
|---|
| 34 | 68 | int |
|---|
| 35 | | -nvkm_firmware_get(struct nvkm_device *device, const char *fwname, |
|---|
| 69 | +nvkm_firmware_get(const struct nvkm_subdev *subdev, const char *fwname, int ver, |
|---|
| 36 | 70 | const struct firmware **fw) |
|---|
| 37 | 71 | { |
|---|
| 72 | + struct nvkm_device *device = subdev->device; |
|---|
| 38 | 73 | char f[64]; |
|---|
| 39 | 74 | char cname[16]; |
|---|
| 40 | 75 | int i; |
|---|
| .. | .. |
|---|
| 48 | 83 | cname[i] = tolower(cname[i]); |
|---|
| 49 | 84 | } |
|---|
| 50 | 85 | |
|---|
| 51 | | - snprintf(f, sizeof(f), "nvidia/%s/%s.bin", cname, fwname); |
|---|
| 52 | | - return request_firmware(fw, f, device->dev); |
|---|
| 86 | + if (ver != 0) |
|---|
| 87 | + snprintf(f, sizeof(f), "nvidia/%s/%s-%d.bin", cname, fwname, ver); |
|---|
| 88 | + else |
|---|
| 89 | + snprintf(f, sizeof(f), "nvidia/%s/%s.bin", cname, fwname); |
|---|
| 90 | + |
|---|
| 91 | + if (!firmware_request_nowarn(fw, f, device->dev)) { |
|---|
| 92 | + nvkm_debug(subdev, "firmware \"%s\" loaded - %zu byte(s)\n", |
|---|
| 93 | + f, (*fw)->size); |
|---|
| 94 | + return 0; |
|---|
| 95 | + } |
|---|
| 96 | + |
|---|
| 97 | + nvkm_debug(subdev, "firmware \"%s\" unavailable\n", f); |
|---|
| 98 | + return -ENOENT; |
|---|
| 53 | 99 | } |
|---|
| 54 | 100 | |
|---|
| 55 | 101 | /** |
|---|