diff options
Diffstat (limited to 'drivers/gpu/drm/nouveau/include/nvkm/core/firmware.h')
-rw-r--r-- | drivers/gpu/drm/nouveau/include/nvkm/core/firmware.h | 77 |
1 files changed, 77 insertions, 0 deletions
diff --git a/drivers/gpu/drm/nouveau/include/nvkm/core/firmware.h b/drivers/gpu/drm/nouveau/include/nvkm/core/firmware.h new file mode 100644 index 000000000..d4e507e25 --- /dev/null +++ b/drivers/gpu/drm/nouveau/include/nvkm/core/firmware.h @@ -0,0 +1,77 @@ +/* SPDX-License-Identifier: MIT */ +#ifndef __NVKM_FIRMWARE_H__ +#define __NVKM_FIRMWARE_H__ +#include <core/memory.h> +#include <core/option.h> +#include <core/subdev.h> + +struct nvkm_firmware { + const struct nvkm_firmware_func { + enum nvkm_firmware_type { + NVKM_FIRMWARE_IMG_RAM, + NVKM_FIRMWARE_IMG_DMA, + } type; + } *func; + const char *name; + struct nvkm_device *device; + + int len; + u8 *img; + u64 phys; + + struct nvkm_firmware_mem { + struct nvkm_memory memory; + struct scatterlist sgl; + } mem; +}; + +int nvkm_firmware_ctor(const struct nvkm_firmware_func *, const char *name, struct nvkm_device *, + const void *ptr, int len, struct nvkm_firmware *); +void nvkm_firmware_dtor(struct nvkm_firmware *); + +int nvkm_firmware_get(const struct nvkm_subdev *, const char *fwname, int ver, + const struct firmware **); +void nvkm_firmware_put(const struct firmware *); + +int nvkm_firmware_load_blob(const struct nvkm_subdev *subdev, const char *path, + const char *name, int ver, struct nvkm_blob *); +int nvkm_firmware_load_name(const struct nvkm_subdev *subdev, const char *path, + const char *name, int ver, + const struct firmware **); + +#define nvkm_firmware_load(s,l,o,p...) ({ \ + struct nvkm_subdev *_s = (s); \ + const char *_opts = (o); \ + char _option[32]; \ + typeof(l[0]) *_list = (l), *_next, *_fwif = NULL; \ + int _ver, _fwv, _ret = 0; \ + \ + snprintf(_option, sizeof(_option), "Nv%sFw", _opts); \ + _ver = nvkm_longopt(_s->device->cfgopt, _option, -2); \ + if (_ver >= -1) { \ + for (_next = _list; !_fwif && _next->load; _next++) { \ + if (_next->version == _ver) \ + _fwif = _next; \ + } \ + _ret = _fwif ? 0 : -EINVAL; \ + } \ + \ + if (_ret == 0) { \ + snprintf(_option, sizeof(_option), "Nv%sFwVer", _opts); \ + _fwv = _fwif ? _fwif->version : -1; \ + _ver = nvkm_longopt(_s->device->cfgopt, _option, _fwv); \ + for (_next = _fwif ? _fwif : _list; _next->load; _next++) { \ + _fwv = (_ver >= 0) ? _ver : _next->version; \ + _ret = _next->load(p, _fwv, _next); \ + if (_ret == 0 || _ver >= 0) { \ + _fwif = _next; \ + break; \ + } \ + } \ + } \ + \ + if (_ret) \ + _fwif = ERR_PTR(_ret); \ + _fwif; \ +}) +#endif |