Linux Audio

Check our new training course

Loading...
v4.6
  1/*
  2 * Copyright 2012 Red Hat Inc.
  3 *
  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:
 10 *
 11 * The above copyright notice and this permission notice shall be included in
 12 * all copies or substantial portions of the Software.
 13 *
 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.
 21 *
 22 * Authors: Ben Skeggs
 23 */
 24#include <core/subdev.h>
 25#include <core/device.h>
 26#include <core/option.h>
 27
 28static struct lock_class_key nvkm_subdev_lock_class[NVKM_SUBDEV_NR];
 29
 30const char *
 31nvkm_subdev_name[NVKM_SUBDEV_NR] = {
 32	[NVKM_SUBDEV_BAR     ] = "bar",
 33	[NVKM_SUBDEV_VBIOS   ] = "bios",
 34	[NVKM_SUBDEV_BUS     ] = "bus",
 35	[NVKM_SUBDEV_CLK     ] = "clk",
 36	[NVKM_SUBDEV_DEVINIT ] = "devinit",
 37	[NVKM_SUBDEV_FB      ] = "fb",
 38	[NVKM_SUBDEV_FUSE    ] = "fuse",
 39	[NVKM_SUBDEV_GPIO    ] = "gpio",
 40	[NVKM_SUBDEV_I2C     ] = "i2c",
 41	[NVKM_SUBDEV_IBUS    ] = "priv",
 42	[NVKM_SUBDEV_ICCSENSE] = "iccsense",
 43	[NVKM_SUBDEV_INSTMEM ] = "imem",
 44	[NVKM_SUBDEV_LTC     ] = "ltc",
 45	[NVKM_SUBDEV_MC      ] = "mc",
 46	[NVKM_SUBDEV_MMU     ] = "mmu",
 47	[NVKM_SUBDEV_MXM     ] = "mxm",
 48	[NVKM_SUBDEV_PCI     ] = "pci",
 49	[NVKM_SUBDEV_PMU     ] = "pmu",
 50	[NVKM_SUBDEV_SECBOOT ] = "secboot",
 51	[NVKM_SUBDEV_THERM   ] = "therm",
 52	[NVKM_SUBDEV_TIMER   ] = "tmr",
 53	[NVKM_SUBDEV_VOLT    ] = "volt",
 54	[NVKM_ENGINE_BSP     ] = "bsp",
 55	[NVKM_ENGINE_CE0     ] = "ce0",
 56	[NVKM_ENGINE_CE1     ] = "ce1",
 57	[NVKM_ENGINE_CE2     ] = "ce2",
 58	[NVKM_ENGINE_CIPHER  ] = "cipher",
 59	[NVKM_ENGINE_DISP    ] = "disp",
 60	[NVKM_ENGINE_DMAOBJ  ] = "dma",
 61	[NVKM_ENGINE_FIFO    ] = "fifo",
 62	[NVKM_ENGINE_GR      ] = "gr",
 63	[NVKM_ENGINE_IFB     ] = "ifb",
 64	[NVKM_ENGINE_ME      ] = "me",
 65	[NVKM_ENGINE_MPEG    ] = "mpeg",
 66	[NVKM_ENGINE_MSENC   ] = "msenc",
 67	[NVKM_ENGINE_MSPDEC  ] = "mspdec",
 68	[NVKM_ENGINE_MSPPP   ] = "msppp",
 69	[NVKM_ENGINE_MSVLD   ] = "msvld",
 70	[NVKM_ENGINE_NVENC0  ] = "nvenc0",
 71	[NVKM_ENGINE_NVENC1  ] = "nvenc1",
 72	[NVKM_ENGINE_NVDEC   ] = "nvdec",
 73	[NVKM_ENGINE_PM      ] = "pm",
 74	[NVKM_ENGINE_SEC     ] = "sec",
 75	[NVKM_ENGINE_SW      ] = "sw",
 76	[NVKM_ENGINE_VIC     ] = "vic",
 77	[NVKM_ENGINE_VP      ] = "vp",
 78};
 79
 80void
 81nvkm_subdev_intr(struct nvkm_subdev *subdev)
 82{
 83	if (subdev->func->intr)
 84		subdev->func->intr(subdev);
 85}
 86
 87int
 
 
 
 
 
 
 
 
 88nvkm_subdev_fini(struct nvkm_subdev *subdev, bool suspend)
 89{
 90	struct nvkm_device *device = subdev->device;
 91	const char *action = suspend ? "suspend" : "fini";
 92	u32 pmc_enable = subdev->pmc_enable;
 93	s64 time;
 94
 95	nvkm_trace(subdev, "%s running...\n", action);
 96	time = ktime_to_us(ktime_get());
 97
 98	if (subdev->func->fini) {
 99		int ret = subdev->func->fini(subdev, suspend);
100		if (ret) {
101			nvkm_error(subdev, "%s failed, %d\n", action, ret);
102			if (suspend)
103				return ret;
104		}
105	}
 
106
107	if (pmc_enable) {
108		nvkm_mask(device, 0x000200, pmc_enable, 0x00000000);
109		nvkm_mask(device, 0x000200, pmc_enable, pmc_enable);
110		nvkm_rd32(device, 0x000200);
111	}
112
113	time = ktime_to_us(ktime_get()) - time;
114	nvkm_trace(subdev, "%s completed in %lldus\n", action, time);
115	return 0;
116}
117
118int
119nvkm_subdev_preinit(struct nvkm_subdev *subdev)
120{
121	s64 time;
122
123	nvkm_trace(subdev, "preinit running...\n");
124	time = ktime_to_us(ktime_get());
125
126	if (subdev->func->preinit) {
127		int ret = subdev->func->preinit(subdev);
128		if (ret) {
129			nvkm_error(subdev, "preinit failed, %d\n", ret);
130			return ret;
131		}
132	}
133
134	time = ktime_to_us(ktime_get()) - time;
135	nvkm_trace(subdev, "preinit completed in %lldus\n", time);
136	return 0;
137}
138
139int
140nvkm_subdev_init(struct nvkm_subdev *subdev)
141{
142	s64 time;
143	int ret;
144
145	nvkm_trace(subdev, "init running...\n");
 
 
 
146	time = ktime_to_us(ktime_get());
 
 
 
 
 
147
148	if (subdev->func->oneinit && !subdev->oneinit) {
149		s64 time;
150		nvkm_trace(subdev, "one-time init running...\n");
151		time = ktime_to_us(ktime_get());
152		ret = subdev->func->oneinit(subdev);
153		if (ret) {
154			nvkm_error(subdev, "one-time init failed, %d\n", ret);
155			return ret;
156		}
157
158		subdev->oneinit = true;
159		time = ktime_to_us(ktime_get()) - time;
160		nvkm_trace(subdev, "one-time init completed in %lldus\n", time);
 
 
 
 
 
 
161	}
162
 
 
 
 
 
 
 
 
 
163	if (subdev->func->init) {
164		ret = subdev->func->init(subdev);
165		if (ret) {
166			nvkm_error(subdev, "init failed, %d\n", ret);
167			return ret;
168		}
169	}
170
171	time = ktime_to_us(ktime_get()) - time;
172	nvkm_trace(subdev, "init completed in %lldus\n", time);
173	return 0;
174}
175
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
176void
177nvkm_subdev_del(struct nvkm_subdev **psubdev)
178{
179	struct nvkm_subdev *subdev = *psubdev;
180	s64 time;
181
182	if (subdev && !WARN_ON(!subdev->func)) {
183		nvkm_trace(subdev, "destroy running...\n");
184		time = ktime_to_us(ktime_get());
 
185		if (subdev->func->dtor)
186			*psubdev = subdev->func->dtor(subdev);
 
187		time = ktime_to_us(ktime_get()) - time;
188		nvkm_trace(subdev, "destroy completed in %lldus\n", time);
189		kfree(*psubdev);
190		*psubdev = NULL;
191	}
192}
193
194void
195nvkm_subdev_ctor(const struct nvkm_subdev_func *func,
196		 struct nvkm_device *device, int index, u32 pmc_enable,
197		 struct nvkm_subdev *subdev)
 
 
 
 
 
 
 
 
 
 
 
 
198{
199	const char *name = nvkm_subdev_name[index];
200	subdev->func = func;
201	subdev->device = device;
202	subdev->index = index;
203	subdev->pmc_enable = pmc_enable;
204
205	__mutex_init(&subdev->mutex, name, &nvkm_subdev_lock_class[index]);
206	subdev->debug = nvkm_dbgopt(device->dbgopt, name);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
207}
v6.8
  1/*
  2 * Copyright 2012 Red Hat Inc.
  3 *
  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:
 10 *
 11 * The above copyright notice and this permission notice shall be included in
 12 * all copies or substantial portions of the Software.
 13 *
 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.
 21 *
 22 * Authors: Ben Skeggs
 23 */
 24#include <core/subdev.h>
 25#include <core/device.h>
 26#include <core/option.h>
 27#include <subdev/mc.h>
 
 28
 29const char *
 30nvkm_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};
 37
 38void
 39nvkm_subdev_intr(struct nvkm_subdev *subdev)
 40{
 41	if (subdev->func->intr)
 42		subdev->func->intr(subdev);
 43}
 44
 45int
 46nvkm_subdev_info(struct nvkm_subdev *subdev, u64 mthd, u64 *data)
 47{
 48	if (subdev->func->info)
 49		return subdev->func->info(subdev, mthd, data);
 50	return -ENOSYS;
 51}
 52
 53int
 54nvkm_subdev_fini(struct nvkm_subdev *subdev, bool suspend)
 55{
 56	struct nvkm_device *device = subdev->device;
 57	const char *action = suspend ? "suspend" : subdev->use.enabled ? "fini" : "reset";
 
 58	s64 time;
 59
 60	nvkm_trace(subdev, "%s running...\n", action);
 61	time = ktime_to_us(ktime_get());
 62
 63	if (subdev->func->fini) {
 64		int ret = subdev->func->fini(subdev, suspend);
 65		if (ret) {
 66			nvkm_error(subdev, "%s failed, %d\n", action, ret);
 67			if (suspend)
 68				return ret;
 69		}
 70	}
 71	subdev->use.enabled = false;
 72
 73	nvkm_mc_reset(device, subdev->type, subdev->inst);
 
 
 
 
 74
 75	time = ktime_to_us(ktime_get()) - time;
 76	nvkm_trace(subdev, "%s completed in %lldus\n", action, time);
 77	return 0;
 78}
 79
 80int
 81nvkm_subdev_preinit(struct nvkm_subdev *subdev)
 82{
 83	s64 time;
 84
 85	nvkm_trace(subdev, "preinit running...\n");
 86	time = ktime_to_us(ktime_get());
 87
 88	if (subdev->func->preinit) {
 89		int ret = subdev->func->preinit(subdev);
 90		if (ret) {
 91			nvkm_error(subdev, "preinit failed, %d\n", ret);
 92			return ret;
 93		}
 94	}
 95
 96	time = ktime_to_us(ktime_get()) - time;
 97	nvkm_trace(subdev, "preinit completed in %lldus\n", time);
 98	return 0;
 99}
