2 * Copyright 2012 Red Hat Inc.
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:
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
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.
24 #include <core/subdev.h>
25 #include <core/device.h>
26 #include <core/option.h>
27 #include <subdev/mc.h>
30 nvkm_subdev_type[NVKM_SUBDEV_NR] = {
31 #define NVKM_LAYOUT_ONCE(type,data,ptr,...) [type] = #ptr,
32 #define NVKM_LAYOUT_INST(A...) NVKM_LAYOUT_ONCE(A)
33 #include <core/layout.h>
34 #undef NVKM_LAYOUT_ONCE
35 #undef NVKM_LAYOUT_INST
36 [NVKM_ENGINE_MSVLD ] = "msvld",
37 [NVKM_ENGINE_NVENC0 ] = "nvenc0",
38 [NVKM_ENGINE_NVENC1 ] = "nvenc1",
39 [NVKM_ENGINE_NVENC2 ] = "nvenc2",
40 [NVKM_ENGINE_NVDEC0 ] = "nvdec0",
41 [NVKM_ENGINE_NVDEC1 ] = "nvdec1",
42 [NVKM_ENGINE_NVDEC2 ] = "nvdec2",
43 [NVKM_ENGINE_PM ] = "pm",
44 [NVKM_ENGINE_SEC ] = "sec",
45 [NVKM_ENGINE_SEC2 ] = "sec2",
46 [NVKM_ENGINE_SW ] = "sw",
47 [NVKM_ENGINE_VIC ] = "vic",
51 nvkm_subdev_intr(struct nvkm_subdev *subdev)
53 if (subdev->func->intr)
54 subdev->func->intr(subdev);
58 nvkm_subdev_info(struct nvkm_subdev *subdev, u64 mthd, u64 *data)
60 if (subdev->func->info)
61 return subdev->func->info(subdev, mthd, data);
66 nvkm_subdev_fini(struct nvkm_subdev *subdev, bool suspend)
68 struct nvkm_device *device = subdev->device;
69 const char *action = suspend ? "suspend" : "fini";
72 nvkm_trace(subdev, "%s running...\n", action);
73 time = ktime_to_us(ktime_get());
75 if (subdev->func->fini) {
76 int ret = subdev->func->fini(subdev, suspend);
78 nvkm_error(subdev, "%s failed, %d\n", action, ret);
84 nvkm_mc_reset(device, subdev->type, subdev->inst);
86 time = ktime_to_us(ktime_get()) - time;
87 nvkm_trace(subdev, "%s completed in %lldus\n", action, time);
92 nvkm_subdev_preinit(struct nvkm_subdev *subdev)
96 nvkm_trace(subdev, "preinit running...\n");
97 time = ktime_to_us(ktime_get());
99 if (subdev->func->preinit) {
100 int ret = subdev->func->preinit(subdev);
102 nvkm_error(subdev, "preinit failed, %d\n", ret);
107 time = ktime_to_us(ktime_get()) - time;
108 nvkm_trace(subdev, "preinit completed in %lldus\n", time);
113 nvkm_subdev_init(struct nvkm_subdev *subdev)
118 nvkm_trace(subdev, "init running...\n");
119 time = ktime_to_us(ktime_get());
121 if (subdev->func->oneinit && !subdev->oneinit) {
123 nvkm_trace(subdev, "one-time init running...\n");
124 time = ktime_to_us(ktime_get());
125 ret = subdev->func->oneinit(subdev);
127 nvkm_error(subdev, "one-time init failed, %d\n", ret);
131 subdev->oneinit = true;
132 time = ktime_to_us(ktime_get()) - time;
133 nvkm_trace(subdev, "one-time init completed in %lldus\n", time);
136 if (subdev->func->init) {
137 ret = subdev->func->init(subdev);
139 nvkm_error(subdev, "init failed, %d\n", ret);
144 time = ktime_to_us(ktime_get()) - time;
145 nvkm_trace(subdev, "init completed in %lldus\n", time);
150 nvkm_subdev_del(struct nvkm_subdev **psubdev)
152 struct nvkm_subdev *subdev = *psubdev;
155 if (subdev && !WARN_ON(!subdev->func)) {
156 nvkm_trace(subdev, "destroy running...\n");
157 time = ktime_to_us(ktime_get());
158 list_del(&subdev->head);
159 if (subdev->func->dtor)
160 *psubdev = subdev->func->dtor(subdev);
161 time = ktime_to_us(ktime_get()) - time;
162 nvkm_trace(subdev, "destroy completed in %lldus\n", time);
169 nvkm_subdev_disable(struct nvkm_device *device, enum nvkm_subdev_type type, int inst)
171 struct nvkm_subdev *subdev;
172 list_for_each_entry(subdev, &device->subdev, head) {
173 if (subdev->type == type && subdev->inst == inst) {
174 *subdev->pself = NULL;
175 nvkm_subdev_del(&subdev);
182 nvkm_subdev_ctor_(const struct nvkm_subdev_func *func, bool old,
183 struct nvkm_device *device, enum nvkm_subdev_type type, int inst,
184 struct nvkm_subdev *subdev)
187 subdev->device = device;
189 subdev->inst = inst < 0 ? 0 : inst;
190 subdev->index = type + subdev->inst;
193 switch (subdev->type) {
194 case NVKM_ENGINE_NVENC0 ... NVKM_ENGINE_NVENC_LAST:
195 subdev->type = NVKM_ENGINE_NVENC;
196 subdev->inst = subdev->index - NVKM_ENGINE_NVENC0;
198 case NVKM_ENGINE_NVDEC0 ... NVKM_ENGINE_NVDEC_LAST:
199 subdev->type = NVKM_ENGINE_NVDEC;
200 subdev->inst = subdev->index - NVKM_ENGINE_NVDEC0;
209 snprintf(subdev->name, sizeof(subdev->name), "%s%d", nvkm_subdev_type[type], inst);
211 strscpy(subdev->name, nvkm_subdev_type[type], sizeof(subdev->name));
212 subdev->debug = nvkm_dbgopt(device->dbgopt, subdev->name);
213 list_add_tail(&subdev->head, &device->subdev);
217 nvkm_subdev_new_(const struct nvkm_subdev_func *func, struct nvkm_device *device,
218 enum nvkm_subdev_type type, int inst, struct nvkm_subdev **psubdev)
220 if (!(*psubdev = kzalloc(sizeof(**psubdev), GFP_KERNEL)))
222 nvkm_subdev_ctor(func, device, type, inst, *psubdev);