100
101static int
102nvkm_subdev_oneinit_(struct nvkm_subdev *subdev)
103{
104	s64 time;
105	int ret;
106
107	if (!subdev->func->oneinit || subdev->oneinit)
108		return 0;
109
110	nvkm_trace(subdev, "one-time init running...\n");
111	time = ktime_to_us(ktime_get());
112	ret = subdev->func->oneinit(subdev);
113	if (ret) {
114		nvkm_error(subdev, "one-time init failed, %d\n", ret);
115		return ret;
116	}
117
118	subdev->oneinit = true;
119	time = ktime_to_us(ktime_get()) - time;
120	nvkm_trace(subdev, "one-time init completed in %lldus\n", time);
121	return 0;
122}
 
 
 
 
123
124static int
125nvkm_subdev_init_(struct nvkm_subdev *subdev)
126{
127	s64 time;
128	int ret;
129
130	if (subdev->use.enabled) {
131		nvkm_trace(subdev, "init skipped, already running\n");
132		return 0;
133	}
134
135	nvkm_trace(subdev, "init running...\n");
136	time = ktime_to_us(ktime_get());
137
138	ret = nvkm_subdev_oneinit_(subdev);
139	if (ret)
140		return ret;
141
142	subdev->use.enabled = true;
143
144	if (subdev->func->init) {
145		ret = subdev->func->init(subdev);
146		if (ret) {
147			nvkm_error(subdev, "init failed, %d\n", ret);
148			return ret;
149		}
150	}
151
152	time = ktime_to_us(ktime_get()) - time;
153	nvkm_trace(subdev, "init completed in %lldus\n", time);
154	return 0;
155}
156
157int
158nvkm_subdev_init(struct nvkm_subdev *subdev)
159{
160	int ret;
161
162	mutex_lock(&subdev->use.mutex);
163	if (refcount_read(&subdev->use.refcount) == 0) {
164		nvkm_trace(subdev, "init skipped, no users\n");
165		mutex_unlock(&subdev->use.mutex);
166		return 0;
167	}
168
169	ret = nvkm_subdev_init_(subdev);
170	mutex_unlock(&subdev->use.mutex);
171	return ret;
172}
173
174int
175nvkm_subdev_oneinit(struct nvkm_subdev *subdev)
176{
177	int ret;
178
179	mutex_lock(&subdev->use.mutex);
180	ret = nvkm_subdev_oneinit_(subdev);
181	mutex_unlock(&subdev->use.mutex);
182	return ret;
183}
184
185void
186nvkm_subdev_unref(struct nvkm_subdev *subdev)
187{
188	if (refcount_dec_and_mutex_lock(&subdev->use.refcount, &subdev->use.mutex)) {
189		nvkm_subdev_fini(subdev, false);
190		mutex_unlock(&subdev->use.mutex);
191	}
192}
193
194int
195nvkm_subdev_ref(struct nvkm_subdev *subdev)
196{
197	int ret;
198
199	if (subdev && !refcount_inc_not_zero(&subdev->use.refcount)) {
200		mutex_lock(&subdev->use.mutex);
201		if (!refcount_inc_not_zero(&subdev->use.refcount)) {
202			if ((ret = nvkm_subdev_init_(subdev))) {
203				mutex_unlock(&subdev->use.mutex);
204				return ret;
205			}
206
207			refcount_set(&subdev->use.refcount, 1);
208		}
209		mutex_unlock(&subdev->use.mutex);
210	}
211
212	return 0;
213}
214
215void
216nvkm_subdev_del(struct nvkm_subdev **psubdev)
217{
218	struct nvkm_subdev *subdev = *psubdev;
219	s64 time;
220
221	if (subdev && !WARN_ON(!subdev->func)) {
222		nvkm_trace(subdev, "destroy running...\n");
223		time = ktime_to_us(ktime_get());
224		list_del(&subdev->head);
225		if (subdev->func->dtor)
226			*psubdev = subdev->func->dtor(subdev);
227		mutex_destroy(&subdev->use.mutex);
228		time = ktime_to_us(ktime_get()) - time;
229		nvkm_trace(subdev, "destroy completed in %lldus\n", time);
230		kfree(*psubdev);
231		*psubdev = NULL;
232	}
233}
234
235void
236nvkm_subdev_disable(struct nvkm_device *device, enum nvkm_subdev_type type, int inst)
237{
238	struct nvkm_subdev *subdev;
239	list_for_each_entry(subdev, &device->subdev, head) {
240		if (subdev->type == type && subdev->inst == inst) {
241			*subdev->pself = NULL;
242			nvkm_subdev_del(&subdev);
243			break;
244		}
245	}
246}
247
248void
249__nvkm_subdev_ctor(const struct nvkm_subdev_func *func, struct nvkm_device *device,
250		   enum nvkm_subdev_type type, int inst, struct nvkm_subdev *subdev)
251{
 
252	subdev->func = func;
253	subdev->device = device;
254	subdev->type = type;
255	subdev->inst = inst < 0 ? 0 : inst;
256
257	if (inst >= 0)
258		snprintf(subdev->name, sizeof(subdev->name), "%s%d", nvkm_subdev_type[type], inst);
259	else
260		strscpy(subdev->name, nvkm_subdev_type[type], sizeof(subdev->name));
261	subdev->debug = nvkm_dbgopt(device->dbgopt, subdev->name);
262
263	refcount_set(&subdev->use.refcount, 1);
264	list_add_tail(&subdev->head, &device->subdev);
265}
266
267int
268nvkm_subdev_new_(const struct nvkm_subdev_func *func, struct nvkm_device *device,
269		 enum nvkm_subdev_type type, int inst, struct nvkm_subdev **psubdev)
270{
271	if (!(*psubdev = kzalloc(sizeof(**psubdev), GFP_KERNEL)))
272		return -ENOMEM;
273	nvkm_subdev_ctor(func, device, type, inst, *psubdev);
274	return 0;
275}